or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

company-management.mdevent-tracking.mdindex.mdjob-management.mdquery-autocompletion.mdsearch-filtering.mdtenant-management.md

event-tracking.mddocs/

0

# Event Tracking and Analytics

1

2

User interaction event tracking for improving search quality and providing analytics insights, including job views, applications, and other user behaviors with support for custom event metadata. The event system enables machine learning improvements and provides valuable insights into user engagement patterns.

3

4

## Capabilities

5

6

### Client Event Creation

7

8

Records user interaction events that help improve search quality and provide analytics insights for understanding user behavior and job performance.

9

10

```python { .api }

11

def create_client_event(self, parent: str, client_event: ClientEvent) -> ClientEvent:

12

"""

13

Records a client interaction event for analytics and search improvement.

14

15

Parameters:

16

- parent (str): Tenant resource name where event will be recorded

17

- client_event (ClientEvent): Event object with interaction details

18

19

Returns:

20

ClientEvent: Recorded event with server-generated metadata

21

22

Raises:

23

- InvalidArgument: Missing required fields or invalid event data

24

- PermissionDenied: Insufficient permissions to create events

25

"""

26

```

27

28

**Usage Example:**

29

30

```python

31

from google.cloud.talent import EventServiceClient, ClientEvent, JobEvent

32

from google.protobuf.timestamp_pb2 import Timestamp

33

from datetime import datetime

34

import uuid

35

36

client = EventServiceClient()

37

38

# Record a job view event

39

job_view_event = ClientEvent(

40

request_id="search-session-123",

41

event_id=str(uuid.uuid4()),

42

create_time=Timestamp(seconds=int(datetime.utcnow().timestamp())),

43

job_event=JobEvent(

44

type_=JobEvent.JobEventType.VIEW,

45

jobs=["projects/my-project/tenants/my-tenant/jobs/job-123"]

46

),

47

event_notes="User viewed job from search results page 1"

48

)

49

50

recorded_event = client.create_client_event(

51

parent="projects/my-project/tenants/my-tenant",

52

client_event=job_view_event

53

)

54

```

55

56

## Event Data Model

57

58

### Client Event

59

60

```python { .api }

61

class ClientEvent:

62

"""

63

User interaction event for analytics and search improvement.

64

"""

65

request_id: str = None # Unique request identifier linking to search requests

66

event_id: str = None # Unique event identifier (client-generated)

67

create_time: Timestamp = None # Event timestamp (client-generated)

68

job_event: JobEvent = None # Job-specific event details

69

event_notes: str = None # Additional event information (max 1000 chars)

70

```

71

72

### Job Event

73

74

```python { .api }

75

class JobEvent:

76

"""

77

Job-specific user interaction events with detailed behavioral tracking.

78

"""

79

type_: JobEventType = None # Type of job interaction

80

jobs: List[str] = None # Job resource names involved in event (max 500)

81

82

class JobEventType(Enum):

83

"""Types of job-related user interactions."""

84

JOB_EVENT_TYPE_UNSPECIFIED = 0

85

IMPRESSION = 1 # Job appeared in search results

86

VIEW = 2 # User viewed job details

87

VIEW_REDIRECT = 3 # User clicked through to external job posting

88

APPLICATION_START = 4 # User began job application process

89

APPLICATION_FINISH = 5 # User completed job application

90

APPLICATION_QUICK_SUBMISSION = 6 # User used quick/one-click application

91

APPLICATION_REDIRECT = 7 # User redirected to external application system

92

APPLICATION_START_FROM_SEARCH = 8 # Application started directly from search results

93

APPLICATION_REDIRECT_FROM_SEARCH = 9 # Application redirect directly from search results

94

APPLICATION_COMPANY_SUBMIT = 10 # Application submitted to company system

95

BOOKMARK = 11 # User bookmarked/saved job

96

NOTIFICATION = 12 # Push notification sent about job

97

HIRED = 13 # User was hired for this job

98

SENT_CV = 14 # User sent CV/resume for job

99

INTERVIEW_GRANTED = 15 # User granted interview for job

100

```

101

102

## Event Tracking Patterns

103

104

### Search Session Tracking

105

106

Track complete user search sessions with multiple events linked by request_id.

107

108

```python

109

import uuid

110

from datetime import datetime

111

112

# Generate session ID for tracking related events

113

session_id = f"search-session-{uuid.uuid4()}"

114

115

# 1. Record search impression events when jobs appear in results

116

for job_id in search_result_job_ids:

117

impression_event = ClientEvent(

118

request_id=session_id,

119

event_id=str(uuid.uuid4()),

120

create_time=Timestamp(seconds=int(datetime.utcnow().timestamp())),

121

job_event=JobEvent(

122

type_=JobEvent.JobEventType.IMPRESSION,

123

jobs=[job_id]

124

),

125

event_notes=f"Job appeared in search results position {position}"

126

)

127

client.create_client_event(parent=tenant_name, client_event=impression_event)

128

129

# 2. Record view events when user clicks on job details

130

view_event = ClientEvent(

131

request_id=session_id,

132

event_id=str(uuid.uuid4()),

133

create_time=Timestamp(seconds=int(datetime.utcnow().timestamp())),

134

job_event=JobEvent(

135

type_=JobEvent.JobEventType.VIEW,

136

jobs=["projects/my-project/tenants/my-tenant/jobs/job-456"]

137

),

138

event_notes="User clicked job title from search results"

139

)

140

client.create_client_event(parent=tenant_name, client_event=view_event)

141

142

# 3. Record application events when user applies

143

application_event = ClientEvent(

144

request_id=session_id,

145

event_id=str(uuid.uuid4()),

146

create_time=Timestamp(seconds=int(datetime.utcnow().timestamp())),

147

job_event=JobEvent(

148

type_=JobEvent.JobEventType.APPLICATION_START,

149

jobs=["projects/my-project/tenants/my-tenant/jobs/job-456"]

150

),

151

event_notes="User clicked apply button"

152

)

153

client.create_client_event(parent=tenant_name, client_event=application_event)

154

```

155

156

### Application Funnel Tracking

157

158

Track the complete application process from initial interest to hiring.

159

160

```python

161

def track_application_funnel(job_id: str, user_id: str):

162

"""Track complete application funnel for analytics."""

163

base_request_id = f"application-{user_id}-{job_id}"

164

165

# Application started

166

start_event = ClientEvent(

167

request_id=base_request_id,

168

event_id=str(uuid.uuid4()),

169

create_time=Timestamp(seconds=int(datetime.utcnow().timestamp())),

170

job_event=JobEvent(

171

type_=JobEvent.JobEventType.APPLICATION_START,

172

jobs=[job_id]

173

),

174

event_notes="User initiated application process"

175

)

176

client.create_client_event(parent=tenant_name, client_event=start_event)

177

178

# Application completed (call when form submitted)

179

def track_application_completion():

180

finish_event = ClientEvent(

181

request_id=base_request_id,

182

event_id=str(uuid.uuid4()),

183

create_time=Timestamp(seconds=int(datetime.utcnow().timestamp())),

184

job_event=JobEvent(

185

type_=JobEvent.JobEventType.APPLICATION_FINISH,

186

jobs=[job_id]

187

),

188

event_notes="User completed application form"

189

)

190

client.create_client_event(parent=tenant_name, client_event=finish_event)

191

192

# CV/Resume sent (call when resume uploaded/sent)

193

def track_cv_sent():

194

cv_event = ClientEvent(

195

request_id=base_request_id,

196

event_id=str(uuid.uuid4()),

197

create_time=Timestamp(seconds=int(datetime.utcnow.timestamp())),

198

job_event=JobEvent(

199

type_=JobEvent.JobEventType.SENT_CV,

200

jobs=[job_id]

201

),

202

event_notes="User resume sent to employer"

203

)

204

client.create_client_event(parent=tenant_name, client_event=cv_event)

205

206

return track_application_completion, track_cv_sent

207

```

208

209

### Batch Event Recording

210

211

For high-volume applications, consider batching events to reduce API calls.

212

213

```python

214

class EventBatcher:

215

def __init__(self, tenant_name: str, batch_size: int = 100):

216

self.tenant_name = tenant_name

217

self.batch_size = batch_size

218

self.pending_events = []

219

self.client = EventServiceClient()

220

221

def add_event(self, event: ClientEvent):

222

"""Add event to batch queue."""

223

self.pending_events.append(event)

224

225

if len(self.pending_events) >= self.batch_size:

226

self.flush()

227

228

def flush(self):

229

"""Send all pending events."""

230

for event in self.pending_events:

231

try:

232

self.client.create_client_event(

233

parent=self.tenant_name,

234

client_event=event

235

)

236

except Exception as e:

237

print(f"Failed to send event {event.event_id}: {e}")

238

239

self.pending_events.clear()

240

241

# Usage

242

batcher = EventBatcher("projects/my-project/tenants/my-tenant")

243

244

# Add events throughout user session

245

batcher.add_event(impression_event)

246

batcher.add_event(view_event)

247

batcher.add_event(application_event)

248

249

# Ensure all events are sent at session end

250

batcher.flush()

251

```

252

253

## Event Request and Response Types

254

255

### Event Service Requests

256

257

```python { .api }

258

class CreateClientEventRequest:

259

parent: str = None # Tenant resource name

260

client_event: ClientEvent = None # Event to record

261

```

262

263

### Event Analytics Integration

264

265

Events are processed by Google's machine learning systems to improve search quality and provide insights. While the API doesn't expose analytics directly, recorded events contribute to:

266

267

- **Search Ranking**: Jobs with higher engagement get better ranking

268

- **Query Understanding**: User interactions help improve query interpretation

269

- **Personalization**: Individual user preferences for future searches

270

- **Company Analytics**: Aggregate performance metrics for employers

271

272

## Event Metadata and Context

273

274

### Request Metadata Integration

275

276

Link events to search requests using RequestMetadata for enhanced analytics.

277

278

```python

279

from google.cloud.talent import RequestMetadata, DeviceInfo

280

281

# Create consistent request metadata for search and events

282

request_metadata = RequestMetadata(

283

domain="mycompany.com",

284

session_id="user-session-789",

285

user_id="user-12345",

286

device_info=DeviceInfo(

287

device_type=DeviceInfo.DeviceType.WEB,

288

id="device-id-browser-123"

289

)

290

)

291

292

# Use same session_id in events

293

event = ClientEvent(

294

request_id="user-session-789", # Match search session

295

event_id=str(uuid.uuid4()),

296

# ... other event fields

297

)

298

```

299

300

### Custom Event Notes

301

302

Use event_notes field to provide additional context for analytics and debugging.

303

304

```python

305

# Include contextual information in event notes

306

event_notes_examples = [

307

"Job clicked from search results position 3",

308

"Application started from job detail page",

309

"Quick apply used - LinkedIn integration",

310

"User bookmarked job for later review",

311

"Push notification opened leading to job view",

312

"Email campaign click-through to job posting"

313

]

314

315

event = ClientEvent(

316

# ... other fields

317

event_notes="User applied after viewing job description for 2+ minutes"

318

)

319

```

320

321

## Error Handling

322

323

Event tracking operations can raise several types of exceptions:

324

325

```python

326

from google.api_core import exceptions

327

import logging

328

329

def safe_track_event(client: EventServiceClient, parent: str, event: ClientEvent):

330

"""Safely track event with error handling."""

331

try:

332

return client.create_client_event(parent=parent, client_event=event)

333

except exceptions.InvalidArgument as e:

334

logging.error(f"Invalid event data: {e}")

335

# Handle validation errors - check required fields

336

except exceptions.PermissionDenied as e:

337

logging.error(f"Event tracking permission denied: {e}")

338

# Handle authorization errors

339

except exceptions.ResourceExhausted as e:

340

logging.warning(f"Event tracking quota exceeded: {e}")

341

# Handle quota limits - consider backing off

342

except exceptions.DeadlineExceeded as e:

343

logging.warning(f"Event tracking timeout: {e}")

344

# Handle timeouts - retry or skip

345

except Exception as e:

346

logging.error(f"Unexpected event tracking error: {e}")

347

# Handle unexpected errors gracefully

348

349

return None # Event tracking failed but don't break user flow

350

```

351

352

Common error scenarios:

353

- **InvalidArgument**: Missing required fields (event_id, job_event), invalid timestamps

354

- **PermissionDenied**: Insufficient IAM permissions for event creation

355

- **ResourceExhausted**: Event tracking API quota limits exceeded

356

- **DeadlineExceeded**: Event submission timeout

357

358

## Best Practices

359

360

1. **Event Timing**: Record events as close to when they occur as possible for accuracy

361

2. **Unique IDs**: Always use unique event_id values to prevent duplicate event processing

362

3. **Session Linking**: Use consistent request_id values to link related events in a user session

363

4. **Error Handling**: Never let event tracking failures break the user experience

364

5. **Privacy**: Follow privacy laws and company policies when tracking user interactions

365

6. **Event Volume**: Consider batching for high-volume applications to manage API quotas

366

7. **Testing**: Implement event tracking testing to ensure data quality

367

8. **Monitoring**: Monitor event tracking success rates and API quota usage

368

369

## Common Integration Patterns

370

371

### React/JavaScript Frontend

372

373

```javascript

374

// Frontend event tracking integration

375

class TalentEventTracker {

376

constructor(sessionId) {

377

this.sessionId = sessionId;

378

this.eventQueue = [];

379

}

380

381

trackJobImpression(jobId, position) {

382

this.queueEvent({

383

type: 'IMPRESSION',

384

jobId: jobId,

385

metadata: { position: position }

386

});

387

}

388

389

trackJobView(jobId) {

390

this.queueEvent({

391

type: 'VIEW',

392

jobId: jobId,

393

metadata: { timestamp: Date.now() }

394

});

395

396

// Send immediately for important events

397

this.flush();

398

}

399

400

trackApplicationStart(jobId) {

401

this.queueEvent({

402

type: 'APPLICATION_START',

403

jobId: jobId,

404

metadata: { timestamp: Date.now() }

405

});

406

this.flush();

407

}

408

409

queueEvent(event) {

410

this.eventQueue.push({

411

...event,

412

sessionId: this.sessionId,

413

eventId: this.generateEventId()

414

});

415

}

416

417

async flush() {

418

if (this.eventQueue.length === 0) return;

419

420

try {

421

await fetch('/api/talent/events', {

422

method: 'POST',

423

headers: { 'Content-Type': 'application/json' },

424

body: JSON.stringify({

425

events: this.eventQueue.splice(0)

426

})

427

});

428

} catch (error) {

429

console.warn('Event tracking failed:', error);

430

}

431

}

432

433

generateEventId() {

434

return 'event_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);

435

}

436

}

437

```

438

439

### Analytics Dashboard Integration

440

441

```python

442

class TalentAnalytics:

443

"""Helper class for integrating with analytics dashboards."""

444

445

def __init__(self, tenant_name: str):

446

self.tenant_name = tenant_name

447

self.client = EventServiceClient()

448

449

def track_search_to_application_funnel(self, search_session_id: str, job_ids: List[str]):

450

"""Track complete search-to-application funnel."""

451

funnel_stages = [

452

(JobEvent.JobEventType.IMPRESSION, "Search results displayed"),

453

(JobEvent.JobEventType.VIEW, "Job details viewed"),

454

(JobEvent.JobEventType.APPLICATION_START, "Application process started"),

455

(JobEvent.JobEventType.APPLICATION_FINISH, "Application completed")

456

]

457

458

for stage_type, description in funnel_stages:

459

event = ClientEvent(

460

request_id=search_session_id,

461

event_id=str(uuid.uuid4()),

462

create_time=Timestamp(seconds=int(datetime.utcnow().timestamp())),

463

job_event=JobEvent(type_=stage_type, jobs=job_ids),

464

event_notes=description

465

)

466

467

self.client.create_client_event(

468

parent=self.tenant_name,

469

client_event=event

470

)

471

```