PostHog Reference Architecture
Overview
Production architecture for product analytics with PostHog. Covers event tracking design, feature flag management, experimentation framework, and integration patterns for web and backend applications.
Prerequisites
-
PostHog project (Cloud or self-hosted)
-
posthog-js and posthog-node SDKs
-
Understanding of event-driven analytics
-
Feature flag strategy planned
Architecture Diagram
set -euo pipefail ┌──────────────────────────────────────────────────────┐ │ Client Applications │ │ Web (posthog-js) │ Mobile (posthog-react-native) │ └──────────┬────────────────────────────┬──────────────┘ │ │ ▼ ▼ ┌──────────────────────────────────────────────────────┐ │ PostHog Platform │ │ ┌───────────┐ ┌───────────┐ ┌─────────────────┐ │ │ │ Events │ │ Feature │ │ Experiments │ │ │ │ & Props │ │ Flags │ │ (A/B tests) │ │ │ └─────┬─────┘ └─────┬─────┘ └───────┬─────────┘ │ │ │ │ │ │ │ ┌─────┴──────────────┴─────────────────┴───────┐ │ │ │ Analytics Engine │ │ │ │ Trends │ Funnels │ Retention │ Paths │ SQL │ │ │ └──────────────────────────────────────────────┘ │ ├──────────────────────────────────────────────────────┤ │ Backend (posthog-node) │ │ Server Events │ Flag Evaluation │ Group Analytics │ └──────────────────────────────────────────────────────┘
Instructions
Step 1: Event Taxonomy Design
// events.ts - Define your event taxonomy export const EVENTS = { // User lifecycle USER_SIGNED_UP: 'user_signed_up', USER_LOGGED_IN: 'user_logged_in', USER_ONBOARDING_COMPLETED: 'user_onboarding_completed',
// Core product actions FEATURE_USED: 'feature_used', ITEM_CREATED: 'item_created', ITEM_SHARED: 'item_shared', EXPORT_COMPLETED: 'export_completed',
// Revenue SUBSCRIPTION_STARTED: 'subscription_started', SUBSCRIPTION_UPGRADED: 'subscription_upgraded', SUBSCRIPTION_CANCELED: 'subscription_canceled', } as const;
// Standard properties for consistency interface EventProperties { feature_name?: string; source?: 'web' | 'mobile' | 'api'; plan_tier?: 'free' | 'pro' | 'enterprise'; duration_ms?: number; }
Step 2: Client-Side Integration
import posthog from 'posthog-js';
posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY!, { api_host: 'https://us.i.posthog.com', capture_pageview: true, capture_pageleave: true, autocapture: true, persistence: 'localStorage+cookie', loaded: (ph) => { if (process.env.NODE_ENV === 'development') { ph.opt_out_capturing(); // Disable in dev } }, });
// Identify users function identifyUser(userId: string, traits: Record<string, any>) { posthog.identify(userId, { email: traits.email, plan: traits.plan, company: traits.company, });
// Set group for company-level analytics if (traits.companyId) { posthog.group('company', traits.companyId, { name: traits.company, plan: traits.plan, }); } }
Step 3: Feature Flag Architecture
// flags.ts - Feature flag definitions export const FLAGS = { NEW_DASHBOARD: 'new-dashboard-v2', AI_FEATURES: 'ai-features-beta', PRICING_EXPERIMENT: 'pricing-page-experiment', } as const;
// React hook for feature flags function useFeatureFlag(flagKey: string) { const [enabled, setEnabled] = useState(false);
useEffect(() => { posthog.onFeatureFlags(() => { setEnabled(posthog.isFeatureEnabled(flagKey) ?? false); }); }, [flagKey]);
return enabled; }
// Server-side flag evaluation import { PostHog } from 'posthog-node'; const serverPosthog = new PostHog(process.env.POSTHOG_API_KEY!);
async function getServerFlags(userId: string) { return serverPosthog.getAllFlags(userId); }
Step 4: Experiment Tracking
function trackExperiment(experimentKey: string, userId: string) { const variant = posthog.getFeatureFlag(experimentKey);
posthog.capture('$experiment_started', { $experiment_name: experimentKey, $experiment_variant: variant, });
return variant; }
Error Handling
Issue Cause Solution
Events not appearing SDK not initialized Check init call and API key
Flag always false Not loaded yet Use onFeatureFlags callback
Missing user properties Not identified Call identify before capture
High event volume Autocapture too broad Configure autocapture selectively
Examples
Funnel Tracking Setup
// Track a conversion funnel posthog.capture(EVENTS.ITEM_CREATED, { source: 'web' }); posthog.capture(EVENTS.ITEM_SHARED, { share_method: 'link' }); posthog.capture(EVENTS.EXPORT_COMPLETED, { format: 'pdf' });
Resources
-
PostHog Documentation
-
PostHog Feature Flags
-
PostHog Experiments
Output
-
Configuration files or code changes applied to the project
-
Validation report confirming correct implementation
-
Summary of changes made and their rationale