Django

Last updated:

|Edit this page|

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:

your_app/apps.py
from django.apps import AppConfig
import posthog
class 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:

settings.py
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:

Python
import posthog
def 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:

Python
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.

JavaScript
__add_tracing_headers: true

Exception capture

By default, the middleware captures exceptions and sends them to PostHog's error tracking. Disable this by setting:

Python
# settings.py
POSTHOG_MW_CAPTURE_EXCEPTIONS = False

Adding custom tags

Use POSTHOG_MW_EXTRA_TAGS to add custom properties to all requests:

Python
# settings.py
def add_user_tags(request):
# type: (HttpRequest) -> Dict[str, Any]
tags = {}
if hasattr(request, 'user') and request.user.is_authenticated:
tags['user_id'] = request.user.id
tags['email'] = request.user.email
return tags
POSTHOG_MW_EXTRA_TAGS = add_user_tags

Filtering requests

Skip tracking for certain requests using POSTHOG_MW_REQUEST_FILTER:

Python
# settings.py
def should_track_request(request):
# type: (HttpRequest) -> bool
# Don't track health checks or admin requests
if request.path.startswith('/health') or request.path.startswith('/admin'):
return False
return True
POSTHOG_MW_REQUEST_FILTER = should_track_request

Modifying default tags

Use POSTHOG_MW_TAG_MAP to modify or remove default tags:

Python
# settings.py
def customize_tags(tags):
# type: (Dict[str, Any]) -> Dict[str, Any]
# Remove URL for privacy
tags.pop('$current_url', None)
# Add custom prefix to method
if '$request_method' in tags:
tags['http_method'] = tags.pop('$request_method')
return tags
POSTHOG_MW_TAG_MAP = customize_tags

Complete configuration example

Python
# settings.py
def 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 info
tags['user_agent'] = request.META.get('HTTP_USER_AGENT', '')
return tags
def filter_tracking(request):
# type: (HttpRequest) -> bool
# Skip internal endpoints
return not request.path.startswith(('/health', '/metrics', '/admin'))
def clean_tags(tags):
# type: (Dict[str, Any]) -> Dict[str, Any]
# Remove sensitive data
tags.pop('user_agent', None)
return tags
POSTHOG_MW_EXTRA_TAGS = add_request_context
POSTHOG_MW_REQUEST_FILTER = filter_tracking
POSTHOG_MW_TAG_MAP = clean_tags
POSTHOG_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:

Questions? Ask Max AI.

It's easier than reading through 680 pages of documentation

Community questions

Was this page useful?

Next article

Docusaurus

To easily track your Docusaurus site, you can install the PostHog plugin . This enables you to autocapture pageviews, clicks, session replays, as well as use the other features of PostHog such as surveys . Install Once you have your Docusaurus site set up, install the PostHog plugin: or Next, add it to your Docusaurus config with your project API key and instance address, both of which you can find in your project settings . Run your site again to see events autocaptured by PostHog. Note…

Read next article