.claude/skills/posthog-web-analytics-diagnosis/SKILL.md
Diagnose PostHog web analytics issues including missing pageviews, incorrect bounce rates, broken channel attribution, missing UTM data, reverse proxy problems, and discrepancies with other analytics tools.
npx skillsauth add mongo-ai/posthog-triage-agent posthog-web-analytics-diagnosisInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
docs-search("web analytics troubleshooting {specific symptom}")docs-search("web analytics installation {framework}")gh search issues --repo PostHog/posthog-js "web analytics {symptom}"The steps below are a diagnostic FRAMEWORK (what questions to ask, in what order). The docs responses are the CONTENT (current answers, version requirements, config details).
Determine whether the web analytics problem is caused by:
$pageview events being capturedWeb analytics relies on $pageview, $pageleave, and autocapture events.
SELECT event, count()
FROM events
WHERE event IN ('$pageview', '$pageleave', '$autocapture')
AND timestamp > now() - interval 7 day
GROUP BY event
ORDER BY count() DESC;
If zero $pageview events → SDK not installed or not capturing. Go to Step 2.
If $pageview exists but numbers look wrong → Go to Step 3.
Run docs-search("web analytics installation {framework}")
Key areas to investigate:
capture_pageview enabled? (it's true by default, but may be manually disabled)capture_pageleave enabled? (needed for bounce rate and session duration)-- Check SDK version in use
SELECT properties.$lib, properties.$lib_version, count()
FROM events
WHERE timestamp > now() - interval 7 day
GROUP BY properties.$lib, properties.$lib_version
ORDER BY count() DESC;
| Framework | Common issue | Fix |
|-----------|-------------|-----|
| Next.js App Router | No pageviews on client navigation | Need PostHog provider with router integration |
| React Router | Only captures initial load | Need useLocation() listener to capture navigations |
| Vue Router | Same as above | Need router.afterEach() hook |
| Nuxt | SSR vs client mismatch | Need client-only plugin initialization |
docs-search("reverse proxy setup PostHog ad blocker")Bounce rate requires both $pageview and $pageleave events.
-- Check if pageleave events are being captured
SELECT count()
FROM events
WHERE event = '$pageleave'
AND timestamp > now() - interval 7 day;
If zero $pageleave → capture_pageleave is likely disabled or SDK is too old.
Run docs-search("web analytics bounce rate pageleave")
Session duration is calculated from $start_timestamp to $end_timestamp on the sessions table.
-- Check session durations
SELECT
avg($session_duration) as avg_duration,
median($session_duration) as median_duration,
max($session_duration) as max_duration
FROM sessions
WHERE $start_timestamp > now() - interval 7 day;
-- Check if UTM data is being captured
SELECT
properties.$utm_source as utm_source,
properties.$utm_medium as utm_medium,
properties.$utm_campaign as utm_campaign,
count()
FROM events
WHERE event = '$pageview'
AND timestamp > now() - interval 7 day
AND properties.$utm_source IS NOT NULL
GROUP BY utm_source, utm_medium, utm_campaign
ORDER BY count() DESC
LIMIT 20;
If zero UTMs → check if the marketing URLs actually contain UTM params, or if a redirect is stripping them.
Run docs-search("web analytics channel type attribution")
PostHog uses session entry properties for channel classification. Check:
SELECT $channel_type, count()
FROM sessions
WHERE $start_timestamp > now() - interval 7 day
GROUP BY $channel_type
ORDER BY count() DESC;
If most traffic shows as "Direct" when it shouldn't → referrer may be stripped by:
Common reasons PostHog and GA/other tools show different numbers:
| Difference | Why |
|-----------|-----|
| PostHog shows fewer pageviews | Ad blockers blocking PostHog but not GA (via GTM) |
| PostHog shows more pageviews | GA sampling data; PostHog doesn't sample |
| Different bounce rates | Different definitions — PostHog uses $pageleave, GA uses interaction events |
| Different session counts | Different session timeout windows (PostHog: 30min, GA: 30min default but configurable) |
| Different user counts | Different identity resolution — cookies, cross-device tracking |
| UTM attribution differs | Different attribution models (PostHog: session entry, GA: last click by default) |
The most common cause is ad blockers. Recommend reverse proxy to close the gap.
Search GitHub with at least 2 variants:
gh search issues --repo PostHog/posthog-js "web analytics {symptom}"gh search issues --repo PostHog/posthog "web analytics {symptom}"capture_pageview disabled, or wrong project token$pageleave not captured, enable capture_pageleavebusiness
Final synthesis skill. Produce a structured, evidence-graded triage report with a clear root-cause assessment, honest confidence, and a ready-to-send customer response.
tools
Normalize an incoming support ticket into structured investigation inputs: product area, identifiers, scope clues, URLs, timeframe, and likely first diagnostic path.
development
Diagnose PostHog survey issues including surveys not appearing, targeting mismatches, response collection failures, display timing problems, and API-mode survey integration issues.
development
Format and post triage reports to Slack using optimized mrkdwn layout. Use after generating a triage report to post it to the #support-triage channel or any specified channel.