0
# Event Tracking
1
2
Core event capture functionality for tracking user actions, system events, and custom analytics data. PostHog's event tracking system supports rich properties, automatic context enrichment, and reliable delivery with batching and retry mechanisms.
3
4
## Capabilities
5
6
### Event Capture
7
8
Capture any user action or system event with optional properties, timestamps, and context information.
9
10
```python { .api }
11
def capture(event: str, **kwargs: OptionalCaptureArgs) -> Optional[str]:
12
"""
13
Capture anything a user does within your system.
14
15
Parameters:
16
- event: str - The event name to specify the event
17
- distinct_id: Optional[ID_TYPES] - Unique identifier for the user
18
- properties: Optional[Dict[str, Any]] - Dict of event properties
19
- timestamp: Optional[Union[datetime, str]] - When the event occurred
20
- uuid: Optional[str] - Unique identifier for this specific event
21
- groups: Optional[Dict[str, str]] - Dict of group types and IDs
22
- send_feature_flags: Optional[Union[bool, SendFeatureFlagsOptions]] - Whether to include active feature flags
23
- disable_geoip: Optional[bool] - Whether to disable GeoIP lookup
24
25
Returns:
26
Optional[str] - The event UUID if successful
27
"""
28
```
29
30
### Exception Capture
31
32
Automatically capture and track exceptions with full stack traces and context information.
33
34
```python { .api }
35
def capture_exception(exception: Optional[ExceptionArg] = None, **kwargs: OptionalCaptureArgs):
36
"""
37
Capture exceptions that happen in your code.
38
39
Parameters:
40
- exception: Optional[ExceptionArg] - The exception to capture. If not provided, captures current exception via sys.exc_info()
41
- All OptionalCaptureArgs parameters are supported
42
43
Notes:
44
- Idempotent - calling twice with same exception instance only tracks one occurrence
45
- Automatically captures stack traces between raise and capture points
46
- Context boundaries may truncate stack traces
47
"""
48
```
49
50
## Usage Examples
51
52
### Basic Event Tracking
53
54
```python
55
import posthog
56
57
# Configure PostHog
58
posthog.api_key = 'phc_your_project_api_key'
59
60
# Simple event
61
posthog.capture('user123', 'button_clicked')
62
63
# Event with properties
64
posthog.capture('user123', 'purchase_completed', {
65
'product_id': 'abc123',
66
'amount': 29.99,
67
'currency': 'USD',
68
'category': 'books'
69
})
70
71
# Event with groups
72
posthog.capture('user123', 'feature_used', {
73
'feature_name': 'advanced_search'
74
}, groups={'company': 'acme_corp'})
75
```
76
77
### Context-Based Event Tracking
78
79
```python
80
import posthog
81
82
# Using context for automatic user identification
83
with posthog.new_context():
84
posthog.identify_context('user123')
85
posthog.tag('session_type', 'premium')
86
87
# Event automatically includes user ID and tags
88
posthog.capture('page_viewed', {'page': 'dashboard'})
89
posthog.capture('button_clicked', {'button': 'export'})
90
91
# Override context user for specific event
92
posthog.capture('admin_action', {'action': 'user_reset'}, distinct_id='admin456')
93
```
94
95
### Exception Tracking
96
97
```python
98
import posthog
99
100
try:
101
risky_operation()
102
except ValueError as e:
103
# Capture specific exception
104
posthog.capture_exception(e, properties={'operation': 'data_processing'})
105
106
try:
107
another_operation()
108
except Exception:
109
# Capture current exception automatically
110
posthog.capture_exception(properties={'context': 'background_task'})
111
```
112
113
### Advanced Event Configuration
114
115
```python
116
import posthog
117
from datetime import datetime, timezone
118
119
# Event with timestamp and feature flags
120
posthog.capture(
121
'user123',
122
'api_call',
123
properties={
124
'endpoint': '/api/users',
125
'method': 'POST',
126
'response_time': 250
127
},
128
timestamp=datetime.now(timezone.utc),
129
send_feature_flags=True,
130
groups={'organization': 'org_456'}
131
)
132
133
# Event with custom UUID for deduplication
134
posthog.capture(
135
'user123',
136
'payment_processed',
137
properties={'transaction_id': 'txn_789'},
138
uuid='custom-event-uuid-123'
139
)
140
```
141
142
### Batching and Performance
143
144
```python
145
import posthog
146
147
# Configure batching behavior
148
posthog.flush_at = 50 # Send batch after 50 events
149
posthog.flush_interval = 2.0 # Send batch after 2 seconds
150
151
# Events are automatically batched
152
for i in range(100):
153
posthog.capture(f'user_{i}', 'bulk_event', {'index': i})
154
155
# Force flush remaining events
156
posthog.flush()
157
```
158
159
## Error Handling
160
161
### Event Validation
162
163
Events are validated before sending:
164
165
- Event names must be non-empty strings
166
- Properties must be JSON-serializable
167
- Distinct IDs are automatically generated if not provided
168
- Invalid data is logged and dropped
169
170
### Retry Behavior
171
172
Failed events are automatically retried:
173
174
- Exponential backoff for temporary failures
175
- Maximum retry attempts configurable
176
- Failed events are logged for debugging
177
- Network errors trigger automatic retries
178
179
### Offline Support
180
181
The SDK handles offline scenarios gracefully:
182
183
- Events are queued when network is unavailable
184
- Automatic retry when connection is restored
185
- Configurable queue size limits
186
- Events are persisted in memory queue
187
188
## Best Practices
189
190
### Event Naming
191
192
Use consistent, descriptive event names:
193
194
```python
195
# Good - verb + noun format
196
posthog.capture('user123', 'video_played')
197
posthog.capture('user123', 'purchase_completed')
198
posthog.capture('user123', 'signup_started')
199
200
# Avoid - unclear or inconsistent
201
posthog.capture('user123', 'click') # Too vague
202
posthog.capture('user123', 'VIDEO_PLAY') # Inconsistent case
203
```
204
205
### Property Structure
206
207
Keep properties flat and meaningful:
208
209
```python
210
# Good - flat structure with clear names
211
posthog.capture('user123', 'purchase_completed', {
212
'product_id': 'abc123',
213
'product_name': 'Premium Plan',
214
'amount': 29.99,
215
'currency': 'USD',
216
'payment_method': 'stripe'
217
})
218
219
# Avoid - nested objects are flattened
220
posthog.capture('user123', 'purchase', {
221
'product': { # This gets flattened
222
'id': 'abc123',
223
'name': 'Premium Plan'
224
}
225
})
226
```
227
228
### Context Usage
229
230
Use contexts for related event sequences:
231
232
```python
233
# Good - group related events in context
234
with posthog.new_context():
235
posthog.identify_context('user123')
236
posthog.tag('flow', 'onboarding')
237
238
posthog.capture('onboarding_started')
239
posthog.capture('form_step_completed', {'step': 1})
240
posthog.capture('form_step_completed', {'step': 2})
241
posthog.capture('onboarding_completed')
242
```