NestJS
Contents
PostHog integrates with your NestJS app to enable analytics, custom events capture, Feature Flags, Error Tracking, and more.
This guide walks you through integrating PostHog with your NestJS app using the PostHogInterceptor, which provides automatic context propagation and optional exception capture.
Prerequisites
To follow this guide along, you need:
- A PostHog instance (either Cloud or self-hosted)
- A NestJS application (v8+)
Installation
Install the posthog-node package:
Setting up the interceptor
The PostHogInterceptor is a NestJS interceptor that automatically propagates context (session ID, distinct ID, request metadata) to all posthog.capture() calls within a request. It uses AsyncLocalStorage under the hood for per-request isolation.
In your main.ts, create a PostHog client and register the interceptor globally:
Context propagation
The interceptor reads the following headers from incoming requests and attaches them as context to all PostHog calls within that request:
| Header | Context property | Description |
|---|---|---|
x-posthog-session-id | sessionId | Links server events to a client session |
x-posthog-distinct-id | distinctId | Identifies you |
x-posthog-window-id | $window_id | Links to a specific browser tab |
It also automatically captures request metadata as properties:
$current_url– the request URL$request_method– the HTTP method (GET, POST, etc.)$request_path– the request path$user_agent– the user agent string$ip– the client IP (parsed fromx-forwarded-forif behind a proxy)
Sending headers from the client
If you're using PostHog JS on the frontend, configure __add_tracing_headers to automatically inject session and identity headers on every request to your NestJS backend:
This automatically adds X-POSTHOG-SESSION-ID and X-POSTHOG-DISTINCT-ID headers to all fetch and XMLHttpRequest calls to the specified hostnames. The PostHogInterceptor reads these headers automatically.
Capturing events in controllers
With the interceptor active, any posthog.capture() call within a request automatically includes the propagated context:
Error Tracking
The PostHogInterceptor supports optional exception capture. When enabled, it automatically captures unhandled exceptions thrown during request handling and sends them to PostHog Error Tracking.
By default, exception capture is disabled. To enable it:
Configuring the minimum status to capture
By default, 4xx errors (like NotFoundException or BadRequestException) are skipped – only 5xx errors are captured. You can lower the threshold:
The interceptor uses an RxJS catchError operator to observe exceptions without interfering with NestJS's exception filter pipeline. It:
- Skips exceptions that have already been captured (deduplication)
- Skips
HttpExceptions with a status code belowminStatusToCapture(default: 500) - Re-throws the exception after capturing, so NestJS exception filters still work as expected
For more details on Error Tracking setup, see the NestJS Error Tracking installation guide.
Next steps
To read more about how to integrate specific PostHog features into NestJS, have a look at our Node SDK docs for concepts such as: