Skip to content

feat(web): first-party Logdash web analytics - #58

Merged
szymeo merged 1 commit into
mainfrom
szymeo/svelte-migration-not-live-v2
Oct 11, 2026
Merged

szymeo merged 1 commit into
mainfrom
szymeo/svelte-migration-not-live-v2

Conversation

@szymeo

@szymeo szymeo commented Oct 11, 2026

Copy link
Copy Markdown
Collaborator

What

  • src/routes/_ld/script.js/+server.ts: GET proxy for https://logdash.io/sdk/web.js. Sends no browser headers upstream. Serves application/javascript with public, max-age=3600, s-maxage=3600, stale-while-revalidate=86400.
  • src/routes/_ld/events/+server.ts: POST proxy for https://api.logdash.io/web_events.
    • Accepts JSON only (else 415). Rejects bodies over 32 KB or more than 20 events (413), the wrong siteId (403), and malformed or empty batches (400).
    • Forwards only Origin, User-Agent and x-logdash-client-ip (from getClientAddress(), which reads Vercel's x-forwarded-for).
    • Replaces /app/project/<id> and /invite/<id> with :id before anything leaves our server. Returns the upstream status with no-store.
  • src/app.html: adds the tracker tag once. It's the server-rendered head for every route, including the ssr = false app pages.
  • $lib/analytics/logdash.ts: track and identify. Both wait for the deferred script's load event when window.logdash isn't ready yet.
  • Root layout: identify(auth.userData?.id ?? null) runs on page load, after sign-in, and with null on sign-out.
  • Events: login_completed {method}, signup_completed, project_created {github_repo}, secrets_saved, secrets_pushed {integrations}, invitation_created {kind, role}, invitation_accepted {kind}, cli_authorized. None carry personal data.
  • e2e/logdash-proxy.spec.ts: covers the rejection paths. None of those requests reach Logdash.
  • No data-respect-dnt: the site has no privacy policy that promises it. No consent gate or opt-out toggle existed to wire.

Verified

  • pnpm check, pnpm lint, Cloudflare and Vercel builds, and the proxy spec (6/6) all pass.
  • End to end, I ran the real Vercel build over HTTPS as https://cryptly.dev (mapped to 127.0.0.1), with a local backend and navigator.webdriver=false. Steps: home, SPA nav to /blog, local sign-in, passphrase, create a project, save, reload, sign out.
    • Every upstream POST returned 202 with origin: https://cryptly.dev and x-logdash-client-ip. No other headers were sent.
    • Events after sign-in and after reload carried a user hash; events after sign-out did not.
    • The project page reached Logdash as /app/project/:id.
    • document.cookie was empty. Local and session storage held only app and SvelteKit keys.
    • The browser never requested logdash.io; all traffic went to cryptly.dev/_ld/*.

Proxy the tracker and events through /_ld on our origin (fixed upstream URLs,
JSON only, 32 KB / 20-event limits, site ID check, only Origin, User-Agent and
the client IP forwarded). Project and invite IDs in paths become :id before
leaving the server. Identify follows auth.userData; track a few key actions.
@vercel

vercel Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
cryptly Ready Ready Preview Oct 11, 2026 8:50pm UTC

@szymeo
szymeo merged commit ff2b78d into main Oct 11, 2026
3 checks passed

This branch was successfully deployed

1 active deployment
Preview — 4a8197e4 Deployed Oct 11, 2026 by vercel[bot]
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