Tutorials / Backend integrations / Product analytics with PostHog
📝 Written ● Beginner Updated 2026-05-13

Product analytics with PostHog

Track what users do, run feature flags, watch session replays — one tool, one signup. Free tier covers 1M events/month + 5K replays. The default analytics stack for indie products.

What PostHog gives you

0
  • Product analytics — track named events ("upload_started", "checkout_completed"), build funnels, see retention cohorts. Like Mixpanel or Amplitude.
  • Session replay — video-like playback of real user sessions. Privacy-aware (auto-masks inputs).
  • Feature flags — gradually roll out new features to N% of users, A/B test variants.
  • Surveys — in-app NPS or feedback prompts.
  • Heatmaps — see where users click on a page.

Alternatives: Plausible ↗ (lighter, privacy-first, page-view focused), Mixpanel ↗, Amplitude ↗. PostHog wins on "single tool covers everything" and a generous free tier.

Sign up + create a project

1

Sign up at app.posthog.com ↗. Pick the US Cloud or EU Cloud region (matters for GDPR). Create a project; name it after your app.

Copy your Project API Key (looks like phc_xxxxxxxxxxxxxxxx). Visible at Settings → Project → General. Safe to ship to browsers — it's a write-only key with no access to your data.

Install — web

2

Easiest: snippet in HTML (works for any web app):

<script>
  !function(t,e){var o,n,p,r;e.__SV||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.crossOrigin="anonymous",p.async=!0,p.src=s.api_host.replace(".i.posthog.com","-assets.i.posthog.com")+"/static/array.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r);var u=e;for(void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],u.toString=function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e},u.people.toString=function(){return u.toString(1)+".people (stub)"},o="capture identify alias people.set people.set_once set_config register register_once unregister opt_out_capturing has_opted_out_capturing opt_in_capturing reset isFeatureEnabled onFeatureFlags getFeatureFlag getFeatureFlagPayload reloadFeatureFlags group updateEarlyAccessFeatureEnrollment getEarlyAccessFeatures getActiveMatchingSurveys getSurveys getNextSurveyStep onSessionId".split(" "),n=0;n<o.length;n++)g(u,o[n]);e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[]);
  posthog.init("phc_YOUR_KEY_HERE", { api_host: "https://us.i.posthog.com" });
</script>

npm version (React/Next.js/Vue):

npm install posthog-js
import posthog from "posthog-js";

if (typeof window !== "undefined") {
  posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY, {
    api_host: "https://us.i.posthog.com",
  });
}

The snippet auto-captures: page views, clicks, form fills, page-leave events. You'll see them appear in PostHog within seconds of loading the page.

Install — backend / mobile

3

All libraries follow the same pattern: init, capture, identify.

Capture your first custom event

4
// Web / React
posthog.capture("upload_started", {
  file_type: "image/png",
  file_size_bytes: 12345,
});

Naming convention worth adopting: noun_verb with snake_case. upload_started, checkout_completed, tutorial_finished. Consistent names make funnels and dashboards readable a year from now.

See it in PostHog → Activity → Live Events. Latency to dashboard is usually under 5 seconds.

Identify your users

5

Right after sign-in, tell PostHog who this anonymous person actually is:

posthog.identify(user.id, {
  email: user.email,
  plan: user.plan,
  signed_up_at: user.created_at,
});

From now on, every event from this browser is associated with that user. PostHog stitches the anonymous pre-sign-in events to the identified user — so the funnel "landed on page → signed up → purchased" stays intact.

On sign-out, reset:

posthog.reset();   // clears identity, generates a new anonymous ID

Build a funnel

6

PostHog → Product analytics → Funnels → New funnel. Pick a sequence of events:

  1. page_view (on landing page)
  2. sign_up_started
  3. sign_up_completed
  4. upload_started

PostHog shows conversion at each step. The biggest drop-off is your highest-leverage UX problem. Funnels docs ↗.

Turn on session replay

7

PostHog → Session replay → Settings → toggle on. (Or pass session_recording: { recordCrossOriginIframes: false } in init.)

Sensitive inputs (passwords, credit cards) are auto-masked. For specific elements, add data-ph-no-capture:

<input data-ph-no-capture type="text" name="ssn">

Replays are scoped to events — you can click any event in PostHog and watch the session that contained it. Useful for "this user signed up but then bounced; what happened?"

Feature flags

8

Roll out a feature to N% of users without redeploying. PostHog → Feature flags → New feature flag. Pick a key (e.g., new-checkout), set rollout to 10%, save.

In your app:

// After init
posthog.onFeatureFlags(() => {
  if (posthog.isFeatureEnabled("new-checkout")) {
    renderNewCheckout();
  } else {
    renderOldCheckout();
  }
});

Bump the percentage as confidence grows. Stop the rollout if metrics go bad. Feature flags docs ↗.

A/B test variants

9

Feature flags can have multiple variants:

const variant = posthog.getFeatureFlag("checkout-button-color");
// returns "control" | "blue" | "green" — randomized per user

if (variant === "green") renderGreenButton();
else if (variant === "blue") renderBlueButton();
else renderControlButton();

PostHog records which variant each user saw. Run for a week, look at conversion per variant. Experiments docs ↗.

Privacy and GDPR

10

Three knobs that matter:

  • EU region — pick during signup if your users are in the EU. Data stays in Frankfurt.
  • Opt-out — for users who've declined analytics in your cookie banner, call posthog.opt_out_capturing(). opt_in_capturing() to re-enable.
  • Anonymize IPs — Settings → Project → toggle Discard client IPs. Reduces PII surface.

Privacy docs ↗ · PostHog legal ↗.

Self-hosted if you need it

11

PostHog is open-source. You can self-host ↗ via Docker Compose or Kubernetes. Production self-hosting is real work — Kafka, ClickHouse, Postgres, Redis, MinIO. Most projects don't bother and use PostHog Cloud.

Don't capture every micro-interaction. Event quotas burn fast when you track every mouse-move. Capture events that map to product decisions: page view, sign up, key feature use, drop-off, conversion. Use session replay for the "what happened in that interaction" view; events are for "how many times did this happen."

Pricing reality

12

Free tier: 1M events + 5K session recordings + 1M feature flag requests per month. Real for early stage. Pricing scales linearly past that. PostHog pricing ↗.

Official references

What's next