Skip to content

Start analytics on mount, because a prerendered page never re-runs load - #162

Merged
xuelink merged 1 commit into
mainfrom
claude/analytics-init-on-mount
Sep 8, 2026
Merged

Start analytics on mount, because a prerendered page never re-runs load#162
xuelink merged 1 commit into
mainfrom
claude/analytics-init-on-mount

Conversation

@xuelink

@xuelink xuelink commented Sep 8, 2026

Copy link
Copy Markdown
Member

Follow-up to #161, which shipped analytics that never ran.

The bug

initAnalytics() went in the root +layout.ts load, which is where PostHog's SvelteKit guide puts it. That guide assumes a page rendered per request. Every page here is prerendered by adapter-static, and SvelteKit hydrates a prerendered page from the serialised layout data rather than re-running the universal load. So load fired on an internal client-side navigation and never on a visit arriving from outside — which is most of them.

It looked fine in local testing because vite preview reached it through a navigation. On langx.io the deployed bundle carried the key and the whole config, and the PostHog chunk was still never fetched. Not a single page view was counted.

onMount runs on hydration, always.

Verified properly this time

Against the built, prerendered output served as static files and entered cold from outside — the shape that actually ships, not a dev server:

Before After
PostHog chunk fetched on a cold first load no yes
Events reach eu.i.posthog.com/e/ no yes
Cookies / localStorage / sessionStorage empty empty

(The initial $pageview is batched — it flushes on a later capture or on page hide, so it does not appear in the network log in the first few seconds. That is PostHog's normal behaviour, not a second bug.)

It also corrects the cookie policy

Section 3.4 said the SDK fetches a small configuration file from PostHog's asset host. That is what vite preview showed; the real build makes no asset-CDN request and no /flags call. The section now names the one connection that does happen — page views to PostHog's EU endpoint — rather than one that does not. The note in analytics.ts says to re-measure request counts on a real build rather than trust a dev server.

Separately, and not fixed here

static.cloudflareinsights.com is loading on langx.io — Cloudflare Web Analytics, injected by Cloudflare Pages, not by this repo. It predates these PRs, but cookie policy §3.4 currently implies nothing third-party is measuring the site. It is either worth turning off in the Cloudflare dashboard or worth naming in §3.4; that is a decision rather than a fix, so it is not in this PR.

🤖 Generated with Claude Code

The previous commit put `initAnalytics()` in the root `+layout.ts`
`load`, which is where PostHog's SvelteKit guide puts it. That guide
assumes a page rendered per request. Every page here is prerendered by
adapter-static, and SvelteKit hydrates a prerendered page from the
serialised layout data instead of re-running the universal `load` — so
`load` fired on an internal client-side navigation and never on a visit
arriving from outside, which is most of them.

It looked fine locally because `vite preview` reached it through a
navigation. On langx.io the deployed bundle carried the key and the
whole config and the PostHog chunk was still never fetched: no page view
was ever counted. `onMount` runs on hydration, always.

Verified the way it should have been the first time — against the built,
prerendered output served as static files, entered cold from outside:
the chunk is fetched, events reach eu.i.posthog.com/e/, and cookies,
localStorage and sessionStorage all stay empty.

That same measurement corrects section 3.4 of the cookie policy. It said
the SDK also fetches a configuration file from PostHog's asset host,
which is what `vite preview` showed; the real build makes no asset-CDN
and no /flags request at all. The section now names the one connection
that does happen rather than one that does not, and the note in
analytics.ts says to re-measure request counts on a real build rather
than trust a dev server.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@xuelink
xuelink merged commit f6c359e into main Sep 8, 2026
1 check passed
@xuelink
xuelink deleted the claude/analytics-init-on-mount branch September 8, 2026 18:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant