TEXT

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)

  1. PostHog must ONLY run in Client Components. No PostHog calls allowed in Server Components, Route Handlers, API routes, or Suspense boundaries.
  2. Identity is controlled solely by the Supabase Auth state.
  3. All analytics must flow through a single, centralized, type-safe abstraction layer (lib/analytics.ts).
  4. 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_KEY and NEXT_PUBLIC_POSTHOG_HOST for environment variables.
    • Set capture_pageview to false to prevent duplicates in the App Router.
    • Set capture_pageleave to true for accurate page exit tracking.
    • Enable Session Replay with mask_all_text_inputs: true for privacy.
    • Ensure the PostHog instance is created before any other client-side components render.

User Identity Lifecycle (Supabase Sync)

  • Create hooks/useAnalyticsAuth.ts.
  • Listen to Supabase onAuthStateChange using a React 19 effect hook.
  • Logic:
    • When signed_in, call posthog.identify with the Supabase user ID.
    • When signed_out, call posthog.reset().
    • If user.data is not available, use a fallback identity (like a guest user ID).
    • Update the PostHog user properties whenever the user data changes.

Billing & Revenue (Polar)

  • PostHog distinct_id must match the Supabase User ID exactly.
  • Set polar_customer_id as 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_CREATED event 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 AnalyticsEvents with all possible events.
  • Export a typed trackEvent function that accepts an eventName from the Enum and optional properties.
  • 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 usePathname and useSearchParams from Next.js 15.
  • CRITICAL RULE: Because useSearchParams causes 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 in app/providers.tsx.
  • Trigger pageviews on route changes using the Next.js 15 router.events object.
  • 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...catch blocks around critical server and client operations.
  • Log the error message and stack trace to PostHog.

Deliverables (MANDATORY)
Return ONLY the following files:

  1. package.json (Dependencies: posthog-js version 2.x).
  2. app/providers.tsx (With Suspense wrapper around the entire application).
  3. lib/analytics.ts (Type-safe analytics layer with strict validation).
  4. hooks/useAnalyticsAuth.ts (Supabase Auth sync with error handling).
  5. components/PostHogPageView.tsx (Navigation tracking with Suspense boundary).
  6. 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.