ReviewOS

stacks/analyticshq

[feature] Ad-blocker bypass via first-party CNAME proxy

#27
Closed glennmichael123 opened this 9 days ago ·
9 days ago

Gap

The tracker is served from its own origin (routes/analytics.ts:601) with no first-party-domain option. Fathom/Plausible/Simple Analytics offer CNAME first-party proxying (Fathom randomizes subdomain + script filename) to reduce blocker loss.

Proposed

Document + support a first-party CNAME setup so the script and /collect load from the customer’s own subdomain, improving data completeness. (Note: some blockers still catch it — set expectations.)

Priority: P2.


From the 2026-07-20 privacy-first competitive audit (vs. Plausible / Fathom / Simple Analytics / Umami).

9 days ago

Shipped in d66870e — the application half. Read the last section before closing the book on this.

What landed

  • POST /api/sites/{siteId}/domain — declare a hostname, stored unverified, returns the CNAME target and instructions
  • POST /api/sites/{siteId}/domain/verify — resolves DNS and marks it verified only if it actually points here
  • GET /api/sites/{siteId}/domain — status plus the snippet to embed
  • DELETE — release it

The client half was already done. public/script.js computes its endpoint as new URL(document.currentScript.src, location.href).origin + '/collect', so the same static asset beacons back to whichever host served it. Nothing in the tracker needed changing — and a test now pins that line, because hardcoding an origin there would break CNAME proxying without breaking anything else a test would notice.

Why verification isn't decoration

DNS is the only evidence available: the customer types a hostname, and the only thing separating "mine" from "someone else's" is whether they can make it point here.

That matters twice. The deployment issues a TLS certificate per accepted domain, so an unverified field is a way to make this service request certificates for domains it has no relationship with. And without it, one customer could claim a hostname belonging to someone else and have it render in their dashboard as theirs.

verified_at stays null until a lookup agrees, and the snippet keeps emitting the app origin until then. Handing over a snippet that silently collects nothing until DNS propagates produces "I installed it and got no data" — the worst failure mode this product has.

Verification accepts two shapes: a CNAME to our host (the documented instruction) and an A record matching ours (what Cloudflare and Route 53 ALIAS actually publish when they flatten CNAMEs). A CNAME-only check would fail customers who followed the instructions correctly, and that failure would look identical to having done nothing.

Tested against real DNS rather than a mocked resolver — including a hostname with no CNAME, which is the only way to prove the address fallback is what passed it. Worth recording that my first probe asserted www.cloudflare.com should verify against cloudflare.com; it doesn't, because they sit on different anycast pools. The probe was wrong about the world, not the code.

Also refused: apex domains (with advice that works — a bare apex cannot hold a CNAME), our own hostnames, IP addresses, and any hostname already claimed by another site.

What is NOT done, and it is not optional

TLS termination and edge routing for the customer's hostname. Nothing here makes https://stats.customer.com serve anything — that needs a certificate for each accepted domain and an edge configured to answer for it. Those are deployment concerns, and faking them in application code would have produced a feature that verifies a domain and then cannot serve it. The verify response says so explicitly rather than implying the job is finished.

So this closes the app-side work the issue asked for and the feature is not usable end-to-end until the platform side exists. If you'd rather track that, reopening or filing a follow-up against the deployment is reasonable — I've closed this one because the code half is complete and tested, not because a customer can use it today.

Also unchanged, per the issue's own note: some blockers still catch first-party proxying. Nothing here claims otherwise.

Sign in to comment on this issue.