Skip to main content

PostHog vs Mixpanel vs Amplitude: Product Analytics (2026)

·PkgPulse Team

TL;DR

PostHog is the open-source product analytics suite — event tracking, session replay, feature flags, A/B testing, surveys, all in one platform, self-hostable. Mixpanel is the event-based analytics platform — powerful funnels, retention analysis, user flows, interactive reports, the pioneer in product analytics. Amplitude is the enterprise analytics platform — behavioral analytics, cohort analysis, data governance, experimentation, used by large product teams. In 2026: PostHog for all-in-one open-source analytics, Mixpanel for focused event analytics with great UX, Amplitude for enterprise behavioral analytics.

Key Takeaways

  • PostHog: posthog-js ~500K weekly downloads — open-source, all-in-one, self-hostable
  • Mixpanel: mixpanel-browser ~500K weekly downloads — event analytics, funnels, flows
  • Amplitude: @amplitude/analytics-browser ~300K weekly downloads — behavioral, cohorts, enterprise
  • PostHog bundles analytics + session replay + feature flags + surveys
  • Mixpanel has the most intuitive analytics UI
  • Amplitude excels at enterprise features and data governance

PostHog

PostHog — open-source product analytics:

Setup

import posthog from "posthog-js"

// Initialize:
posthog.init(process.env.POSTHOG_KEY!, {
  api_host: "https://us.i.posthog.com",  // Or self-hosted URL
  person_profiles: "identified_only",
  capture_pageview: true,
  capture_pageleave: true,
  autocapture: true,  // Auto-track clicks, form submissions
})

Event tracking

import posthog from "posthog-js"

// Track event:
posthog.capture("package_compared", {
  packages: ["react", "vue"],
  comparison_type: "downloads",
})

// Track with groups:
posthog.capture("report_generated", {
  report_type: "monthly",
  packages_count: 10,
  $groups: { organization: "org-123" },
})

// Identify user:
posthog.identify("user-123", {
  email: "royce@example.com",
  plan: "pro",
  signup_date: "2026-01-15",
})

// Set user properties:
posthog.people.set({
  last_active: new Date().toISOString(),
  packages_tracked: 25,
})

// Page view:
posthog.capture("$pageview", {
  $current_url: window.location.href,
})

Feature flags

import posthog from "posthog-js"

// Check feature flag:
if (posthog.isFeatureEnabled("new-comparison-ui")) {
  renderNewComparisonUI()
} else {
  renderClassicUI()
}

// Get flag payload:
const variant = posthog.getFeatureFlag("pricing-experiment")
// "control" | "variant-a" | "variant-b"

// React hook:
import { useFeatureFlagEnabled } from "posthog-js/react"

function ComparisonPage() {
  const showNewUI = useFeatureFlagEnabled("new-comparison-ui")

  return showNewUI ? <NewUI /> : <ClassicUI />
}

Session replay and surveys

import posthog from "posthog-js"

// Session replay is automatic (configured in PostHog dashboard)
// Records user sessions for debugging and UX analysis

// Trigger survey programmatically:
posthog.capture("$survey_shown", {
  $survey_id: "survey-123",
})

// React:
import { PostHogProvider } from "posthog-js/react"

function App() {
  return (
    <PostHogProvider client={posthog}>
      <Router />
    </PostHogProvider>
  )
}

Mixpanel

Mixpanel — event-based analytics:

Setup

import mixpanel from "mixpanel-browser"

// Initialize:
mixpanel.init(process.env.MIXPANEL_TOKEN!, {
  debug: process.env.NODE_ENV === "development",
  track_pageview: "url-with-path",
  persistence: "localStorage",
  ignore_dnt: false,
})

Event tracking

import mixpanel from "mixpanel-browser"

// Track event:
mixpanel.track("Package Compared", {
  packages: ["react", "vue"],
  comparison_type: "downloads",
  result_count: 2,
})

// Track with timing:
const startTime = Date.now()
await generateReport()
mixpanel.track("Report Generated", {
  duration_ms: Date.now() - startTime,
  report_type: "monthly",
})

// Identify user:
mixpanel.identify("user-123")

// Set user profile:
mixpanel.people.set({
  $email: "royce@example.com",
  $name: "Royce",
  plan: "pro",
  signup_date: "2026-01-15",
  packages_tracked: 25,
})

// Increment property:
mixpanel.people.increment("comparisons_made", 1)

// Track revenue:
mixpanel.people.track_charge(29.99, {
  plan: "pro",
  billing_cycle: "monthly",
})

Funnels and groups

import mixpanel from "mixpanel-browser"

// Track funnel steps:
mixpanel.track("Signup Started")
// ... user fills form ...
mixpanel.track("Signup Email Entered", { method: "email" })
// ... user completes ...
mixpanel.track("Signup Completed", { plan: "free" })

// Group analytics:
mixpanel.set_group("organization", "org-123")
mixpanel.get_group("organization", "org-123").set({
  name: "PkgPulse Team",
  plan: "enterprise",
  member_count: 15,
})

// Super properties (sent with every event):
mixpanel.register({
  app_version: "2.1.0",
  platform: "web",
  theme: "dark",
})

// Time events:
mixpanel.time_event("Search")
// ... user searches ...
mixpanel.track("Search", { query: "react", results: 150 })
// Automatically includes $duration

React integration

import { MixpanelProvider, useMixpanel } from "react-mixpanel-browser"

function App() {
  return (
    <MixpanelProvider token={process.env.MIXPANEL_TOKEN!}>
      <Router />
    </MixpanelProvider>
  )
}

function ComparisonButton({ packages }: { packages: string[] }) {
  const mixpanel = useMixpanel()

  return (
    <button onClick={() => {
      mixpanel.track("Compare Clicked", { packages })
    }}>
      Compare
    </button>
  )
}

Amplitude

Amplitude — behavioral analytics:

Setup

import * as amplitude from "@amplitude/analytics-browser"

// Initialize:
amplitude.init(process.env.AMPLITUDE_API_KEY!, {
  defaultTracking: {
    sessions: true,
    pageViews: true,
    formInteractions: true,
    fileDownloads: true,
  },
})

Event tracking

import * as amplitude from "@amplitude/analytics-browser"

// Track event:
amplitude.track("Package Compared", {
  packages: ["react", "vue"],
  comparison_type: "downloads",
})

// Identify user:
const identifyEvent = new amplitude.Identify()
identifyEvent.set("email", "royce@example.com")
identifyEvent.set("plan", "pro")
identifyEvent.set("signup_date", "2026-01-15")
identifyEvent.setOnce("first_platform", "web")
identifyEvent.add("comparisons_made", 1)
amplitude.identify(identifyEvent)

// Set user ID:
amplitude.setUserId("user-123")

// Revenue tracking:
const revenue = new amplitude.Revenue()
  .setProductId("pro-plan")
  .setPrice(29.99)
  .setQuantity(1)
  .setRevenueType("subscription")
amplitude.revenue(revenue)

// Group analytics:
amplitude.setGroup("organization", "org-123")

Advanced tracking

import * as amplitude from "@amplitude/analytics-browser"

// User properties with operations:
const identify = new amplitude.Identify()
identify.set("plan", "pro")
identify.append("used_features", "comparison")
identify.prepend("recent_searches", "react")
identify.add("session_count", 1)
identify.unset("trial_expired")
amplitude.identify(identify)

// Flush events:
amplitude.flush()

// Track with groups:
amplitude.track("Report Downloaded", {
  format: "pdf",
  pages: 5,
}, {
  groups: { organization: "org-123" },
})

// Session replay (Amplitude Session Replay):
amplitude.init(API_KEY, {
  defaultTracking: { sessions: true },
  plugins: [
    amplitude.sessionReplayPlugin({
      sampleRate: 0.1,  // Record 10% of sessions
    }),
  ],
})

React integration

import { useEffect } from "react"
import * as amplitude from "@amplitude/analytics-browser"

// Track page views:
function usePageTracking() {
  useEffect(() => {
    amplitude.track("Page Viewed", {
      path: window.location.pathname,
      referrer: document.referrer,
    })
  }, [])
}

// Track component interactions:
function PackageCard({ pkg }: { pkg: Package }) {
  return (
    <div
      onClick={() => {
        amplitude.track("Package Card Clicked", {
          package_name: pkg.name,
          position: pkg.rank,
        })
      }}
    >
      <h3>{pkg.name}</h3>
      <p>{pkg.downloads.toLocaleString()} downloads</p>
    </div>
  )
}

// Experiment (A/B testing):
import { Experiment } from "@amplitude/experiment-js-client"

const experiment = Experiment.initializeWithAmplitudeAnalytics(
  process.env.AMPLITUDE_DEPLOYMENT_KEY!
)

await experiment.fetch()
const variant = experiment.variant("new-pricing-page")

if (variant.value === "treatment") {
  renderNewPricing()
}

Feature Comparison

FeaturePostHogMixpanelAmplitude
Open-source
Self-hosted
Event tracking
Funnels
Retention
User flows✅ (Journeys)
Cohort analysis
Session replay✅ (built-in)✅ (add-on)
Feature flags✅ (built-in)
A/B testing✅ (built-in)✅ (Experiment)
Surveys✅ (built-in)
Autocapture✅ (limited)
Data governance✅ (Taxonomy)
Group analytics
SQL access✅ (HogQL)
Free tier1M events/mo20M events/mo50K MTUs
PricingUsage-basedEvent-basedMTU-based

When to Use Each

Use PostHog if:

  • Want an all-in-one platform (analytics + replay + flags + surveys)
  • Prefer open-source and self-hosting option
  • Need feature flags and A/B testing alongside analytics
  • Want to own your data (GDPR, data sovereignty)

Use Mixpanel if:

  • Want the best event analytics UI and query builder
  • Need powerful funnel analysis and user flows
  • Building growth-focused products with detailed behavioral tracking
  • Want the most generous free tier (20M events/month)

Use Amplitude if:

  • Building enterprise products with large data volumes
  • Need advanced behavioral analytics and cohort analysis
  • Want data governance and taxonomy management
  • Need experimentation platform (A/B testing)

Methodology

Download data from npm registry (weekly average, February 2026). Feature comparison based on posthog-js v1.x, mixpanel-browser v2.x, and @amplitude/analytics-browser v2.x.

Compare analytics and developer tooling on PkgPulse →

Comments

Stay Updated

Get the latest package insights, npm trends, and tooling tips delivered to your inbox.