Skip to main content
The PostHog React integration provides a seamless way to add analytics, feature flags, and session replay to your React applications using hooks and context providers.

Installation

Install both posthog-js and the React wrapper:
npm install posthog-js @posthog/react

Setup

1

Add environment variables

Create or update your .env file with your PostHog credentials. For Vite-based apps, use the VITE_PUBLIC_ prefix:
.env
VITE_PUBLIC_POSTHOG_KEY=<ph_project_token>
VITE_PUBLIC_POSTHOG_HOST=<ph_client_api_host>
For Create React App, use the REACT_APP_ prefix:
.env
REACT_APP_POSTHOG_KEY=<ph_project_token>
REACT_APP_POSTHOG_HOST=<ph_client_api_host>
2

Wrap your app with PostHogProvider

Add the PostHogProvider at the root of your application (typically in main.tsx or index.tsx):
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.jsx'
import { PostHogProvider } from '@posthog/react'

const options = {
  api_host: import.meta.env.VITE_PUBLIC_POSTHOG_HOST,
  defaults: '2026-01-30',
} as const

createRoot(document.getElementById('root')).render(
  <StrictMode>
    <PostHogProvider 
      apiKey={import.meta.env.VITE_PUBLIC_POSTHOG_KEY} 
      options={options}
    >
      <App />
    </PostHogProvider>
  </StrictMode>
)
The defaults option automatically configures PostHog with recommended settings. See SDK defaults for details.
3

Verify installation

Check your browser’s developer console for PostHog logs, or visit your Activity feed to see events.

Using the usePostHog Hook

Access the PostHog instance in any component using the usePostHog hook:
MyComponent.tsx
import { usePostHog } from '@posthog/react'

function MyComponent() {
  const posthog = usePostHog()

  function handleClick() {
    posthog.capture('button_clicked', { 
      button_name: 'signup',
      page: 'homepage'
    })
  }

  return <button onClick={handleClick}>Sign up</button>
}

Capturing Events

Custom Events

import { usePostHog } from '@posthog/react'

function ProductPage() {
  const posthog = usePostHog()

  const handlePurchase = (product, amount) => {
    posthog.capture('purchase_completed', {
      product_id: product.id,
      product_name: product.name,
      amount: amount,
      currency: 'USD'
    })
  }

  return (
    <button onClick={() => handlePurchase(product, 99.99)}>
      Buy Now
    </button>
  )
}

Track Component Lifecycle

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

function Dashboard() {
  const posthog = usePostHog()

  useEffect(() => {
    posthog.capture('dashboard_viewed')
  }, [])

  return <div>Dashboard Content</div>
}

Identifying Users

On Login

import { usePostHog } from '@posthog/react'

function LoginForm() {
  const posthog = usePostHog()

  const handleLogin = async (email, password) => {
    const user = await login(email, password)
    
    posthog.identify(user.id, {
      email: user.email,
      name: user.name,
      plan: user.plan
    })
  }

  return <form onSubmit={handleLogin}>{/* ... */}</form>
}

On Logout

import { usePostHog } from '@posthog/react'

function LogoutButton() {
  const posthog = usePostHog()

  const handleLogout = () => {
    logout()
    posthog.reset()
  }

  return <button onClick={handleLogout}>Logout</button>
}

Feature Flags

useFeatureFlagEnabled Hook

Check if a feature flag is enabled:
import { useFeatureFlagEnabled } from '@posthog/react'

function FeatureComponent() {
  const showNewDashboard = useFeatureFlagEnabled('new-dashboard')

  if (showNewDashboard) {
    return <NewDashboard />
  }

  return <OldDashboard />
}

useFeatureFlagVariantKey Hook

Get the variant of a multivariate flag:
import { useFeatureFlagVariantKey } from '@posthog/react'

function ExperimentButton() {
  const variant = useFeatureFlagVariantKey('button-color-experiment')

  const buttonColor = {
    'blue': '#0000FF',
    'green': '#00FF00',
    'red': '#FF0000'
  }[variant] || '#808080'

  return (
    <button style={{ backgroundColor: buttonColor }}>
      Click me
    </button>
  )
}

useFeatureFlagPayload Hook

Retrieve feature flag payload data:
import { useFeatureFlagPayload } from '@posthog/react'

function ConfigurableComponent() {
  const config = useFeatureFlagPayload('feature-config')

  return (
    <div>
      <h1>{config?.title || 'Default Title'}</h1>
      <p>Max items: {config?.maxItems || 10}</p>
    </div>
  )
}

Manual Flag Checking

import { usePostHog } from '@posthog/react'

function FeatureGate() {
  const posthog = usePostHog()

  const handleAction = () => {
    if (posthog.isFeatureEnabled('premium-feature')) {
      performPremiumAction()
    } else {
      showUpgradePrompt()
    }
  }

  return <button onClick={handleAction}>Action</button>
}

Accessing PostHog Outside Components

For utility functions or non-React code:
utils/analytics.ts
import posthog from 'posthog-js'

export function trackPurchase(amount: number) {
  posthog.capture('purchase_completed', { amount })
}

export function checkFeature(flagName: string): boolean {
  return posthog.isFeatureEnabled(flagName)
}

React Router Integration

Track route changes automatically:
App.tsx
import { useEffect } from 'react'
import { useLocation } from 'react-router-dom'
import { usePostHog } from '@posthog/react'

function App() {
  const location = useLocation()
  const posthog = usePostHog()

  useEffect(() => {
    posthog.capture('$pageview')
  }, [location, posthog])

  return <Routes>{/* your routes */}</Routes>
}

Group Analytics

Track events for organizations or teams:
import { usePostHog } from '@posthog/react'

function OrganizationSettings() {
  const posthog = usePostHog()

  useEffect(() => {
    posthog.group('company', 'company_id_123', {
      name: 'Acme Corporation',
      plan: 'enterprise'
    })
  }, [])

  const handleFeatureUse = () => {
    posthog.capture('feature_used', {
      feature_name: 'advanced_analytics'
    })
  }

  return <div>{/* ... */}</div>
}

Advanced Configuration

import { PostHogProvider } from '@posthog/react'

const options = {
  api_host: import.meta.env.VITE_PUBLIC_POSTHOG_HOST,
  session_recording: {
    recordCrossOriginIframes: true,
    maskAllInputs: false,
    maskInputOptions: {
      password: true,
      email: true
    }
  }
}

root.render(
  <PostHogProvider apiKey={apiKey} options={options}>
    <App />
  </PostHogProvider>
)

Privacy Controls

Mask sensitive elements in session replay:
function SensitiveForm() {
  return (
    <form>
      <input 
        type="text" 
        placeholder="Name" 
      />
      <input 
        type="email" 
        placeholder="Email"
        className="ph-no-capture" // This input won't be recorded
      />
      <div className="ph-mask">
        This text will be masked in recordings
      </div>
    </form>
  )
}

TypeScript Support

The SDK includes full TypeScript support:
import { PostHog } from 'posthog-js'
import { usePostHog } from '@posthog/react'

interface CustomEventProperties {
  button_name: string
  page: string
}

function TypedComponent() {
  const posthog: PostHog = usePostHog()

  const handleClick = () => {
    posthog.capture<CustomEventProperties>('button_clicked', {
      button_name: 'signup',
      page: 'homepage'
    })
  }

  return <button onClick={handleClick}>Click</button>
}

Debugging

Enable debug mode during development:
import { PostHogProvider } from '@posthog/react'

const options = {
  api_host: import.meta.env.VITE_PUBLIC_POSTHOG_HOST,
  debug: import.meta.env.DEV // Enable in development only
}

Best Practices

Provider Placement: Always place PostHogProvider as high as possible in your component tree to ensure all components have access.
Avoid Over-tracking: Don’t track every click. Focus on meaningful user actions that help you understand product usage.
Use Hooks: Prefer usePostHog and feature flag hooks over importing posthog-js directly for better React integration.
Reset on Logout: Always call posthog.reset() when users log out to prevent data leakage between accounts.

Next Steps

Next.js Integration

Add PostHog to Next.js with SSR support

Feature Flags

Learn advanced feature flag patterns

Session Replay

Configure privacy and recording options

JavaScript SDK

Full JavaScript SDK reference

Build docs developers (and LLMs) love