> ## Documentation Index
> Fetch the complete documentation index at: https://retain.so/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Connect PostHog

> Stream your existing PostHog events into Retain, no re-instrumentation needed

Already tracking product usage with PostHog? Good news: you don't need to instrument anything twice. PostHog's realtime destinations can forward your events straight to Retain, so churn signals start flowing in minutes.

<Note>
  Retain identifies people by **email**. Make sure your PostHog setup stores an
  `email` property on person profiles (most `posthog.identify()` calls already
  do this). Events from anonymous visitors are skipped.
</Note>

## How it works

PostHog sends each event to Retain as it happens. Retain then:

* Turns `$identify` and `$set` events into customer profiles (email, name, and other traits)
* Records your custom events (e.g. `report exported`) as Retain events, auto-creating them on first sight
* Maps [group analytics](https://posthog.com/docs/product-analytics/group-analytics) (`$groupidentify`, `$groups`) to Retain accounts, so B2B usage rolls up correctly
* Ignores PostHog-internal events like `$pageview`, `$autocapture`, and `$feature_flag_called`
* Deduplicates retries, so a redelivered event never counts twice

Event names are normalized to snake\_case: `Report Exported` becomes `report_exported`.

## Set it up

<Steps>
  <Step title="Copy your Retain write key">
    In Retain, go to **Settings → Project token** and copy your write key (it
    starts with `rk-`).
  </Step>

  <Step title="Create the destination in PostHog">
    In PostHog, open **Data → Destinations → New destination**, search for
    **Retain** and select it.
  </Step>

  <Step title="Paste your write key">
    Paste the write key into the **Retain write key** field. That's the whole
    configuration.
  </Step>

  <Step title="Filter to the events that matter">
    In the destination's **Filters**, select your key product events plus
    `$identify`. Two reasons: Retain's churn detection works best on
    high-signal events, and PostHog bills realtime destinations per trigger
    event (the first 10k per month are free), so filtering keeps you in the
    free tier.
  </Step>

  <Step title="Test and enable">
    Use PostHog's **Start testing** button to fire a test event, then enable
    the destination. Events show up in Retain under
    [**Events**](https://retain.so/dashboard/events), and identified users
    under **Customers**.
  </Step>
</Steps>

## Configure your events

Once events arrive, set their **Importance** and **Expected frequency** on the [Events page](https://retain.so/dashboard/events) so Retain knows what healthy usage looks like. See [Track events](/docs/guides/track) for what each setting does.

## Troubleshooting

* **Events aren't showing up.** Check the destination's logs in PostHog. A `401` means the write key is wrong — copy it again from **Settings → Project token** in Retain.
* **Events arrive but no customer is created.** The person has no valid `email` in their PostHog person properties. Retain skips events it can't tie to an email.
* **An event appears with a different name.** That's the snake\_case normalization. `Signed Up` in PostHog is `signed_up` in Retain.
* **`$pageview` never arrives.** By design — PostHog-internal `$` events are ignored. Track a meaningful custom event instead.
