Skip to main content

⚡ Add this skill

One command

Add the Autoplay PostHog session replay provider skill for an existing PostHog setup.
View the docs →

Agent onboarding

Fetch this skill when a customer already uses PostHog as a session replay provider and wants Autoplay live user activity.
View the skill →
Prerequisite: install the SDK first — see Quickstart.
This guide assumes you already have PostHog set up and capturing events in your app. Register with your existing PostHog project id; Autoplay issues an opaque product_id for the ingest URL and live-activity reads. If you don’t have a PostHog project yet, see PostHog’s docs to set one up first, then come back here.
What Autoplay needs from your PostHog project:
  • Project ID — links your PostHog project to the Autoplay product Autoplay will issue. Find it in the URL while logged into your project (the numeric value following /project/), or under Project Settings in the sidebar.
  • Project API Key (phc_...) — the public key your posthog.init() call already uses.
  • Personal API Key (phx_...) — only needed if you want the SDK to create the webhook destination for you (Step 3, Option A).

🎯 Step 1 — Get credentials from your existing PostHog setup

Find your Project ID and Project API Key (Settings → Projects → [Your Project] → General; the key starts with phc_ — not the phx_ Personal API Key, which posthog.init() rejects). 📺 How to find your PostHog Project ID and Project API Key
Save your Project ID — you will use it to register in Step 2 and configure the destination in Step 3. Your app should already have posthog-js installed and initialized — see PostHog’s library docs if you need to check the install/init() pattern for your framework (that page already shows the full posthog.init(...) call — no need to repeat it here). The one Autoplay-specific addition, inside your init’s loaded callback:
api_host must match the destination’s region. Whatever host your posthog.init() sends events to (us.i.posthog.com or eu.i.posthog.com) must be the same region you pass as host when registering the destination in Step 3 (PostHogProvider.create_destination(host=...)). If they don’t match, nothing flows — PostHog itself has no way to warn you about this, since it’s specific to how Autoplay provisions the destination.
Required: identify users on login. Your app most likely already calls posthog.identify() with your own user id somewhere in the login flow (never the anonymous posthog.get_distinct_id()) — see PostHog’s identify docs if you need to check the general identify() / reset() pattern (that page already covers login/logout and why to avoid the anonymous id). The Autoplay-specific addition: include product_id in the identify traits (email is optional but recommended — it enables email-based scoping). This makes PostHog’s distinct_id equal your app’s user id — so the same id reaches Autoplay as user_id — and links earlier anonymous activity to the identified person. Merge these fields into your existing call (or use this as the full call if you don’t have one yet):
Don’t call posthog.identify(posthog.get_distinct_id(), …) — that re-stamps the anonymous id and never sets a real user id. Always pass your app’s stable user id. Until a user logs in they stay anonymous (that’s expected); the session_id still scopes everything.
Running an Autoplay experiment? Set autoplay_experiment_group and autoplay_experiment_id (or any custom traits) based on whatever condition decides eligibility. After PostHog receives the identify call and a later event for that user, these ride through as person properties and can be used to filter the destination you create in Step 3 — so only the autoplay group’s events stream to Autoplay while comparison-group activity stays in PostHog.
👋 Quick Tip: Once you add this code to your site, jump into our Discord and say hi — we will check your data is flowing and help you get fully set up!
Identity plumbing for widget-based support AI agents: make sure the same user identity flows across all three layers: PostHog distinct_id / user_id, your chat widget session metadata, and the support AI agent backend sender identifier. If those do not match, chat replies will look like “no recent activity” because events are stored under one key and fetched with another.

📝 Step 2 — Register your product with Autoplay

Now that your website is tracking clicks, we need to create a secure “ingest_url” (Webhook URL) and a shared secret (X-PostHog-Secret) so that data can be safely sent to Autoplay. The autoplay-sdk was installed on the Quickstart page. Create a Python file with the script below, replace the placeholders with your values from Step 1, and run it once:
This will print the following fields:
  • product_id: prod_wQ7r8kF9... — the issued Autoplay id
  • provider: posthog
  • provider_project_id: YOUR_POSTHOG_PROJECT_ID
  • ingest_url: https://connector.autoplay.ai/ingest/prod_wQ7r8kF9...
  • ingest_secret: {secret} — PostHog sends this as the X-PostHog-Secret header
  • mcp_url: https://mcp.autoplay.ai/mcp
  • mcp_key: {secret} — your agent’s Bearer token
  • owner_token: {secret} — shown only on first registration; save it securely
Save what prints in the terminal — you will need these values in Step 3 and Step 4:
  • Step 3 (PostHog webhook): use the ingest_url and ingest_secret printed above
  • Step 4 (read live activity): use the mcp_url and mcp_key printed above (mcp_key is your Bearer token)
  • Future re-registration/rotation: save owner_token; it is required and is not shown again
Re-registering your product
  • A second onboard_product with the same provider/project pair returns 409 unless you pass the saved owner_token.
  • Re-run with owner_token="<saved token>". You must still pass contact_email on every registration.
  • After a successful re-registration, the ingest_secret rotates. Update PostHog (Step 3) so X-PostHog-Secret matches the new secret.

🔗 Step 3 — Set up your PostHog webhook

Now we must tell the website tracker (Step 1) to send its data to the secure address (webhook) you just generated (Step 2). You have three choices: Option A — Automated with the SDK (recommended) Let the SDK create and verify the destination for you — no clicking around in PostHog, no pasting Hog code. Run this once with the values from Step 2:
Where to find your PostHog Personal API Key: In PostHog, go to Settings → [Your name] → Personal API keys → Create personal API key. Give it project:read and hog_function:write permissions — see PostHog’s Personal API key docs if you need more detail. This is different from the Project API Key used in posthog.init().
📺 Generate your PostHog Personal API Key
It’s idempotent — it creates the “Autoplay Event Stream” destination (or updates it) and confirms it’s enabled, so you can re-run it safely. Option B — Managed
  • Join our Discord and say hi.
  • We configure the PostHog webhook for you.
  • You receive a 1Password link with your ingest_url, ingest_secret, and mcp_key.
Option C — Fully manual (advanced) Add the destination by hand in PostHog — only needed if you can’t run Option A:
  • In PostHog, add a Webhook destination.
  • Webhook URL: paste the ingest_url printed by Step 2.
  • X-PostHog-Secret header: paste the ingest_secret printed by Step 2. Do not create a new secret.
PostHog still requires the form-level Webhook URL field even if your Hog source code also sets let url := .... For the general mechanics of adding a webhook destination in PostHog’s UI, see PostHog’s destinations docs — the Autoplay-specific part is the Hog source below, which shapes PostHog’s event data into the payload Autoplay expects. PostHog webhook setup walkthrough
Paste this into the Event Body / Source field of your PostHog webhook destination:
Optional: limit streaming to an experiment cohort If you’re running an Autoplay onboarding experiment, filter the destination you just created (whichever option above you used — the destination is the same “Autoplay Event Stream” hog function either way) so only the experiment group’s events reach Autoplay:
  1. In PostHog, go to Data pipeline → Destinations and open Autoplay Event Stream.
  2. Add a filter condition on the property you set in Step 1Person properties → autoplay_experiment_group → equals → autoplay, optionally combined with any other eligibility property (e.g. plan → equals → trial).
  3. Use the destination’s built-in Testing tab to send a real event and confirm it only fires for a person carrying that property.
PostHog destination Filters panel: '+ Filter' under Filters, set to where autoplay_experiment_group equals autoplay
This means PostHog will not forward comparison-group events to the Autoplay connector for this destination. Keep the assignment stable in your app or experimentation system so users do not move between groups during the trial. See PostHog’s destination filtering docs for the general filter-builder walkthrough — the Autoplay-specific part is just which property to filter on, not the mechanics of PostHog’s filter UI.
Validated against a live PostHog project. A destination filtered to autoplay_experiment_group (person property) exact-matching autoplay only invoked for events from a person carrying that value — a comparison-group person’s $identify and $pageview events never triggered it, while the same events reached an unfiltered destination normally. PostHog compiles a properties condition like this into the same filters field the dashboard and API both read, so it behaves identically regardless of whether the destination was created via Option A, B, or C above.Unlike Amplitude’s template, the Hog script above only forwards a fixed set of fields to Autoplay (event, email, timestamp, session_id, current_url, etc.) — it does not include autoplay_experiment_group/autoplay_experiment_id in the payload itself. These properties only gate whether the destination fires; they won’t appear in the activity Autoplay stores.PostHog’s own filter UI warns: “You are filtering on Person properties. Be aware that this filtering applies at the time the event is processed so if Person Profiles are not enabled or the person property has not been set by then then the filters may not work as expected.” In practice: make sure the identify() call from Step 1 fires before the events you want filtered, not after.
Do not rely on Autoplay to tell you who was excluded. If comparison-group events are filtered out here, they never reach the Autoplay connector — Autoplay only ever sees the autoplay group. Keep the experiment assignment in your app, PostHog, or your warehouse as the source of truth for evaluation, and compare conversion by autoplay_experiment_group (or your equivalent property). Keep the assignment stable in your app — don’t randomize it on each page load.

📡 Step 4 — See your activity land

Everything is wired up! The connector is pull-based — instead of streaming, you (or your agent) ask for a user’s recent activity the moment you need it. Let’s confirm your events are landing. Click around your app while logged in as an identified user, then fetch that user’s activity with the mcp_key you saved from Step 2:
  • YOUR_USER_ID — the stable id you pass to posthog.identify(...).
  • YOUR_AUTOPLAY_PRODUCT_ID — the issued product_id printed by Step 2.
  • YOUR_MCP_KEY — the mcp_key printed by Step 2.
What you’ll get back — the user’s recent footsteps, ordered oldest → newest:
A 200 with a populated actions array means your events are flowing. An empty array means the user identified but hasn’t browsed yet (activity is built from $pageview / $autocapture), or the events haven’t landed yet — click around and give it a few seconds.
This REST call returns the exact same data your agent reads — the agent just pulls it over MCP (the get_live_user_activity tool) instead of curl. That’s the next step.

🔌 Next: connect your AI support agent

Your activity is now flowing into the connector. Head back to Quickstart to choose your existing AI support agent and connect it via MCP — it then pulls a user’s live activity on demand, the moment it needs context to answer.

Choose your AI support agent

Fin (Intercom), Maven, Ada, Botpress, and more — pick yours and connect via MCP.
For structured logging and extra field conventions used across the SDK, see Logging. Release history is on the Changelog.