posthog/experiment-audit
Audit a PostHog A/B experiment for a customer — verify config, exposure, attribution, and metrics. Trigger phrases include \"audit [customer]'s experiment\", \"audit the [name] experiment\", \"check experiment setup for [customer]\", \"validate this A/B test\", or any request to review whether an experiment is correctly wired up. Assumes you already have MCP access to the customer's project (typically via the impersonation flow set up by the `impersonate-audit` wrapper that ships with this plugin).
npx skills add https://github.com/PostHog/skills --skill experiment-audit
Verify that a customer's experiment is actually collecting variant data, that downstream attribution survives the funnel, and that the metrics measure what the customer thinks they measure. Output is a Slack-ready writeup grouped by the four questions customers almost always ask.
The skill assumes the active PostHog MCP is scoped to the customer's project, not yours. Always start with:
> "What project am I in? List the most recent 5 experiments."
If the project name looks like your own internal project (e.g. "PostHog App + Website", id 2), STOP — the impersonation isn't routing correctly. Re-run the wizard or check /mcp auth before continuing.
Use experiment-list with search to find the experiment by name. Then pull the full record. Capture:
device_id vs user_id), and ensure_experience_continuity.$feature_flag_called or a custom event.For the linked flag:
$current_url = ...) — uses the *latest URL the person has been seen on*, not the current page. Stale by definition. Always flag as a problem.$current_url is captured as the full URL (https://host/path). Exact-matching /path will never hit.ensure_experience_continuity setting on the flag (this overrides the experiment-level setting).Pull $feature_flag_called events for the flag key since the experiment start date.
$feature_flag_response. Should split close to 50/50 between the variant names (e.g. control / test). Flag a sample ratio mismatch if imbalance exceeds ~5% with non-trivial volume.$feature_flag_response returns false for most events, the user isn't being bucketed into the experiment at all — the release condition is rejecting them. This is the most common cause of "experiment shows 0 exposures."$current_url, $device_type, $feature_flag, $feature_flag_response, and distinct_id.For each metric event (CTA click, signup page visit, signup completion, conversion):
$feature/<flag-key> property with a real variant value (control or test), not false or missing.$pageview containing /signup"), it will credit both variants for global traffic regardless of source. Suggest scoping by $feature/<flag-key> property or session entry pathname.Cross-domain handoff (Webflow → app, marketing → product, etc.) is where attribution usually dies.
$feature_flag_called event with a real variant value.$identify fires on the handoff. If users never have an $identify event, the anonymous device profile never stitches to the authenticated user — variant attribution is dead even with a perfectly fired flag.ensure_experience_continuity settings together don't cause re-bucketing. device_id bucketing without continuity = same user on a new device looks fresh.Customers often have a primary conversion event that lives downstream (in their app or warehouse).
plus_trial_activated, trial_started, subscription_created).external-data-sources-list. Common pattern: Snowflake/Postgres table like accounts.trial_started_at.The customer's actual setup almost always has one of these:
$identify on the marketing → product domain handoffdevice_id bucketing without ensure_experience_continuity → re-bucketing across sessionsGroup the report by the four standard customer questions. Lead with the worst finding:
:warning: [Experiment name] — audit findings
[One-paragraph TL;DR of the headline finding. Be direct.]
---
(a) Does the config look correct?
[Verdict + specific issues with evidence — event counts, sample values, etc.]
---
(b) How to verify attribution (once issues are fixed)
[Concrete steps the customer can run themselves.]
---
(c) What to change about attribution
[Numbered action list, priority order. Each item should be specific
enough that the customer's engineer can act on it directly.]
---
(d) Common pitfalls to watch for
[Subset of step 7's checklist relevant to this customer's setup.
Frame as general guidance, not as accusations.]
---
Bottom line: [one or two sentences. What's the single most important
fix that unblocks the experiment?]
Remind the user to:
claude plugin disable posthogThe impersonate-audit.sh wrapper handles step 3 prompts automatically on exit.
Take posthog/experiment-audit from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.