docs-utm-analyzer — Match UTM campaigns to landing-page reality
Marketing posts promise X. Users arrive with ?utm_campaign=launch-hn expecting X. They land on quick-start.md which is about Y. They bounce in 8 seconds. This skill finds those mismatches with numbers.
When to run#
- Weekly during active campaigns.
- After every major launch (HN, Product Hunt, blog post, ad burst).
- When
get_analyticsshows a referrer surge without a corresponding signup bump.
Workflow (4-stage pipeline)#
This skill is a thin orchestrator over four pinned subagents that already live in the docs-insights Claude Code plugin. If those subagents are not installed, instruct the user to /plugin install docs-insights@docs-claude-plugins first.
Stage 1 — Collect (Haiku)#
Invoke the analytics-collector subagent:
SLICE: utm
WORKSPACE: <resolved id or owner/repo>
PERIOD: <iso-from>..<iso-to>
OUTPUT: .docsbook/insights/.tmp/utm-dump-<iso>.json
LIMIT: 1000
Wait for WROTE: <path>.
Stage 2 — Cluster (Sonnet)#
Invoke analytics-clusterer:
DUMP: <path from stage 1>
OUTPUT: .docsbook/insights/.tmp/utm-clustered-<iso>.json
TOP_N: 15
MIN_CLUSTER_SIZE: 5
Wait for CLUSTERED: <path>.
Stage 3 — Report (Sonnet)#
Invoke analytics-reporter:
CLUSTERED: <path from stage 2>
SCHEMA: <plugin-root>/schemas/insight.schema.json
OUTDIR: .docsbook/insights/
SKILL: docs-utm-analyzer
SKILL_VERSION: 1.0.0
Wait for REPORT_JSON: and REPORT_MD:.
Stage 4 — Archive (Haiku)#
Invoke insights-archivist:
INSIGHTS_DIR: .docsbook/insights/
NEW_REPORT_JSON: <path from stage 3 REPORT_JSON>
Wait for INDEX: / DIFF: / ROTATED:.
Stage 5 — Tell the user#
Print:
✅ docs-utm-analyzer ran.
Report: .docsbook/insights/latest/docs-utm-analyzer.md (human)
JSON: .docsbook/insights/latest/docs-utm-analyzer.json (machine)
Diff: .docsbook/insights/latest/docs-utm-analyzer.diff.json (since last run)
Findings: <critical_count> critical · <high_count> high · <medium_count> medium
Top finding: <summary.headline>
Next steps:
• Read the Markdown report for context
• Pass the JSON to the actor agent (forthcoming) or feed it to your own /apply pipeline
• Re-run weekly during active campaigns
What this skill catches#
| Pattern | Example finding |
|---|---|
| UTM with high bounce | utm_campaign=launch-hn → 800 pv on quick-start.md, 78% bounce. Headline of quick-start.md doesn't match the HN post's hook. |
| UTM with zero conversion | utm_source=ph → 1.2k pv, 0 clicks on Upgrade. The PH copy promised pricing — link to pricing.md instead. |
| Missing landing page | UTM landed on 404 or root. Suggest creating the campaign-specific landing doc. |
| Successful campaign signal | High pv + low bounce + clicks on conversion CTAs. Marked as info — replicate the formula. |
Guardrails#
- PRO+ only —
query_eventsis gated. Exit early if the workspace plan is belowpro_pluswith a clear upgrade message. - Do not modify any doc pages. This is a read-only analyzer. Action is delegated to the actor agent that reads the JSON.
- Min volume — clusters with
pageviews < 50are dropped by the clusterer; do not surface low-confidence findings. - PII — never include raw
referrerquery strings in the report. The collector already strips them.
Output for downstream consumption#
The JSON report at .docsbook/insights/latest/docs-utm-analyzer.json conforms to insight.schema.json.
Each finding's suggested_actions[] is pre-filled so a future actor agent can:
- Open a GitHub Issue per high-bounce UTM/landing pair (
action_type: open_github_issue) - Invoke
docs-editorto rewrite the landing page headline (action_type: invoke_skill,skill_to_invoke: docs-editor) - Drop a Slack note for traffic anomalies (
action_type: notify_slack)
Acceptance criteria#
- All four pipeline subagents invoked in sequence.
- Final JSON validates against
insight.schema.json(schema_version: 1). - Two files written:
<ts>__docs-utm-analyzer.jsonand<ts>__docs-utm-analyzer.md. -
latest/symlinks updated. - Diff against previous run computed when prior run exists.
- Skill exits early with PRO+ upgrade message if workspace is not PRO+.
Arguments#
| Argument | Type | Default | Description |
|---|---|---|---|
workspace |
string | required | Workspace id or owner/repo |
period |
string | 30d |
7d / 14d / 30d / 90d |
limit |
number | 1000 |
Max raw rows the collector pulls |
Related skills#
docs-engagement-analyzer— what users do after landingdocs-funnel-mapper— multi-step journey analysisdocs-gap-finder— what to write next (different question entirely)