Activation Funnel Diagnosis with Claude Code, Step by Step
Date: July 6, 2026 • Author: Second Axis
Activation is the closest metric to revenue a PM actually owns. The funnel between "created an account" and "did the thing that makes them stay" is yours, and when a step in it drops eight points overnight, the question lands on your desk within the hour: why?
Today the answer comes from a grim ritual: pull the funnel by segment, eyeball last week's deploys, ask support if anything's up, then start watching session replays one by one. As one PM put it on r/ProductManagement, manually watching session replays "is super time-consuming and hard to know what actually matters". Hours later you have a hunch, a screenshot, and no way to prove the hunch over the four other stories your team believes.
Can you build the diagnosis itself with Claude Code? Yes. Not the hunch, the diagnosis: a ranked list of causes, each with evidence for and against, each traceable to a query you can rerun. Same spirit as the churn analysis playbook: every step, no hand-waving.
What you're building
Two loops, one cheap and one triggered:
- A daily detection check that computes conversion for every funnel step against a trailing baseline and stays silent unless a delta is material.
- A triggered diagnosis run when detection fires (or on a weekly cadence). A generator agent proposes 5-7 candidate causes: release regression, traffic-mix shift, a specific segment, a specific browser or platform, an upstream change. A verifier agent pulls evidence for and against each from the actual sources: funnel queries by segment, error data, support tickets, the release timeline, session-replay aggregates. A critic kills hypotheses whose evidence doesn't hold.
- The output: a committed diagnosis document per incident, causes ranked, every claim citing a query result, confidence levels stated, next tests recommended.
- A memory that compounds: every hypothesis ever tested lives in a registry with its evidence and verdict, so "was it the pricing-page change again?" gets answered from the record, not re-investigated.
Why plausible causes are cheap
The naive version is one prompt: "activation dropped, here's some data, why?" It fails because a language model can generate five plausible causes in ten seconds, and so can your team in a meeting. Plausibility was never the bottleneck. The bottleneck is evidence, and evidence is work: a segment cut showing the drop is confined to mobile Safari, a deploy timestamp two hours before the inflection, a ticket cluster naming the exact step. A diagnosis is only as good as the claims it proves and the appealing stories it rules out.
The second failure is the replay trap. Replays feel like ground truth, but watching them is linear human time against a problem that needs aggregates. The scalable move is to treat your replay platform as a stats source: rage-click counts, abandonment coordinates, drop-off timing distributions. Agents read the aggregates; humans watch exactly three exemplar replays, linked in the final report, only for hypotheses that survived the critic. Aggregates first, eyeballs last.
So the architecture is a judge loop over evidence: generate cheaply, verify in parallel, and let a critic enforce the standard of proof.
Phase 0: Prerequisites
- Claude Code installed (
npm install -g @anthropic-ai/claude-code) and authenticated, on a Pro, Max, Team, or Enterprise plan for the scheduling and publishing steps. - Query access to your funnel. Either an analytics MCP connection (PostHog's official MCP server covers funnels, events, and session-recording data) or warehouse access via Google's MCP Toolbox for Databases if events land in BigQuery or Postgres.
- Read access to the other evidence sources: your support tool, your tracker, your repo. Wiring specifics in Phase 4.
- A git repo dedicated to this system, because the hypothesis registry only works as committed history.
- A head start: Anthropic's knowledge-work-plugins include a Product Management plugin with
/metrics-reviewscaffolding. Useful, but the thresholds, agent trio, and registry below are this playbook, not the plugin.
Phase 1: The diagnosis repo
activation-diagnosis/
├── CLAUDE.md # brief for every session
├── .mcp.json # posthog / warehouse / tracker connections
├── .claude/
│ └── agents/
│ ├── generator.md # proposes candidate causes
│ ├── verifier.md # gathers evidence for AND against
│ └── critic.md # kills what doesn't hold
├── funnel/
│ ├── definition.yaml # steps, source queries, expected ranges
│ └── thresholds.yaml # what counts as a material drop
├── registry/
│ └── hypotheses.jsonl # every hypothesis ever tested
├── incidents/ # committed: one folder per diagnosis
│ └── 2026-07-06-step3-drop/
│ ├── evidence/ # query results, one file per claim
│ └── diagnosis.md # the ranked, cited verdict
└── scripts/
└── check_funnel.py # daily detection query
Two files are the soul of this repo.
funnel/definition.yaml is your funnel as code: each step's name, the exact source query that computes it, the expected conversion range, and seasonal caveats ("step 2 dips every Monday; B2B signups don't activate on weekends"). Committing it means the detection script and every agent read one definition instead of improvising queries, and a funnel change becomes a reviewable diff, not a silent dashboard edit.
registry/hypotheses.jsonl is the anti-re-litigation memory, one line per hypothesis ever tested:
{"id": "H-2026-05-14-03", "incident": "2026-05-14-step2-drop",
"hypothesis": "Safari 17 autofill breaks the signup form",
"verdict": "ruled_out",
"evidence": ["evidence/safari-segment-cut.json"],
"reason": "Safari share of step-2 entrants flat; drop uniform across browsers",
"date": "2026-05-15"}
The generator reads this file before proposing anything. A hypothesis ruled out in May doesn't get re-investigated in July unless new evidence is cited; one confirmed before gets checked first next time. This is the compounding asset: after ten incidents, the registry knows more about your funnel's failure modes than anyone on the team. Continuity across runs is engineered, not switched on: this file, committed, read at step one of every run.
CLAUDE.md carries the rules: work only from funnel/definition.yaml queries, check the registry before generating, and every evidence claim gets a file in evidence/.
Phase 2: Drop detection
check_funnel.py runs daily and does deliberately little: for each step in definition.yaml, compute conversion for the trailing 7 days, compare against a trailing 28-day baseline, and apply thresholds.yaml:
step_3_checkout:
min_absolute_delta: 3.0 # percentage points vs baseline
min_sample: 200 # entrants below this: never alert
sustained_days: 2 # one bad day is noise
Only a material, sustained delta on adequate sample triggers the full diagnosis. This gate keeps the system cheap and credible: the expensive loop runs a few times a month, and when it fires, people know it's real. Thresholds are committed and tuned like code; they are the alert-fatigue dial. Detection commits its daily numbers either way, so every diagnosis has a clean time series to point at.
Phase 3: The hypothesis loop
Three agent files in .claude/agents/; the division of labor between them is the quality mechanism.
generator.md proposes 5-7 candidate causes for the specific drop: a release regression, a traffic-mix shift (a new campaign flooding the funnel with low-intent signups), a specific segment, browser, or platform, an upstream change (an email provider, an OAuth partner). Its rules: read registry/hypotheses.jsonl first and exclude anything already ruled out for the same signature; every hypothesis must name the query that would kill it.
verifier.md takes one hypothesis and gathers evidence for and against from the Phase 4 sources. Its non-negotiable rule:
Every evidence claim MUST have an attached query result saved to
incidents/<id>/evidence/. "Mobile conversion fell" is not evidence.
"Mobile step-3 conversion 41% -> 29% (evidence/mobile-cut.json),
desktop flat at 55% (evidence/desktop-cut.json)" is evidence.
Report the strongest fact AGAINST the hypothesis with the same
rigor as the facts for it. If you found nothing against it,
say which disconfirming query you ran and what it returned.
Verifiers fan out in parallel, one per hypothesis, each with its own context window.
critic.md is the judge; its checklist is short and mean:
For each surviving hypothesis:
1. RECOMPUTABLE: rerun 2 cited queries from the evidence files.
Numbers must match. Mismatch -> FAIL the hypothesis.
2. TIMELINE: does the proposed cause precede the drop date in
the detection series? A deploy after the inflection cannot
be the cause.
3. SEGMENT MATH: do the segment cuts add up? A "mobile-only"
cause must not require desktop to also fall to explain the
total delta.
4. NO TAUTOLOGIES: "users who don't complete step 3 convert
worse" is the definition of the drop, not a cause.
Rank survivors by evidence strength. Assign confidence:
high / medium / low, with the single fact that earns it.
One loop's output is incidents/<id>/diagnosis.md: surviving causes ranked with confidence levels, killed hypotheses with cause of death, links to three exemplar replays for the top cause, a "what would change our mind" section naming the query that would overturn the verdict, and recommended next tests. Every hypothesis, surviving or killed, is appended to the registry. Commit everything.
Phase 4: Wiring the evidence sources
This is a multi-tool system by nature. Project-scoped .mcp.json, committed so every session and teammate gets identical connections:
- Funnel and event queries: PostHog's official MCP server, or your warehouse via MCP Toolbox if events live in BigQuery or Postgres. Covers segment cuts, error-event counts, and traffic-mix queries.
- Session-replay aggregates: rage-click counts, abandonment points, and per-step recording stats via the same analytics connection. Agents consume numbers and link exemplar recording URLs; nobody's context window watches a video.
- Support tickets: Intercom has an official MCP server (US workspaces); Zendesk has none official, so use the community reminia/zendesk-mcp-server or a small export script. The verifier searches tickets mentioning the step by name and by symptom.
- Release timeline: deploys and merged PRs from GitHub via the
ghCLI in Bash; ticket and flag history from Jira via the official Atlassian MCP server or Linear's official server. The release-regression verifier diffs the drop date against everything shipped in the surrounding 72 hours, feature flags included.
One churn-playbook discipline applies unchanged: MCP is for targeted queries, not bulk export. A verifier asks "step-3 conversion by browser, last 14 days"; it does not page through raw events.
Phase 5: Scheduling
Two cadences, one mechanism.
The daily detection run is a cloud routine: /schedule (or claude.ai/code/routines), daily, prompt: "run scripts/check_funnel.py, commit the daily numbers; if any threshold in funnel/thresholds.yaml trips, continue into the full diagnosis loop." The routine clones the repo's default branch, inheriting the funnel definition, thresholds, and registry automatically; that clone is the state-passing mechanism, and the reason everything lives in git. Output comes back as commits on a claude/ branch, or direct push if you decide the repo warrants it.
Off-schedule triggers matter more here than in a weekly report: drops don't wait for Mondays. Routines can also fire via an API endpoint with a bearer token, so your existing alerting can kick off the diagnosis the moment it pages a human. Nothing stops you from running it interactively either; same skill, same registry.
The self-hosted alternative is unchanged from the churn playbook: cron plus headless mode (claude -p with --allowedTools scoped to the query tools and the repo), or a GitHub Actions cron with claude-code-action. Add a Stop hook posting run status to Slack, because a detection system that quietly died two weeks before the drop is worse than none.
Before scheduling anything, run the loop interactively on a past incident whose ending you know. If the critic doesn't reach the same verdict with evidence attached, tune the agents now, not during a live incident.
Phase 6: Sharing with the team
When detection fires, a Slack message goes out immediately: which step, how big, against what baseline, "diagnosis running." Slack has no official MCP server; use the community korotovsky/slack-mcp-server or a plain webhook script, which is plenty for an alert. When the diagnosis lands, a second message follows with the top-ranked cause, its confidence, and a link.
The link target: publish diagnosis.md as an artifact page on claude.ai, so the exec asking "why did activation drop" gets a readable page, not a repo URL. The churn playbook's caveats apply verbatim: publishing works from the CLI and desktop app but not from every automated surface, and org-scoped visibility needs a Team or Enterprise plan. The publish step is a reasonable place for the human who reviews the claude/ branch to stay in the loop; a diagnosis deserves one pair of eyes before it circulates.
Phase 7: Maintenance (what you own now)
- Funnel definition upkeep. Step 2 gets redesigned, an onboarding screen disappears, a new required step appears. Each is an edit to
definition.yamlwith expected ranges rebased. A stale definition produces confident diagnoses of a funnel that no longer exists. - Threshold tuning. Too tight and the team learns to ignore alerts; too loose and you hear about drops from your CEO instead of your bot. Revisit
thresholds.yamlafter every false alarm and every missed drop, in a PR, with the incident linked. - Registry hygiene. Verdicts age; a hypothesis ruled out in March can become true after an August rewrite. Give entries a review-by date tied to major releases, and let the generator resurface expired verdicts as "previously ruled out, evidence stale."
- Evidence-source drift. Event names get renamed, the support tool migrates, a token expires. Add a source health check to the daily run: each source must answer a trivial query, and a failure alerts loudly instead of letting verifiers report "no evidence found."
- Prompt drift. The critic's checklist grows one line per bad diagnosis. Treat
.claude/agents/like code, with PR review, because an edit there changes what your team believes about why users leave.
What this costs
- Detection is nearly free. One script run, a comparison, a commit: a few thousand tokens a day, noise inside any subscription tier.
- A diagnosis run is a bounded fan-out. Assume 6 hypotheses, one verifier each. A verifier reads the funnel definition and registry context (~3K tokens), runs 5-10 targeted queries returning a few hundred tokens each, and writes a ~1K-token memo: 10-15K tokens per verifier, ~60-90K across the fan-out, plus generator and critic passes for perhaps another 30-40K. Order of 100-150K tokens per incident, a few times a month, comfortably inside a Pro or Max subscription's included usage; no separate metered line item unless you add one. What blows the budget is an unscoped verifier free-exploring raw events, which the definition-file discipline and
--allowedToolsexist to prevent. - The invoice nobody prints: someone wrote the funnel definition, tuned thresholds through two false alarms, taught the critic its checklist, and owns the registry. That someone is doing diagnostic engineering. The payoff is an evidence standard your team's debates currently lack; the price is a system with an owner, not a prompt.
The four practical challenges
- Setup at scale: not data volume this time, but source breadth. The diagnosis is only as good as the evidence reach (Phases 1 and 4), and wiring five sources with committed config is the real setup work.
- Sharing with the team: the alert-then-diagnosis Slack flow and the published incident page (Phase 6), with the usual plan-tier and automation caveats.
- Maintenance: funnel definitions, thresholds, registry verdicts, and source health all drift with the product (Phase 7).
- Cost: cheap in tokens because the loop is gated and bounded, expensive in the judgment that built the gate. The token math above is the small half of the bill.
The managed alternative
If you want parts of this off the shelf, the adjacent categories are real. Product analytics suites like Pendo and Appcues instrument onboarding funnels and give you conversion dashboards on day one; session tools like FullStory surface friction signals such as rage clicks without you defining them. Those are fair trades where detection is concerned: the dashboards are excellent, and you should not hand-roll what they chart. What they leave to you is this playbook's middle: the hypothesis-to-evidence loop across releases, tickets, and segments. A dashboard shows you the step that fell. Which of six plausible causes explains it, with evidence that survives a critic, is the human part, and it stays yours whichever suite you buy.
Doing this with Second Axis
Everything above is the do-it-yourself path. On Second Axis, activation funnel diagnosis is a workflow in the marketplace: connect your analytics, session replay, tracker, and Slack, choose the workflow, and set the goal ("watch my activation funnel daily, diagnose drops with evidence, alert me with the ranked causes"). It runs continuously from there, hypothesis memory built in, and it monitors itself: broken queries, failed runs, and stale funnel definitions get found and alerted instead of quietly rotting under a green dashboard.