Skip to content

Send page views through langx.io, because blockers drop PostHog's host - #164

Merged
xuelink merged 2 commits into
mainfrom
claude/bunu-coz-qhfb4y
Sep 8, 2026
Merged

Send page views through langx.io, because blockers drop PostHog's host#164
xuelink merged 2 commits into
mainfrom
claude/bunu-coz-qhfb4y

Conversation

@xuelink

@xuelink xuelink commented Sep 8, 2026

Copy link
Copy Markdown
Member

PostHog's setup check warns about this: events went straight to eu.i.posthog.com, a host every blocklist carries, so an unknown share of visits was dropped before it was ever sent. Requests to langx.io are not blocked, because blocking them would break the site.

What changed

  • functions/relay/[[path]].js — a Cloudflare Pages Function that forwards /relay/* to PostHog's EU cloud: ingestion to eu.i.posthog.com, /static/ to eu-assets.i.posthog.com. It drops the cookie header before forwarding, and does no caching of its own — Workers' fetch already puts GET subrequests through Cloudflare's cache under the origin's headers. The site is adapter-static, so this is the only server it has.
  • src/lib/analytics.tsapi_host is now /relay on whatever origin served the page rather than a hardcoded https://langx.io, so a pages.dev preview proxies through its own copy. ui_host points at the dashboard, which the SDK can no longer infer. VITE_POSTHOG_HOST stays the escape hatch and is now the only way to reach PostHog directly — which is what npm run dev needs, since it serves no Function.
  • .github/workflows/deploy.yml — Wrangler compiles Functions from a functions/ directory in its working directory, not from inside the directory it publishes, and the deploy job only unpacks the artifact. Naming two upload paths keeps the workspace as the artifact root, so build/ and functions/ arrive side by side; hence directory: 'build' rather than '.'.
  • Cookie and privacy policy — §3.4 said in so many words that the connection was made from your browser directly rather than through us, which is no longer true. It now describes the hop, why we made it, and that nothing about what is sent changed. The privacy policy gets the same sentence, and PRODUCT.md notes the one path that is no longer a file.

Nothing changed about what is sent: the same page views and two events, still cookieless, still nothing written to the visitor's browser.

Verification

  • wrangler@3 pages functions build compiles the Function and generates include: ["/relay/*"], so no other path invokes it.
  • The forwarding was exercised against a stubbed fetch for a POST event, a /static/ asset, a preview origin and a bare /relay: prefix stripped, query and method and body preserved, cookie dropped, asset host split.
  • npm run lint clean, npm run check 0 errors, vite build succeeds and the built bundle no longer contains eu.i.posthog.com.

The PostHog warning clears on its own once the first events arrive through the proxy.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WVA9XXNJJkvUDrNqztc39t


Generated by Claude Code

PostHog's own setup check warns about this: events went straight to
eu.i.posthog.com, which every blocklist carries, so an unknown share of
visits was dropped before it was sent.

`functions/relay/[[path]].js` is a Cloudflare Pages Function that forwards
`/relay/*` to PostHog's EU cloud — ingestion to eu.i.posthog.com, `/static/`
to eu-assets.i.posthog.com — and the SDK now points at `/relay` on whatever
origin served the page, so a pages.dev preview proxies through its own copy.
`VITE_POSTHOG_HOST` stays the escape hatch and is the only way to reach
PostHog directly, which is what `npm run dev` needs.

Nothing changed about what is sent: the same page views and two events, still
cookieless, and the hop strips any cookie before forwarding. The cookie policy
said in so many words that the connection was made from your browser directly
rather than through us, which is no longer true, so §3.4 now describes the
forwarding and why we did it; the privacy policy gets the same sentence.

The deploy needed one adjustment: Wrangler compiles Functions from a
`functions/` directory in its working directory, not from inside the directory
it publishes, and the deploy job only unpacks the artifact. Naming two upload
paths keeps the workspace as the artifact root, so `build/` and `functions/`
arrive side by side — hence `directory: 'build'` rather than `'.'`.

Verified locally: `wrangler pages functions build` compiles it and generates
`include: ["/relay/*"]`, so no other path invokes a Function; the forwarding
was exercised against a stubbed fetch for a POST event, a `/static/` asset and
a bare `/relay`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WVA9XXNJJkvUDrNqztc39t
Both sides rewrote the same two paragraphs. main named the Cloudflare Web
Analytics that was already there, taking §3.4 from two third-party connections
to three; this branch replaced the sentence in that paragraph saying the
PostHog connection is made from your browser directly. Kept main's structure —
three things named, Cloudflare among them — with the proxy description in
place of the sentence it made untrue, and the same in the privacy policy's
website paragraph, which main had already split in two.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WVA9XXNJJkvUDrNqztc39t
@xuelink
xuelink merged commit 8edceb0 into main Sep 8, 2026
1 check passed
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.

2 participants