askill
posthog

posthogSafety 95Repository

Implements product analytics with PostHog including event tracking, feature flags, and session replay. Use when adding analytics, A/B testing, or user behavior tracking to React and Next.js applications.

3 stars
1.2k downloads
Updated 2/13/2026

Package Files

Loading files...
SKILL.md

PostHog

Product analytics platform with autocapture, feature flags, session replay, and A/B testing. Open source with self-hosting option.

Quick Start

npm install posthog-js @posthog/react

React Setup

// src/main.tsx or src/index.tsx
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import posthog from 'posthog-js';
import { PostHogProvider } from '@posthog/react';
import App from './App';

posthog.init(import.meta.env.VITE_PUBLIC_POSTHOG_KEY, {
  api_host: import.meta.env.VITE_PUBLIC_POSTHOG_HOST || 'https://us.i.posthog.com',
  defaults: '2025-11-30',  // Use 2025 defaults
});

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <PostHogProvider client={posthog}>
      <App />
    </PostHogProvider>
  </StrictMode>
);

Next.js App Router Setup

// app/providers.tsx
'use client';

import posthog from 'posthog-js';
import { PostHogProvider as PHProvider } from '@posthog/react';
import { useEffect } from 'react';

export function PostHogProvider({ children }: { children: React.ReactNode }) {
  useEffect(() => {
    posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY!, {
      api_host: process.env.NEXT_PUBLIC_POSTHOG_HOST || 'https://us.i.posthog.com',
      defaults: '2025-11-30',
      capture_pageview: 'history_change',  // Auto-capture for App Router
    });
  }, []);

  return <PHProvider client={posthog}>{children}</PHProvider>;
}
// app/layout.tsx
import { PostHogProvider } from './providers';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <PostHogProvider>
          {children}
        </PostHogProvider>
      </body>
    </html>
  );
}

Event Tracking

Using the usePostHog Hook

import { usePostHog } from '@posthog/react';

function ProductCard({ product }) {
  const posthog = usePostHog();

  const handleAddToCart = () => {
    posthog.capture('add_to_cart', {
      product_id: product.id,
      product_name: product.name,
      price: product.price,
      category: product.category,
    });
  };

  const handleView = () => {
    posthog.capture('product_viewed', {
      product_id: product.id,
      product_name: product.name,
    });
  };

  return (
    <div onClick={handleView}>
      <h3>{product.name}</h3>
      <button onClick={handleAddToCart}>Add to Cart</button>
    </div>
  );
}

Common Events

const posthog = usePostHog();

// Page views (automatic with defaults: '2025-11-30')
// posthog.capture('$pageview');  // Usually not needed

// User actions
posthog.capture('button_clicked', { button_name: 'signup' });
posthog.capture('form_submitted', { form_name: 'contact' });
posthog.capture('file_downloaded', { file_name: 'report.pdf' });

// Ecommerce
posthog.capture('purchase_completed', {
  order_id: 'order_123',
  total: 99.99,
  currency: 'USD',
  items: ['product_1', 'product_2'],
});

// Feature usage
posthog.capture('feature_used', {
  feature_name: 'export',
  feature_variant: 'csv',
});

User Identification

const posthog = usePostHog();

// Identify user after login
function onLogin(user) {
  posthog.identify(user.id, {
    email: user.email,
    name: user.name,
    plan: user.subscription?.plan,
    created_at: user.createdAt,
  });
}

// Reset on logout
function onLogout() {
  posthog.reset();
}

// Update user properties
posthog.people.set({
  plan: 'pro',
  last_active: new Date().toISOString(),
});

// Set properties once (won't overwrite)
posthog.people.set_once({
  initial_referrer: document.referrer,
  signup_date: new Date().toISOString(),
});

Feature Flags

Check Flag Status

import { useFeatureFlagEnabled, useFeatureFlagVariantKey } from '@posthog/react';

function FeatureComponent() {
  // Boolean flag
  const showNewFeature = useFeatureFlagEnabled('new-feature');

  // Multivariate flag
  const variant = useFeatureFlagVariantKey('checkout-experiment');

  if (!showNewFeature) {
    return null;
  }

  return (
    <div>
      {variant === 'control' && <OldCheckout />}
      {variant === 'test' && <NewCheckout />}
    </div>
  );
}

PostHogFeature Component

import { PostHogFeature } from '@posthog/react';

function App() {
  return (
    <div>
      <PostHogFeature flag="new-dashboard" match={true}>
        <NewDashboard />
      </PostHogFeature>

      <PostHogFeature flag="new-dashboard" match={false}>
        <OldDashboard />
      </PostHogFeature>
    </div>
  );
}

Feature Flag with Payload

import { useFeatureFlagPayload, useFeatureFlagEnabled } from '@posthog/react';

function PricingPage() {
  // Use both hooks to track experiment exposure
  const isEnabled = useFeatureFlagEnabled('pricing-experiment');
  const payload = useFeatureFlagPayload('pricing-experiment');

  if (!isEnabled || !payload) {
    return <DefaultPricing />;
  }

  return (
    <div>
      <h1>{payload.headline}</h1>
      <p>Starting at ${payload.startingPrice}/month</p>
    </div>
  );
}

Server-Side Feature Flags

// app/api/feature/route.ts
import { PostHog } from 'posthog-node';

const posthog = new PostHog(process.env.POSTHOG_API_KEY!, {
  host: process.env.POSTHOG_HOST,
});

export async function GET(request: Request) {
  const userId = getUserId(request);

  const flagEnabled = await posthog.isFeatureEnabled('new-feature', userId);
  const variant = await posthog.getFeatureFlag('experiment', userId);

  return Response.json({ flagEnabled, variant });
}

Groups (B2B Analytics)

const posthog = usePostHog();

// Associate user with a company
posthog.group('company', 'company_123', {
  name: 'Acme Inc',
  plan: 'enterprise',
  employee_count: 50,
});

// Events now include company context
posthog.capture('feature_used', { feature: 'api' });

Session Replay

Enable in PostHog dashboard and configure:

posthog.init(POSTHOG_KEY, {
  api_host: POSTHOG_HOST,
  defaults: '2025-11-30',

  // Session replay options
  session_recording: {
    maskAllInputs: true,
    maskTextSelector: '.sensitive-data',
  },
});

Manual Controls

const posthog = usePostHog();

// Start/stop recording
posthog.startSessionRecording();
posthog.stopSessionRecording();

// Check if recording
const isRecording = posthog.sessionRecordingStarted();

A/B Testing (Experiments)

import { useFeatureFlagVariantKey, usePostHog } from '@posthog/react';

function CheckoutButton() {
  const posthog = usePostHog();
  const variant = useFeatureFlagVariantKey('checkout-button-experiment');

  const handleClick = () => {
    posthog.capture('checkout_clicked');
    // Process checkout...
  };

  if (variant === 'control') {
    return <button onClick={handleClick}>Checkout</button>;
  }

  if (variant === 'test') {
    return <button onClick={handleClick} className="cta-primary">Buy Now</button>;
  }

  return <button onClick={handleClick}>Checkout</button>;
}

Server-Side (Node.js)

npm install posthog-node
import { PostHog } from 'posthog-node';

const posthog = new PostHog(process.env.POSTHOG_API_KEY!, {
  host: process.env.POSTHOG_HOST,
});

// Capture event
posthog.capture({
  distinctId: 'user_123',
  event: 'api_called',
  properties: {
    endpoint: '/api/users',
    method: 'POST',
  },
});

// Identify user
posthog.identify({
  distinctId: 'user_123',
  properties: {
    email: 'user@example.com',
    plan: 'pro',
  },
});

// Shutdown (important for serverless)
await posthog.shutdown();

Configuration Options

posthog.init(POSTHOG_KEY, {
  api_host: 'https://us.i.posthog.com',
  defaults: '2025-11-30',

  // Autocapture
  autocapture: true,
  capture_pageview: 'history_change',
  capture_pageleave: true,

  // Privacy
  disable_session_recording: false,
  mask_all_text: false,
  mask_all_element_attributes: false,

  // Performance
  loaded: (posthog) => {
    // Called when PostHog is ready
  },

  // Debugging
  debug: process.env.NODE_ENV === 'development',
});

Environment Variables

# Client-side
NEXT_PUBLIC_POSTHOG_KEY=phc_xxxxxxxxxxxxxx
NEXT_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com

# Or for Vite
VITE_PUBLIC_POSTHOG_KEY=phc_xxxxxxxxxxxxxx
VITE_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com

# Server-side
POSTHOG_API_KEY=phx_xxxxxxxxxxxxxx
POSTHOG_HOST=https://us.i.posthog.com

Best Practices

  1. Use defaults: '2025-11-30' - Enables modern best practices
  2. Identify early - Call identify as soon as user logs in
  3. Use groups for B2B - Track company-level analytics
  4. Reset on logout - Call reset() to clear user data
  5. Use feature flag hooks - Tracks experiment exposure automatically
  6. Avoid direct import - Always use usePostHog hook in components
  7. Consider reverse proxy - Reduces ad blocker interference

Install

Download ZIP
Requires askill CLI v1.0+

AI Quality Score

91/100Analyzed 2/19/2026

Comprehensive PostHog integration skill with extensive code examples for React, Next.js, and Node.js. Covers event tracking, feature flags, A/B testing, session replay, and user identification with copy-paste ready snippets. Well-structured with clear sections and best practices. Slightly less complete on deployment/advanced topics but highly actionable for developers. Path suggests internal plugin context but content is broadly reusable.

95
88
90
88
92

Metadata

Licenseunknown
Version-
Updated2/13/2026
Publishermgd34msu

Tags

apitesting