PostHog makes it easy to get data about traffic and usage of your Django app. Integrating PostHog enables analytics, custom events capture, feature flags, and more.
This guide walks you through integrating PostHog into your Django app using the Python SDK.
Installation
To start, run pip install posthog
to install PostHog’s Python SDK.
Then, set the PostHog API key and host in your AppConfig
in your your_app/apps.py
so that's it's available everywhere:
from django.apps import AppConfigimport posthogclass YourAppConfig(AppConfig):name = "your_app_name"def ready(self):posthog.api_key = '<ph_project_api_key>'posthog.host = 'https://us.i.posthog.com'
You can find your project API key and instance address in your project settings.
Next, if you haven't done so already, make sure you add your AppConfig
to your settings.py
under INSTALLED_APPS
:
INSTALLED_APPS = [# other apps'your_app_name.apps.MyAppConfig', # Add your app config]
Lastly, to access PostHog in any file, simply import posthog
and call the method you'd like. For example, to capture an event:
import posthogdef some_request(request):with posthog.new_context():posthog.identify_context(request.user.id)posthog.capture('event_name')
Django contexts middleware
The Python SDK provides a Django middleware that automatically wraps all requests with a context. This middleware extracts session and user information from request headers and tags all events captured during the request with relevant metadata.
Basic setup
Add the middleware to your Django settings:
MIDDLEWARE = [# ... other middleware'posthog.integrations.django.PosthogContextMiddleware',# ... other middleware]
The middleware automatically extracts and uses:
- Session ID from the
X-POSTHOG-SESSION-ID
header, if present - Distinct ID from the
X-POSTHOG-DISTINCT-ID
header, if present - Current URL as
$current_url
- Request method as
$request_method
All events captured during the request (including exceptions) will include these properties and be associated with the extracted session and distinct ID.
If you are using PostHog on your frontend, the JavaScript Web SDK will add the session and distinct ID headers automatically if you enable tracing headers.
__add_tracing_headers: true
Exception capture
By default, the middleware captures exceptions and sends them to PostHog's error tracking. Disable this by setting:
# settings.pyPOSTHOG_MW_CAPTURE_EXCEPTIONS = False
Adding custom tags
Use POSTHOG_MW_EXTRA_TAGS
to add custom properties to all requests:
# settings.pydef add_user_tags(request):# type: (HttpRequest) -> Dict[str, Any]tags = {}if hasattr(request, 'user') and request.user.is_authenticated:tags['user_id'] = request.user.idtags['email'] = request.user.emailreturn tagsPOSTHOG_MW_EXTRA_TAGS = add_user_tags
Filtering requests
Skip tracking for certain requests using POSTHOG_MW_REQUEST_FILTER
:
# settings.pydef should_track_request(request):# type: (HttpRequest) -> bool# Don't track health checks or admin requestsif request.path.startswith('/health') or request.path.startswith('/admin'):return Falsereturn TruePOSTHOG_MW_REQUEST_FILTER = should_track_request
Modifying default tags
Use POSTHOG_MW_TAG_MAP
to modify or remove default tags:
# settings.pydef customize_tags(tags):# type: (Dict[str, Any]) -> Dict[str, Any]# Remove URL for privacytags.pop('$current_url', None)# Add custom prefix to methodif '$request_method' in tags:tags['http_method'] = tags.pop('$request_method')return tagsPOSTHOG_MW_TAG_MAP = customize_tags
Complete configuration example
# settings.pydef add_request_context(request):# type: (HttpRequest) -> Dict[str, Any]tags = {}if hasattr(request, 'user') and request.user.is_authenticated:tags['user_type'] = 'authenticated'tags['user_id'] = str(request.user.id)else:tags['user_type'] = 'anonymous'# Add request infotags['user_agent'] = request.META.get('HTTP_USER_AGENT', '')return tagsdef filter_tracking(request):# type: (HttpRequest) -> bool# Skip internal endpointsreturn not request.path.startswith(('/health', '/metrics', '/admin'))def clean_tags(tags):# type: (Dict[str, Any]) -> Dict[str, Any]# Remove sensitive datatags.pop('user_agent', None)return tagsPOSTHOG_MW_EXTRA_TAGS = add_request_contextPOSTHOG_MW_REQUEST_FILTER = filter_trackingPOSTHOG_MW_TAG_MAP = clean_tagsPOSTHOG_MW_CAPTURE_EXCEPTIONS = True
All events captured within the request context automatically include the configured tags and are associated with the session and user identified from the request headers.
Next steps
For any technical questions for how to integrate specific PostHog features into Django (such as analytics, feature flags, A/B testing, etc.), have a look at our Python SDK docs.
Alternatively, the following tutorials can help you get started: