Skip to main content
Sabo includes pre-configured PostHog analytics with automatic pageview tracking, custom event support, and feature flags. PostHog is optional and only activates when environment variables are set.

Overview

PostHog is an open-source product analytics platform that helps you understand how users interact with your application. Sabo’s PostHog integration provides:
  • Automatic pageview tracking for all routes
  • Custom event tracking via the usePostHog() hook
  • Server-side analytics for API routes and server components
  • Feature flags for gradual feature rollouts
  • Session recording (configurable in PostHog dashboard)
  • Privacy-first analytics with GDPR compliance options
PostHog is completely optional. If you don’t set the environment variables, Sabo will function normally without analytics.
Need a deeper dive into every PostHog feature (insights, dashboards, cohorts)? Keep the official PostHog documentation handy while working through this guide.

Quick Setup

1

Create PostHog account

Sign up for PostHog to get your project API key.
  1. Visit PostHog Cloud or self-host PostHog
  2. Create a new project
  3. Copy your Project API Key from Project Settings
  4. Note your PostHog host URL:
    • Cloud: https://app.posthog.com (US) or https://eu.posthog.com (EU)
    • Self-hosted: Your custom domain
PostHog offers a generous free tier with 1 million events per month. No credit card required for signup.
2

Add environment variables

Add PostHog credentials to your .env.local file:
.env.local
Important: Both variables must be present for PostHog to initialize. If either is missing, PostHog will remain disabled.
Restart your development server after adding environment variables.
3

Verify integration

Test that PostHog is tracking events:
  1. Start your dev server: pnpm dev
  2. Visit http://localhost:3000
  3. Open browser console and look for PostHog debug messages (in development mode)
  4. Check PostHog dashboard → Activity to see live pageviews
In development mode, PostHog automatically enables debug logging. Check your browser console for [PostHog] messages.

How It Works

Architecture

Sabo’s PostHog integration consists of three main parts:
  1. Client-side provider (src/components/posthog-provider.tsx)
    • Initializes PostHog in the browser
    • Wraps the entire app to provide PostHog context
    • Enables debug mode in development
  2. Server-side client (src/lib/posthog/server.ts)
    • Tracks events from API routes and server components
    • Uses PostHog Node.js SDK
    • Flushes events immediately for real-time tracking
  3. Exports module (src/lib/posthog/index.ts)
    • Centralizes imports for both client and server utilities
    • Re-exports usePostHog hook and getPostHogClient function

Initialization

PostHog initializes automatically when the app loads, but only if environment variables are set.
src/components/posthog-provider.tsx
The PHProvider wraps your entire app in src/app/layout.tsx:
src/app/layout.tsx
PHProvider wraps ThemeProvider to ensure PostHog context is available throughout the entire application, including all client components.

Tracking Events

Automatic Pageview Tracking

PostHog automatically tracks pageviews for all routes in your app. No additional code required. What’s tracked:
  • Route changes (including Next.js App Router navigation)
  • URL parameters and query strings
  • Referrer information
  • Browser and device details
Viewing pageviews:
  1. Go to PostHog Dashboard → Activity
  2. Filter by event type: $pageview
  3. See real-time page visits with full URL paths

Custom Event Tracking (Client-Side)

Track user interactions, button clicks, form submissions, and other custom events using the usePostHog() hook.
1

Import the hook

2

Call the hook in your component

3

Track events

Complete Example

src/components/marketing/pricing.tsx
Use optional chaining (posthog?.capture) to safely handle cases where PostHog is not initialized (e.g., missing environment variables).

Common Events to Track

Here are some recommended events to track in a SaaS application:

Server-Side Event Tracking

Track events from API routes, server actions, or server components using the server-side PostHog client.
src/app/api/your-route/route.ts
The server client (src/lib/posthog/server.ts) is configured to flush events immediately:
src/lib/posthog/server.ts
Server-side tracking requires a distinctId (usually the user ID) to associate events with specific users. Make sure to provide this when capturing server events.

User Identification

Identifying Users

Call posthog.identify() in whichever component completes your authentication flow (for example, the /sign-in page) so future events are tied to the logged-in user:

Setting User Properties

Update user properties as they change:

Resetting User Identity

Clear user identification on logout:

Feature Flags

PostHog feature flags allow you to roll out features gradually, run A/B tests, and toggle features without deploying code.

Using Feature Flags (Client-Side)

Feature Flag with Variants

Creating Feature Flags

  1. Go to PostHog Dashboard → Feature Flags
  2. Click “New feature flag”
  3. Configure:
    • Key: new-dashboard-ui (use in code)
    • Rollout: Percentage (e.g., 50% of users)
    • Filters: Target specific users, groups, or properties
  4. Save and the flag is immediately available
Feature flags are cached locally, so changes may take a few minutes to propagate to all users. You can force a refresh by calling posthog?.reloadFeatureFlags().
Want to convert those flags into statistically sound experiments? PostHog’s A/B testing guide explains how to define variants, success metrics, and rollouts using the same flag keys shown above.

Configuration Options

PostHog Initialization Options

You can customize PostHog behavior by modifying src/components/posthog-provider.tsx:
src/components/posthog-provider.tsx

Privacy Options

Configure PostHog to respect user privacy:

Best Practices

If you need a formal naming taxonomy for events and properties, refer to PostHog’s event taxonomy guide. It includes naming tables, spreadsheet templates, and enforcement strategies that complement the recommendations below.
Use consistent, descriptive names for events:Good:
  • subscription_started
  • user_signed_up
  • file_uploaded
Bad:
  • click
  • event1
  • test
Guidelines:
  • Use snake_case for event names
  • Use past tense verbs (clicked, not click)
  • Be specific (checkout_completed vs purchase)
  • Group related events with prefixes (subscription_*, user_*)
Include relevant context with every event:
Guidelines:
  • Keep property names consistent across events
  • Include user properties (plan, role, etc.)
  • Add context (page location, user state)
  • Use appropriate data types (numbers for counts, booleans for flags)
PostHog batches events by default, but you can optimize further:
Tips:
  • Don’t track every keystroke or mouse movement
  • Batch similar events (e.g., track scroll milestones: 25%, 50%, 75%, 100%)
  • Use feature flags to disable analytics in staging environments
Verify events are tracked correctly:In Development:
  • Check browser console for [PostHog] debug messages
  • Visit PostHog Dashboard → Activity (live view)
  • Use PostHog’s “Test mode” to see events in real-time
Before Production:
  • Test with different user states (logged in/out, different plans)
  • Verify user identification works after sign-in
  • Check that properties contain expected values
  • Test feature flags with different rollout percentages

Production Deployment

1

Update environment variables

Set PostHog credentials in your production environment (Vercel, Netlify, etc.):
Use separate PostHog projects for development and production to keep analytics data isolated.
2

Disable debug mode

Ensure debug mode is only enabled in development (already configured in posthog-provider.tsx):
3

Configure session recording

Decide whether to enable session recording in PostHog Dashboard:
  1. Go to Settings → Project Settings → Recordings
  2. Enable/disable session recording
  3. Configure privacy settings:
    • Mask sensitive inputs (passwords, credit cards)
    • Block specific elements by CSS selector
    • Disable recording on certain pages
Session recording captures user interactions. Ensure you comply with GDPR/privacy regulations and disclose this in your privacy policy.
4

Set up alerts

Configure PostHog to notify you of important events:
  1. Go to Alerts → Create alert
  2. Choose trigger (e.g., “Subscription cancelled” event)
  3. Set threshold and frequency
  4. Connect to Slack, email, or webhooks
Test alerts in PostHog to ensure notifications are working before going live.

Troubleshooting

Symptoms: No events in PostHog dashboard, no debug messages in console.Causes:
  • Missing environment variables
  • Incorrect API key or host
  • Variables not prefixed with NEXT_PUBLIC_
Fix:
  1. Verify both NEXT_PUBLIC_POSTHOG_KEY and NEXT_PUBLIC_POSTHOG_HOST are set in .env.local
  2. Restart dev server after adding variables
  3. Check browser console for PostHog errors
  4. Confirm API key format: phc_...
  5. Use correct host (US: https://app.posthog.com, EU: https://eu.posthog.com)
Symptoms: PostHog initializes but events don’t show up.Causes:
  • Wrong project API key
  • Ad blockers blocking PostHog
  • Network issues
  • PostHog ingestion delay
Fix:
  1. Check you’re viewing the correct project in PostHog dashboard
  2. Disable ad blockers (uBlock, Privacy Badger often block analytics)
  3. Check browser network tab for failed requests to PostHog
  4. Wait 1-2 minutes for events to appear (PostHog has slight delay)
  5. Verify API key in PostHog → Project Settings → Project API Key
Symptoms: React error when calling usePostHog().Causes:
  • Missing "use client" directive
  • Component is server component
  • PostHog not imported correctly
Fix:
  1. Add "use client" at top of file using usePostHog()
  2. Import from @/lib/posthog, not posthog-js directly
  3. Ensure PHProvider wraps your component tree in layout.tsx
Symptoms: getPostHogClient() returns null on server.Causes:
  • Environment variables not set in production
  • Variables missing NEXT_PUBLIC_ prefix
Fix:
  1. Verify environment variables are set in hosting platform (Vercel, Netlify)
  2. Both client and server use NEXT_PUBLIC_* variables (this is intentional for consistency)
  3. Redeploy after adding environment variables
  4. Check server logs for PostHog initialization messages
Symptoms: isFeatureEnabled() always returns false.Causes:
  • Feature flag not created in PostHog
  • User not identified (posthog.identify() not called)
  • Flag filters don’t match current user
  • Feature flags not loaded yet
Fix:
  1. Create feature flag in PostHog Dashboard → Feature Flags
  2. Call posthog.identify(userId) after authentication
  3. Check flag filters/rollout percentage
  4. Wait for flags to load or call posthog.reloadFeatureFlags()

Privacy & GDPR Compliance

PostHog provides tools to help you comply with privacy regulations: PostHog sets cookies (ph_*) to track users. Implement cookie consent before initializing:
src/components/posthog-provider.tsx

Data Deletion Requests

Handle GDPR deletion requests via PostHog API:

Anonymization

Anonymize sensitive data before tracking:
Review your privacy policy to disclose PostHog usage. Sabo includes placeholder legal pages in src/content/legal/ that mention PostHog—update these with your specific implementation.