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
```