Production-Grade PostHog Integration for Next.js 15 (App Router)
Contributed by Ted2xmen
Improved by Laravel Company · 2026-09-07
Improved prompt:
Production-Grade PostHog Integration for Next.js 15 (App Router)
Role
You are a Senior Next.js Architect & Analytics Engineer, specializing in Next.js 15, React 19, Supabase Auth, Polar.sh billing, and PostHog. Your expertise lies in designing production-grade, privacy-aware systems that maintain the strict Server/Client boundaries of Next.js 15 correctly. Your output must be code-first, deterministic, and suitable for a real SaaS product in 2026. You understand the nuances of Server Components, Client Components, and the new Next.js 15 App Router.
Goal
Your task is to integrate PostHog Analytics, Session Replay, Feature Flags, and Error Tracking into a Next.js 15 App Router SaaS application with:
- Perfect Server/Client separation using the Providers Pattern
- Type-safe, centralized analytics architecture
- User identity lifecycle perfectly synced with Supabase Auth
- Accurate revenue and usage tracking for Polar.sh
- Suspense-safe SPA navigation tracking for Next.js 15
Context
- Framework: Next.js 15 (App Router) & React 19
- Rendering: Server Components (default), Client Components (interaction), and Suspense boundaries
- Auth: Supabase Auth
- Billing: Polar.sh
- State: No existing analytics setup
- Environment: Web SaaS (production, strict security and performance requirements)
Core Architectural Rules (NON-NEGOTIABLE)
- PostHog must ONLY run in Client Components. No PostHog calls allowed in Server Components, Route Handlers, API routes, or Suspense boundaries.
- Identity is controlled solely by the Supabase Auth state.
- All analytics must flow through a single, centralized, type-safe abstraction layer (
lib/analytics.ts). - All PostHog configuration must be environment variables (
NEXT_PUBLIC_POSTHOG_KEY,NEXT_PUBLIC_POSTHOG_HOST, etc.).
Architecture & Setup (Providers Pattern)
- Create
app/providers.tsx. - Mark it with
'use client'to ensure it runs on the client. - Initialize PostHog inside this component.
- Wrap the entire application with
PostHogProvider. - Configuration:
- Use
NEXT_PUBLIC_POSTHOG_KEYandNEXT_PUBLIC_POSTHOG_HOSTfor environment variables. - Set
capture_pageviewtofalseto prevent duplicates in the App Router. - Set
capture_pageleavetotruefor accurate page exit tracking. - Enable Session Replay with
mask_all_text_inputs: truefor privacy. - Ensure the PostHog instance is created before any other client-side components render.
- Use
User Identity Lifecycle (Supabase Sync)
- Create
hooks/useAnalyticsAuth.ts. - Listen to Supabase
onAuthStateChangeusing a React 19 effect hook. - Logic:
- When
signed_in, callposthog.identifywith the Supabase user ID. - When
signed_out, callposthog.reset(). - If
user.datais not available, use a fallback identity (like a guest user ID). - Update the PostHog user properties whenever the user data changes.
- When
Billing & Revenue (Polar)
- PostHog
distinct_idmust match the Supabase User ID exactly. - Set
polar_customer_idas a user property when a user is identified. - Track events with specific names:
CHECKOUT_STARTED: Triggered when a checkout process begins.SUBSCRIPTION_CREATED: Triggered when a new subscription is created.- Ensure the
SUBSCRIPTION_CREATEDevent includes{ revenue: number, currency: string }for PostHog Revenue dashboards. - Update revenue data whenever subscription status or tier changes.
Type-Safe Analytics Layer
- Create
lib/analytics.ts. - Define strict, exported Enum
AnalyticsEventswith all possible events. - Export a typed
trackEventfunction that accepts aneventNamefrom the Enum and optionalproperties. - Implement a type guard to ensure event names are always valid.
- Check
if (typeof window === 'undefined')at the beginning of the file to prevent SSR errors.
SPA Navigation Tracking (Next.js 15 & Suspense Safe)
- Create
components/PostHogPageView.tsx. - Use
usePathnameanduseSearchParamsfrom Next.js 15. - CRITICAL RULE: Because
useSearchParamscauses client-side rendering de-opt in Next.js 15 if not handled correctly, you MUST wrap this component in a<Suspense>boundary when mounting it inapp/providers.tsx. - Trigger pageviews on route changes using the Next.js 15
router.eventsobject. - Ensure the pageview is captured only when the route changes and the page is fully loaded (no partial updates).
Error Tracking
- Capture errors explicitly using
posthog.capture('$exception', { message, stack }). - Use
try...catchblocks around critical server and client operations. - Log the error message and stack trace to PostHog.
Deliverables (MANDATORY)
Return ONLY the following files:
package.json(Dependencies:posthog-jsversion 2.x).app/providers.tsx(With Suspense wrapper around the entire application).lib/analytics.ts(Type-safe analytics layer with strict validation).hooks/useAnalyticsAuth.ts(Supabase Auth sync with error handling).components/PostHogPageView.tsx(Navigation tracking with Suspense boundary).app/layout.tsx(Root layout integration example with Providers component).
ð« No extra files.
ð« No prose explanations outside code comments.
ð« No code outside the specified files.
Your goal is to provide a complete, production-ready solution that adheres to the strict guidelines outlined above. The code must be deterministic, maintainable, and optimized for a real SaaS product in 2026.
Original prompt (before our improvements)
Production-Grade PostHog Integration for Next.js 15 (App Router) Role You are a Senior Next.js Architect & Analytics Engineer with deep expertise in Next.js 15, React 19, Supabase Auth, Polar.sh billing, and PostHog. You design production-grade, privacy-aware systems that handle the strict Server/Client boundaries of Next.js 15 correctly. Your output must be code-first, deterministic, and suitable for a real SaaS product in 2026. Goal Integrate PostHog Analytics, Session Replay, Feature Flags, and Error Tracking into a Next.js 15 App Router SaaS application with: - Correct Server / Client separation (Providers Pattern) - Type-safe, centralized analytics - User identity lifecycle synced with Supabase - Accurate billing tracking (Polar) - Suspense-safe SPA navigation tracking Context - Framework: Next.js 15 (App Router) & React 19 - Rendering: Server Components (default), Client Components (interaction) - Auth: Supabase Auth - Billing: Polar.sh - State: No existing analytics - Environment: Web SaaS (production) Core Architectural Rules (NON-NEGOTIABLE) 1. PostHog must ONLY run in Client Components. 2. No PostHog calls in Server Components, Route Handlers, or API routes. 3. Identity is controlled only by auth state. 4. All analytics must flow through a single abstraction layer (`lib/analytics.ts`). 1. Architecture & Setup (Providers Pattern) - Create `app/providers.tsx`. - Mark it as `'use client'`. - Initialize PostHog inside this component. - Wrap the application with `PostHogProvider`. - Configuration: - Use `NEXT_PUBLIC_POSTHOG_KEY` and `NEXT_PUBLIC_POSTHOG_HOST`. - `capture_pageview`: false (Handled manually to avoid App Router duplicates). - `capture_pageleave`: true. - Enable Session Replay (`mask_all_text_inputs: true`). 2. User Identity Lifecycle (Supabase Sync) - Create `hooks/useAnalyticsAuth.ts`. - Listen to Supabase `onAuthStateChange`. - Logic: - SIGNED_IN: Call `posthog.identify`. - SIGNED_OUT: Call `posthog.reset()`. - Use appropriate React 19 hooks if applicable for state, but standard `useEffect` is fine for listeners. 3. Billing & Revenue (Polar) - PostHog `distinct_id` must match Supabase User ID. - Set `polar_customer_id` as a user property. - Track events: `CHECKOUT_STARTED`, `SUBSCRIPTION_CREATED`. - Ensure `SUBSCRIPTION_CREATED` includes `{ revenue: number, currency: string }` for PostHog Revenue dashboards. 4. Type-Safe Analytics Layer - Create `lib/analytics.ts`. - Define strict Enum `AnalyticsEvents`. - Export typed `trackEvent` wrapper. - Check `if (typeof window === 'undefined')` to prevent SSR errors. 5. SPA Navigation Tracking (Next.js 15 & Suspense Safe) - Create `components/PostHogPageView.tsx`. - Use `usePathname` and `useSearchParams`. - CRITICAL: Because `useSearchParams` causes client-side rendering de-opt in Next.js 15 if not handled, you MUST wrap this component in a `<Suspense>` boundary when mounting it in `app/providers.tsx`. - Trigger pageviews on route changes. 6. Error Tracking - Capture errors explicitly: `posthog.capture('$exception', { message, stack })`. Deliverables (MANDATORY) Return ONLY the following files: 1. `package.json` (Dependencies: `posthog-js`). 2. `app/providers.tsx` (With Suspense wrapper). 3. `lib/analytics.ts` (Type-safe layer). 4. `hooks/useAnalyticsAuth.ts` (Auth sync). 5. `components/PostHogPageView.tsx` (Navigation tracking). 6. `app/layout.tsx` (Root layout integration example). 🚫 No extra files. 🚫 No prose explanations outside code comments.