vybekiit 0.7.34 → 0.7.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +520 -9
- package/dist/global-skills/eas-app-stores/SKILL.md +2 -2
- package/dist/global-skills/eas-hosting/SKILL.md +2 -2
- package/dist/global-skills/eas-observe/SKILL.md +7 -15
- package/dist/global-skills/eas-observe/references/queries.md +51 -10
- package/dist/global-skills/eas-observe/references/setup.md +60 -7
- package/dist/global-skills/eas-simulator/SKILL.md +2 -2
- package/dist/global-skills/eas-simulator/references/run-your-app.md +2 -0
- package/dist/global-skills/eas-update/SKILL.md +2 -2
- package/dist/global-skills/eas-update-insights/SKILL.md +2 -2
- package/dist/global-skills/eas-workflows/SKILL.md +2 -2
- package/dist/global-skills/expo-animation/SKILL.md +2 -2
- package/dist/global-skills/expo-app-clip/SKILL.md +2 -2
- package/dist/global-skills/expo-brownfield/SKILL.md +2 -2
- package/dist/global-skills/expo-data-fetching/SKILL.md +2 -2
- package/dist/global-skills/expo-design-system/SKILL.md +2 -2
- package/dist/global-skills/expo-dev-client/SKILL.md +4 -2
- package/dist/global-skills/expo-dom/SKILL.md +2 -2
- package/dist/global-skills/expo-examples/SKILL.md +2 -2
- package/dist/global-skills/expo-migrate-module/SKILL.md +2 -2
- package/dist/global-skills/expo-module/SKILL.md +2 -2
- package/dist/global-skills/expo-native-ui/SKILL.md +2 -2
- package/dist/global-skills/expo-overview/SKILL.md +9 -4
- package/dist/global-skills/expo-overview/references/launch-without-dev-menu.md +24 -0
- package/dist/global-skills/expo-project-structure/SKILL.md +2 -2
- package/dist/global-skills/expo-router/SKILL.md +2 -2
- package/dist/global-skills/expo-ui/SKILL.md +2 -2
- package/dist/global-skills/expo-upgrade/SKILL.md +2 -2
- package/dist/global-skills/expo-web-to-native/SKILL.md +2 -2
- package/dist/global-skills/expo-web-to-native/references/verify-on-device.md +1 -1
- package/dist/global-skills/firebase-app-hosting-basics/SKILL.md +16 -3
- package/dist/global-skills/firebase-app-hosting-basics/references/cli_commands.md +10 -12
- package/dist/global-skills/firebase-app-hosting-basics/references/configuration.md +2 -1
- package/dist/global-skills/firebase-basics/SKILL.md +6 -4
- package/dist/global-skills/firebase-basics/references/web_setup.md +3 -3
- package/dist/global-skills/instrument-feature-flags/references/adding-feature-flag-code.md +81 -333
- package/dist/global-skills/instrument-feature-flags/references/android.md +19 -13
- package/dist/global-skills/instrument-feature-flags/references/api.md +17 -13
- package/dist/global-skills/instrument-feature-flags/references/best-practices.md +35 -35
- package/dist/global-skills/instrument-feature-flags/references/django.md +120 -72
- package/dist/global-skills/instrument-feature-flags/references/dotnet.md +48 -102
- package/dist/global-skills/instrument-feature-flags/references/elixir.md +4 -10
- package/dist/global-skills/instrument-feature-flags/references/flask.md +55 -39
- package/dist/global-skills/instrument-feature-flags/references/flutter.md +19 -13
- package/dist/global-skills/instrument-feature-flags/references/go.md +21 -13
- package/dist/global-skills/instrument-feature-flags/references/ios.md +19 -13
- package/dist/global-skills/instrument-feature-flags/references/java.md +4 -12
- package/dist/global-skills/instrument-feature-flags/references/laravel.md +18 -16
- package/dist/global-skills/instrument-feature-flags/references/next-js.md +44 -54
- package/dist/global-skills/instrument-feature-flags/references/nodejs.md +21 -13
- package/dist/global-skills/instrument-feature-flags/references/php.md +21 -13
- package/dist/global-skills/instrument-feature-flags/references/python.md +22 -14
- package/dist/global-skills/instrument-feature-flags/references/react-native.md +18 -13
- package/dist/global-skills/instrument-feature-flags/references/react.md +21 -14
- package/dist/global-skills/instrument-feature-flags/references/ruby-on-rails.md +31 -68
- package/dist/global-skills/instrument-feature-flags/references/ruby.md +21 -13
- package/dist/global-skills/instrument-feature-flags/references/rust.md +10 -34
- package/dist/global-skills/instrument-feature-flags/references/usage.md +94 -114
- package/dist/global-skills/instrument-feature-flags/references/web.md +21 -13
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-android.md +7 -7
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-expo.md +2 -2
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-fastapi.md +1 -1
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-flask.md +1 -1
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-laravel.md +2 -2
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-php.md +1 -1
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-python.md +1 -1
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-ruby.md +1 -1
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-swift.md +4 -4
- package/dist/global-skills/instrument-product-analytics/references/android.md +64 -109
- package/dist/global-skills/instrument-product-analytics/references/angular.md +32 -28
- package/dist/global-skills/instrument-product-analytics/references/astro.md +29 -34
- package/dist/global-skills/instrument-product-analytics/references/configuration.md +27 -42
- package/dist/global-skills/instrument-product-analytics/references/django.md +120 -72
- package/dist/global-skills/instrument-product-analytics/references/dotnet.md +48 -102
- package/dist/global-skills/instrument-product-analytics/references/elixir.md +25 -50
- package/dist/global-skills/instrument-product-analytics/references/flask.md +55 -39
- package/dist/global-skills/instrument-product-analytics/references/flutter.md +94 -96
- package/dist/global-skills/instrument-product-analytics/references/go.md +39 -77
- package/dist/global-skills/instrument-product-analytics/references/identify-users.md +24 -26
- package/dist/global-skills/instrument-product-analytics/references/ios.md +22 -22
- package/dist/global-skills/instrument-product-analytics/references/laravel.md +18 -16
- package/dist/global-skills/instrument-product-analytics/references/next-js.md +44 -54
- package/dist/global-skills/instrument-product-analytics/references/nuxt-js-3-6.md +32 -34
- package/dist/global-skills/instrument-product-analytics/references/nuxt-js.md +36 -36
- package/dist/global-skills/instrument-product-analytics/references/php.md +42 -87
- package/dist/global-skills/instrument-product-analytics/references/posthog-python.md +15 -12
- package/dist/global-skills/instrument-product-analytics/references/python.md +106 -154
- package/dist/global-skills/instrument-product-analytics/references/react-native.md +97 -176
- package/dist/global-skills/instrument-product-analytics/references/react-router-v6.md +29 -40
- package/dist/global-skills/instrument-product-analytics/references/react-router-v7-data-mode.md +29 -38
- package/dist/global-skills/instrument-product-analytics/references/react-router-v7-declarative-mode.md +29 -40
- package/dist/global-skills/instrument-product-analytics/references/react-router-v7-framework-mode.md +32 -37
- package/dist/global-skills/instrument-product-analytics/references/ruby-on-rails.md +31 -68
- package/dist/global-skills/instrument-product-analytics/references/ruby.md +40 -96
- package/dist/global-skills/instrument-product-analytics/references/svelte.md +34 -34
- package/dist/global-skills/instrument-product-analytics/references/tanstack-start.md +19 -19
- package/dist/global-skills/instrument-product-analytics/references/usage.md +94 -114
- package/dist/global-skills/instrument-product-analytics/references/vue-js.md +33 -45
- package/dist/global-skills/mongodb-search-and-ai/SKILL.md +40 -22
- package/dist/global-skills/mongodb-search-and-ai/references/automated-embedding.md +8 -2
- package/dist/global-skills/mongodb-search-and-ai/references/quick-start.md +725 -0
- package/dist/global-skills/mongodb-search-and-ai/scripts/quickstart_complete.py +386 -0
- package/dist/global-skills/neon/references/claimable-neon.md +2 -0
- package/dist/global-skills/neon-realtime/references/queries.md +2 -2
- package/dist/global-skills/resend/SKILL.md +1 -1
- package/dist/global-skills/resend/references/inboxes.md +49 -21
- package/dist/global-skills/resend/references/webhooks.md +1 -1
- package/dist/global-skills/stripe-best-practices/SKILL.md +1 -1
- package/dist/global-skills/stripe-best-practices/references/connect.md +1 -1
- package/dist/global-skills/stripe-best-practices/references/security.md +9 -9
- package/dist/global-skills/vybekiitReferences/backend/AGENTS.md +1 -1
- package/dist/global-skills/vybekiitReferences/backend/agent/goal-routes.json +303 -18
- package/dist/global-skills/vybekiitReferences/extension/AGENTS.md +1 -1
- package/dist/global-skills/vybekiitReferences/extension/agent/goal-routes.json +352 -18
- package/dist/global-skills/vybekiitReferences/mobile/AGENTS.md +1 -1
- package/dist/global-skills/vybekiitReferences/mobile/agent/goal-routes.json +413 -22
- package/dist/global-skills/vybekiitReferences/spa/AGENTS.md +1 -1
- package/dist/global-skills/vybekiitReferences/spa/agent/goal-routes.json +391 -21
- package/dist/global-skills/vybekiitReferences/web/AGENTS.md +14 -2
- package/dist/global-skills/vybekiitReferences/web/agent/goal-routes.json +490 -32
- package/package.json +8 -8
|
@@ -2,18 +2,29 @@
|
|
|
2
2
|
|
|
3
3
|
# Django
|
|
4
4
|
|
|
5
|
+
Canonical URL: https://posthog.com/docs/libraries/django
|
|
6
|
+
|
|
7
|
+
> **Cloud region:** This page uses US Cloud hosts. For an EU Cloud project, use `https://eu.i.posthog.com` instead of `https://us.i.posthog.com` (ingestion host), and use `https://eu.posthog.com` instead of `https://app.posthog.com` (app host for links).
|
|
8
|
+
|
|
9
|
+
## On this page
|
|
10
|
+
|
|
11
|
+
- [Beta: integration via LLM](#beta-integration-via-llm)
|
|
12
|
+
- [Installation](#installation)
|
|
13
|
+
- [Identifying users](#identifying-users)
|
|
14
|
+
- [Django contexts middleware](#django-contexts-middleware)
|
|
15
|
+
- [Next steps](#next-steps)
|
|
16
|
+
- [Supported versions](#supported-versions)
|
|
17
|
+
|
|
5
18
|
PostHog makes it easy to get data about traffic and usage of your Django app. Integrating PostHog enables analytics, custom events capture, feature flags, error tracking, and more.
|
|
6
19
|
|
|
7
|
-
This guide walks you through integrating PostHog into your Django app using the [Python SDK](/docs/libraries/python.md).
|
|
20
|
+
This guide walks you through integrating PostHog into your Django app using the [Python SDK](https://posthog.com/docs/libraries/python.md).
|
|
8
21
|
|
|
9
22
|
## Beta: integration via LLM
|
|
10
23
|
|
|
11
|
-
Install PostHog for Django in seconds with our wizard by running this prompt with [LLM coding agents](/blog/envoy-wizard-llm-agent.md) like Cursor and Bolt, or by running it in your terminal.
|
|
24
|
+
Install PostHog for Django in seconds with our wizard by running this prompt with [LLM coding agents](https://posthog.com/blog/envoy-wizard-llm-agent.md) like Cursor and Bolt, or by running it in your terminal.
|
|
12
25
|
|
|
13
26
|
`npx @posthog/wizard`
|
|
14
27
|
|
|
15
|
-
[Learn more](/wizard.md)
|
|
16
|
-
|
|
17
28
|
Or, to integrate manually, continue with the rest of this guide.
|
|
18
29
|
|
|
19
30
|
> These docs cover version `7.x` of the Python SDK, which requires Python 3.10 or higher. On Python 3.9? See [supported versions](#supported-versions).
|
|
@@ -53,8 +64,6 @@ You can find your project token and instance address in [your project settings](
|
|
|
53
64
|
|
|
54
65
|
To capture events from any file, import `posthog` and call the method you need. For example:
|
|
55
66
|
|
|
56
|
-
Python
|
|
57
|
-
|
|
58
67
|
```python
|
|
59
68
|
import posthog
|
|
60
69
|
from posthog import identify_context
|
|
@@ -69,7 +78,7 @@ def some_request(request):
|
|
|
69
78
|
posthog.capture('event_name')
|
|
70
79
|
```
|
|
71
80
|
|
|
72
|
-
Events captured without a context or explicit `distinct_id` are sent as [anonymous events](/docs/data/anonymous-vs-identified-events.md) with an auto-generated `distinct_id`. See the [Python SDK docs](/docs/libraries/python.md#person-profiles-and-properties) for more details.
|
|
81
|
+
Events captured without a context or explicit `distinct_id` are sent as [anonymous events](https://posthog.com/docs/data/anonymous-vs-identified-events.md) with an auto-generated `distinct_id`. See the [Python SDK docs](https://posthog.com/docs/libraries/python.md#person-profiles-and-properties) for more details.
|
|
73
82
|
|
|
74
83
|
## Identifying users
|
|
75
84
|
|
|
@@ -77,8 +86,6 @@ Events captured without a context or explicit `distinct_id` are sent as [anonymo
|
|
|
77
86
|
>
|
|
78
87
|
> In Python, you can do this through a context. All event captures in the same context will be tagged automatically with the correct `distinct_id`. Typically, you would set a fresh context and identify at the top of each route.
|
|
79
88
|
>
|
|
80
|
-
> Python
|
|
81
|
-
>
|
|
82
89
|
> ```python
|
|
83
90
|
> from posthog import new_context, identify_context, capture
|
|
84
91
|
>
|
|
@@ -94,18 +101,16 @@ Events captured without a context or explicit `distinct_id` are sent as [anonymo
|
|
|
94
101
|
|
|
95
102
|
## Django contexts middleware
|
|
96
103
|
|
|
97
|
-
The Python SDK provides a Django middleware that automatically wraps all requests with a [context](/docs/libraries/python.md#contexts). This middleware extracts session and user information from each request and
|
|
104
|
+
The Python SDK provides a Django middleware that automatically wraps all requests with a [context](https://posthog.com/docs/libraries/python.md#contexts). This middleware extracts session and user information from each request and adds relevant properties to events captured during that request.
|
|
98
105
|
|
|
99
106
|
### Basic setup
|
|
100
107
|
|
|
101
108
|
Add the middleware to your Django settings. If your app uses Django authentication, place it after `django.contrib.auth.middleware.AuthenticationMiddleware` so the middleware can use the authenticated Django user as a distinct ID fallback and capture the user's email.
|
|
102
109
|
|
|
103
|
-
Python
|
|
104
|
-
|
|
105
110
|
```python
|
|
106
111
|
MIDDLEWARE = [
|
|
107
112
|
# ... other middleware
|
|
108
|
-
|
|
113
|
+
"posthog.integrations.django.PosthogContextMiddleware",
|
|
109
114
|
# ... other middleware
|
|
110
115
|
]
|
|
111
116
|
```
|
|
@@ -114,8 +119,8 @@ The middleware uses the globally configured `posthog` client by default, so you
|
|
|
114
119
|
|
|
115
120
|
The middleware automatically extracts and uses:
|
|
116
121
|
|
|
117
|
-
- **Session ID** from the `X-POSTHOG-SESSION-ID` header
|
|
118
|
-
- **Distinct ID** from the
|
|
122
|
+
- **Session ID** from the `X-POSTHOG-SESSION-ID` header when you enable `POSTHOG_MW_TRUST_TRACING_HEADERS`
|
|
123
|
+
- **Distinct ID** from the authenticated Django user's `pk` (Django's primary-key alias, which works with custom user models), or from the `X-POSTHOG-DISTINCT-ID` header when you enable `POSTHOG_MW_TRUST_TRACING_HEADERS`
|
|
119
124
|
- **User email** from the authenticated Django user's `email` as `email`
|
|
120
125
|
- **Current URL** as `$current_url`
|
|
121
126
|
- **Request method** as `$request_method`
|
|
@@ -123,7 +128,14 @@ The middleware automatically extracts and uses:
|
|
|
123
128
|
- **Forwarded IP address** from `X-Forwarded-For` as `$ip`
|
|
124
129
|
- **User agent** from `User-Agent` as `$user_agent`
|
|
125
130
|
|
|
126
|
-
The session and distinct ID headers
|
|
131
|
+
The middleware ignores the session and distinct ID headers by default because clients can control them. To use them as analytics context, enable them in your Django settings:
|
|
132
|
+
|
|
133
|
+
```python
|
|
134
|
+
# settings.py
|
|
135
|
+
POSTHOG_MW_TRUST_TRACING_HEADERS = True
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Don't use these headers for authentication or authorization. The middleware sanitizes trusted header values before use. It ignores empty values, removes control characters, trims values, and caps them at 1000 characters.
|
|
127
139
|
|
|
128
140
|
All events captured during the request (including exceptions) include these properties and are associated with the extracted session and distinct ID.
|
|
129
141
|
|
|
@@ -133,8 +145,6 @@ The middleware reads `request.user` once, before your view runs. On a login or s
|
|
|
133
145
|
|
|
134
146
|
Identify the context from inside the request once you know who the user is. Django's auth signals are the natural place:
|
|
135
147
|
|
|
136
|
-
Python
|
|
137
|
-
|
|
138
148
|
```python
|
|
139
149
|
from django.contrib.auth.signals import user_logged_in
|
|
140
150
|
from django.dispatch import receiver
|
|
@@ -147,7 +157,7 @@ def identify_posthog_user(sender, request, user, **kwargs):
|
|
|
147
157
|
|
|
148
158
|
Every capture later in that request is then attributed to the user who just logged in. Requests made after login don't need this. The middleware sees the authenticated user from the start.
|
|
149
159
|
|
|
150
|
-
If you're using [PostHog JavaScript Web](/docs/libraries/js.md) on the frontend, configure [`tracing_headers`](/docs/libraries/js/config.md#tracing-headers) for your Django backend hostname so browser requests include the session and distinct ID headers.
|
|
160
|
+
If you're using [PostHog JavaScript Web](https://posthog.com/docs/libraries/js.md) on the frontend, configure [`tracing_headers`](https://posthog.com/docs/libraries/js/config.md#tracing-headers) for your Django backend hostname so browser requests include the session and distinct ID headers. You must also set `POSTHOG_MW_TRUST_TRACING_HEADERS = True` in Django to accept them.
|
|
151
161
|
|
|
152
162
|
### Exception capture
|
|
153
163
|
|
|
@@ -155,120 +165,166 @@ By default, the middleware captures exceptions and sends them to PostHog's error
|
|
|
155
165
|
|
|
156
166
|
Disable this by setting:
|
|
157
167
|
|
|
158
|
-
Python
|
|
159
|
-
|
|
160
168
|
```python
|
|
161
169
|
# settings.py
|
|
162
170
|
POSTHOG_MW_CAPTURE_EXCEPTIONS = False
|
|
163
171
|
```
|
|
164
172
|
|
|
165
|
-
|
|
173
|
+
Set `POSTHOG_MW_CAPTURE_EXCEPTIONS = None` to inherit the global client's `enable_exception_autocapture` setting. When you omit `POSTHOG_MW_CAPTURE_EXCEPTIONS`, the middleware preserves the existing Django default and captures exceptions.
|
|
174
|
+
|
|
175
|
+
### Capture Django REST Framework exceptions
|
|
166
176
|
|
|
167
|
-
|
|
177
|
+
This integration requires version `7.69.0` or later of the Python SDK.
|
|
168
178
|
|
|
169
|
-
|
|
179
|
+
Django REST Framework (DRF) converts many exceptions into responses before Django middleware can observe them. Add PostHog's DRF exception handler to capture these handled errors:
|
|
170
180
|
|
|
171
181
|
```python
|
|
172
182
|
# settings.py
|
|
173
|
-
|
|
183
|
+
REST_FRAMEWORK = {
|
|
184
|
+
# ... other DRF settings
|
|
185
|
+
"EXCEPTION_HANDLER": "posthog.integrations.drf.exception_handler",
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Keep `PosthogContextMiddleware` enabled. The middleware adds request properties and identity to the active context, while the DRF handler captures handled API exceptions. The handler captures responses with a `5xx` status by default and ignores expected `4xx` responses. If DRF doesn't handle an exception, Django re-raises it and the middleware captures it instead.
|
|
190
|
+
|
|
191
|
+
If you already use a custom DRF exception handler, wrap it in an application module:
|
|
192
|
+
|
|
193
|
+
```python
|
|
194
|
+
# your_app/exception_handlers.py
|
|
195
|
+
from posthog.integrations.drf import create_exception_handler
|
|
196
|
+
from your_app.api import existing_exception_handler
|
|
197
|
+
|
|
198
|
+
exception_handler = create_exception_handler(existing_exception_handler)
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Then point DRF to the wrapper:
|
|
202
|
+
|
|
203
|
+
```python
|
|
204
|
+
# settings.py
|
|
205
|
+
REST_FRAMEWORK = {
|
|
206
|
+
"EXCEPTION_HANDLER": "your_app.exception_handlers.exception_handler",
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
To capture selected `4xx` responses, create a handler with `capture_4xx=True` and an exception filter:
|
|
211
|
+
|
|
212
|
+
```python
|
|
213
|
+
# your_app/exception_handlers.py
|
|
214
|
+
from posthog.integrations.drf import create_exception_handler
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def capture_auth_errors(exception, response, context):
|
|
218
|
+
return response.status_code >= 500 or response.status_code in {401, 403}
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
exception_handler = create_exception_handler(
|
|
222
|
+
capture_4xx=True,
|
|
223
|
+
exception_filter=capture_auth_errors,
|
|
224
|
+
)
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
The DRF handler follows `POSTHOG_MW_CAPTURE_EXCEPTIONS` and `POSTHOG_MW_REQUEST_FILTER`. You can also pass `capture_exceptions=True` or `capture_exceptions=False` to `create_exception_handler()` to override the middleware setting.
|
|
228
|
+
|
|
229
|
+
### Add custom properties
|
|
230
|
+
|
|
231
|
+
Use `POSTHOG_MW_EXTRA_PROPERTIES` to add custom properties to all requests:
|
|
232
|
+
|
|
233
|
+
```python
|
|
234
|
+
# settings.py
|
|
235
|
+
def add_user_properties(request):
|
|
174
236
|
# type: (HttpRequest) -> Dict[str, Any]
|
|
175
|
-
|
|
176
|
-
if hasattr(request,
|
|
237
|
+
properties = {}
|
|
238
|
+
if hasattr(request, "user") and request.user.is_authenticated:
|
|
177
239
|
# Use pk instead of id so this works with custom User primary keys.
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
return
|
|
240
|
+
properties["user_id"] = str(request.user.pk)
|
|
241
|
+
properties["email"] = request.user.email
|
|
242
|
+
return properties
|
|
181
243
|
|
|
182
|
-
|
|
244
|
+
POSTHOG_MW_EXTRA_PROPERTIES = add_user_properties
|
|
183
245
|
```
|
|
184
246
|
|
|
185
|
-
|
|
247
|
+
### Filter requests
|
|
186
248
|
|
|
187
249
|
Skip tracking for certain requests using `POSTHOG_MW_REQUEST_FILTER`:
|
|
188
250
|
|
|
189
|
-
Python
|
|
190
|
-
|
|
191
251
|
```python
|
|
192
252
|
# settings.py
|
|
193
253
|
def should_track_request(request):
|
|
194
254
|
# type: (HttpRequest) -> bool
|
|
195
255
|
# Don't track health checks or admin requests
|
|
196
|
-
if request.path.startswith(
|
|
256
|
+
if request.path.startswith("/health") or request.path.startswith("/admin"):
|
|
197
257
|
return False
|
|
198
258
|
return True
|
|
199
259
|
|
|
200
260
|
POSTHOG_MW_REQUEST_FILTER = should_track_request
|
|
201
261
|
```
|
|
202
262
|
|
|
203
|
-
###
|
|
263
|
+
### Modify default properties
|
|
204
264
|
|
|
205
|
-
Use `
|
|
206
|
-
|
|
207
|
-
Python
|
|
265
|
+
Use `POSTHOG_MW_PROPERTIES_MAP` to modify or remove default properties:
|
|
208
266
|
|
|
209
267
|
```python
|
|
210
268
|
# settings.py
|
|
211
|
-
def
|
|
269
|
+
def customize_properties(properties):
|
|
212
270
|
# type: (Dict[str, Any]) -> Dict[str, Any]
|
|
213
271
|
# Remove URL for privacy
|
|
214
|
-
|
|
272
|
+
properties.pop("$current_url", None)
|
|
215
273
|
# Add custom prefix to method
|
|
216
|
-
if
|
|
217
|
-
|
|
218
|
-
return
|
|
274
|
+
if "$request_method" in properties:
|
|
275
|
+
properties["http_method"] = properties.pop("$request_method")
|
|
276
|
+
return properties
|
|
219
277
|
|
|
220
|
-
|
|
278
|
+
POSTHOG_MW_PROPERTIES_MAP = customize_properties
|
|
221
279
|
```
|
|
222
280
|
|
|
223
281
|
### Complete configuration example
|
|
224
282
|
|
|
225
|
-
Python
|
|
226
|
-
|
|
227
283
|
```python
|
|
228
284
|
# settings.py
|
|
229
285
|
def add_request_context(request):
|
|
230
286
|
# type: (HttpRequest) -> Dict[str, Any]
|
|
231
|
-
|
|
232
|
-
if hasattr(request,
|
|
233
|
-
|
|
287
|
+
properties = {}
|
|
288
|
+
if hasattr(request, "user") and request.user.is_authenticated:
|
|
289
|
+
properties["user_type"] = "authenticated"
|
|
234
290
|
# Use pk instead of id so this works with custom User primary keys.
|
|
235
|
-
|
|
291
|
+
properties["user_id"] = str(request.user.pk)
|
|
236
292
|
else:
|
|
237
|
-
|
|
293
|
+
properties["user_type"] = "anonymous"
|
|
238
294
|
|
|
239
295
|
# Add request info
|
|
240
|
-
|
|
241
|
-
return
|
|
296
|
+
properties["user_agent"] = request.META.get("HTTP_USER_AGENT", "")
|
|
297
|
+
return properties
|
|
242
298
|
|
|
243
299
|
def filter_tracking(request):
|
|
244
300
|
# type: (HttpRequest) -> bool
|
|
245
301
|
# Skip internal endpoints
|
|
246
|
-
return not request.path.startswith((
|
|
302
|
+
return not request.path.startswith(("/health", "/metrics", "/admin"))
|
|
247
303
|
|
|
248
|
-
def
|
|
304
|
+
def clean_properties(properties):
|
|
249
305
|
# type: (Dict[str, Any]) -> Dict[str, Any]
|
|
250
306
|
# Remove sensitive data
|
|
251
|
-
|
|
252
|
-
return
|
|
307
|
+
properties.pop("user_agent", None)
|
|
308
|
+
return properties
|
|
253
309
|
|
|
254
|
-
|
|
310
|
+
POSTHOG_MW_EXTRA_PROPERTIES = add_request_context
|
|
255
311
|
POSTHOG_MW_REQUEST_FILTER = filter_tracking
|
|
256
|
-
|
|
312
|
+
POSTHOG_MW_PROPERTIES_MAP = clean_properties
|
|
257
313
|
POSTHOG_MW_CAPTURE_EXCEPTIONS = True
|
|
258
314
|
```
|
|
259
315
|
|
|
260
|
-
All events captured within the request context automatically include the configured
|
|
316
|
+
All events captured within the request context automatically include the configured properties. They use the authenticated Django user as the distinct ID, or the session and distinct ID from request headers when you enable `POSTHOG_MW_TRUST_TRACING_HEADERS`.
|
|
261
317
|
|
|
262
318
|
The middleware supports both sync (WSGI) and async (ASGI) Django applications. In async mode, it uses Django's `request.auser()` API when available to avoid synchronous user access.
|
|
263
319
|
|
|
264
320
|
## Next steps
|
|
265
321
|
|
|
266
|
-
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](/docs/libraries/python.md).
|
|
322
|
+
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](https://posthog.com/docs/libraries/python.md).
|
|
267
323
|
|
|
268
324
|
Alternatively, the following tutorials can help you get started:
|
|
269
325
|
|
|
270
|
-
- [Setting up Django analytics, feature flags, and more](/tutorials/django-analytics.md)
|
|
271
|
-
- [How to set up A/B tests in Django](/tutorials/django-ab-tests.md)
|
|
326
|
+
- [Setting up Django analytics, feature flags, and more](https://posthog.com/tutorials/django-analytics.md)
|
|
327
|
+
- [How to set up A/B tests in Django](https://posthog.com/tutorials/django-ab-tests.md)
|
|
272
328
|
|
|
273
329
|
## Supported versions
|
|
274
330
|
|
|
@@ -277,11 +333,3 @@ These docs cover version `7.x` of the PostHog Python SDK, which requires Python
|
|
|
277
333
|
Everything on this page works the same way on `6.9.3`. Event capture, the context API (`new_context`, `identify_context`, `set_context_session`), and `PosthogContextMiddleware` are identical on `6.9.3` and `7.0.0` — `7.0.0` only dropped Python 3.9 and bumped the optional LLM provider SDKs. That includes the middleware identifying the request context from the `X-POSTHOG-DISTINCT-ID` header and falling back to the authenticated user, which behaves the same across both lines.
|
|
278
334
|
|
|
279
335
|
Later `7.x` releases add what the 6.x line does not receive, such as the Celery integration, tracing header sanitization, and `set_context_device_id`. They also changed the middleware's own captured properties: `7.x` sends the request IP as `$ip`, where `6.9.3` sends it as `$ip_address`, and `7.x` additionally captures `$request_path`, `$raw_user_agent`, and the authenticated user's `email`.
|
|
280
|
-
|
|
281
|
-
### Still have questions?
|
|
282
|
-
|
|
283
|
-
Ask PostHog AI
|
|
284
|
-
|
|
285
|
-
### Was this page useful?
|
|
286
|
-
|
|
287
|
-
HelpfulCould be better
|