The PostHog Python SDK enables server-side event tracking, feature flag evaluation, and user identification for Python applications including Django, Flask, FastAPI, and more.
Installation
Install the PostHog Python library using pip:
Initialization
Import the library
from posthog import Posthog
Create a client instance
Initialize PostHog with your project API key and host from your project settings:posthog = Posthog(
project_api_key='<ph_project_token>',
host='<ph_client_api_host>'
)
Verify the connection
Send a test event to verify your setup:posthog.capture(
distinct_id='test_user',
event='test_event'
)
Check your Activity feed to confirm the event was received.
Django Integration: If you’re using Django, check out the Django integration guide for automatic middleware setup and request tracking.
Capturing Events
Basic Event Capture
Capture events with a distinct user ID and optional properties:
posthog.capture(
distinct_id='user_123',
event='button_clicked',
properties={
'button_name': 'signup',
'page': 'homepage'
}
)
Capture with Timestamp
Include a custom timestamp for historical events:
from datetime import datetime
posthog.capture(
distinct_id='user_123',
event='purchase_completed',
properties={'amount': 49.99},
timestamp=datetime(2024, 1, 15, 10, 30)
)
Batch Events
Events are automatically batched for performance. Flush manually when needed:
posthog.capture('user_123', 'event_1')
posthog.capture('user_123', 'event_2')
posthog.capture('user_123', 'event_3')
# Flush all pending events
posthog.flush()
Identifying Users
Set User Identity
Identify users with their unique ID and properties:
posthog.identify(
distinct_id='user_123',
properties={
'email': '[email protected]',
'name': 'Jane Doe',
'plan': 'premium',
'signup_date': '2024-01-01'
}
)
Update User Properties
Set or update properties for existing users:
posthog.set(
distinct_id='user_123',
properties={
'plan': 'enterprise',
'last_login': datetime.now().isoformat()
}
)
Set Once
Set properties only if they don’t already exist:
posthog.set_once(
distinct_id='user_123',
properties={
'first_visit': datetime.now().isoformat()
}
)
Feature Flags
Check if Flag is Enabled
if posthog.feature_enabled('new-dashboard', 'user_123'):
# Show new dashboard
render_new_dashboard()
else:
# Show old dashboard
render_old_dashboard()
Get Flag Value
For multivariate flags, get the variant value:
variant = posthog.get_feature_flag('experiment-button-color', 'user_123')
if variant == 'blue':
button_color = '#0000FF'
elif variant == 'green':
button_color = '#00FF00'
else:
button_color = '#FF0000' # default
Get Flag Payload
Retrieve JSON payloads attached to feature flags:
payload = posthog.get_feature_flag_payload(
'experiment-config',
'user_123'
)
print(payload) # {'theme': 'dark', 'maxItems': 10}
Include User Properties
Provide user properties for better flag targeting:
is_enabled = posthog.feature_enabled(
'premium-feature',
'user_123',
person_properties={
'plan': 'enterprise',
'country': 'US'
}
)
Get All Flags
Retrieve all feature flags for a user:
flags = posthog.get_all_flags('user_123')
print(flags) # {'flag-1': True, 'flag-2': 'variant-a', 'flag-3': False}
Group Analytics
Associate users with groups (companies, organizations, etc.):
# Identify a group
posthog.group_identify(
group_type='company',
group_key='company_id_123',
properties={
'name': 'Acme Corporation',
'plan': 'enterprise',
'employees': 500
}
)
# Capture event for a user in a group
posthog.capture(
distinct_id='user_123',
event='feature_used',
properties={'feature': 'advanced_analytics'},
groups={'company': 'company_id_123'}
)
Alias
Merge user identities when a user transitions from anonymous to identified:
# User was anonymous with ID 'anon_123'
# After signup, merge with permanent ID
posthog.alias(
previous_id='anon_123',
distinct_id='user_123'
)
Error Tracking
Capture Exceptions
try:
risky_operation()
except Exception as e:
posthog.capture_exception(
e,
distinct_id='user_123',
properties={'context': 'payment_processing'}
)
With Context Manager
with posthog.exception_autocapture(distinct_id='user_123'):
# Any exception here is automatically captured
process_payment()
Django Integration
For Django applications, use the Django-specific setup:
# settings.py
POSTHOG_API_KEY = '<ph_project_token>'
POSTHOG_HOST = '<ph_client_api_host>'
MIDDLEWARE = [
'posthog.middleware.PostHogMiddleware',
# ... other middleware
]
Flask Integration
from flask import Flask, request, session
from posthog import Posthog
app = Flask(__name__)
posthog = Posthog(
project_api_key='<ph_project_token>',
host='<ph_client_api_host>'
)
@app.route('/signup', methods=['POST'])
def signup():
user_id = create_user(request.form)
posthog.identify(
distinct_id=user_id,
properties={
'email': request.form['email'],
'name': request.form['name']
}
)
posthog.capture(
distinct_id=user_id,
event='user_signed_up',
properties={'source': 'web'}
)
return {'success': True}
FastAPI Integration
from fastapi import FastAPI, Depends
from posthog import Posthog
app = FastAPI()
posthog = Posthog(
project_api_key='<ph_project_token>',
host='<ph_client_api_host>'
)
@app.post('/api/purchase')
async def create_purchase(user_id: str, amount: float):
# Process purchase
purchase_id = process_payment(user_id, amount)
# Track event
posthog.capture(
distinct_id=user_id,
event='purchase_completed',
properties={
'amount': amount,
'purchase_id': purchase_id
}
)
return {'purchase_id': purchase_id}
Configuration Options
posthog = Posthog(
project_api_key='<ph_project_token>',
host='<ph_client_api_host>',
# Batch settings
max_batch_size=100, # Max events per batch
flush_at=20, # Flush after this many events
flush_interval=10, # Flush after this many seconds
# Performance
max_queue_size=10000, # Max queued events
send=True, # Set to False for testing
# Debugging
debug=True, # Enable debug logging
on_error=lambda e, batch: print(f'Error: {e}')
)
Shutdown
Always flush and close the client when your application shuts down:
import atexit
# Ensure events are sent before exit
atexit.register(posthog.shutdown)
# Or call manually
posthog.shutdown()
Testing
Disable sending events in tests:
import os
from posthog import Posthog
posthog = Posthog(
project_api_key='test_key',
host='https://app.posthog.com',
send=os.getenv('ENVIRONMENT') == 'production'
)
Or use a mock:
from unittest.mock import Mock
posthog = Mock()
posthog.capture('user_123', 'test_event')
posthog.capture.assert_called_once_with('user_123', 'test_event')
Best Practices
Use Environment Variables: Store your API key in environment variables, not in code.
Flush on Shutdown: Always call posthog.shutdown() or posthog.flush() before your application exits to ensure all events are sent.
Batch for Performance: The SDK automatically batches events. For high-volume applications, tune max_batch_size and flush_interval.
User Context: Include relevant user properties with identify() to enable better analytics and targeting.
Next Steps
Feature Flags
Learn advanced feature flag techniques
Django Integration
Full Django integration guide
API Reference
Complete Python SDK documentation
Group Analytics
Track B2B metrics by company or organization