From 2eaabcfa316961cfb8fb60ce85bb3982688112d2 Mon Sep 17 00:00:00 2001 From: Vishal Rana Date: Mon, 17 Aug 2026 20:27:10 -0700 Subject: [PATCH] fix(site): make the analytics actually cookieless MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The component claimed to set no cookies. It set two. `client_storage: "none"` passed inside `gtag("config", ...)` is not a directive gtag recognises. It forwarded it as a custom event parameter — every hit carried `ep.client_storage=none` — and GA4 wrote `_ga` and `_ga_` regardless. The setting did nothing except add a meaningless field to the payload. Consent Mode is the mechanism that works, declared before `js` and `config`: gtag("consent", "default", { analytics_storage: "denied", ad_storage: "denied", ad_user_data: "denied", ad_personalization: "denied", }); Measured in a real browser before and after, on the built output: before document.cookie -> _ga_C1KM4SN3JR=GS2.1...; _ga=GA1.1... payload -> ep.client_storage=none after document.cookie -> (none) payload -> gcs=G100 pscdl=denied `gcs=G100` is GA acknowledging the denial. A page_view is still recorded (204), title and location are still correct, and npa=1 still reports ad personalisation off. The only thing that changed is that the claim is now true. Worth recording why this survived review. Every earlier check tested the wrong thing: grepping the built HTML for `client_storage: "none"` proved the string was emitted, never that GA honoured it, and executing the script against a DOM stub cannot observe cookies because the stub has no cookie jar. Both passed. Only a real browser could see it. Co-Authored-By: Claude Opus 5 (1M context) --- site/src/components/Analytics.astro | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/site/src/components/Analytics.astro b/site/src/components/Analytics.astro index 04a2d54f..a6393151 100644 --- a/site/src/components/Analytics.astro +++ b/site/src/components/Analytics.astro @@ -74,10 +74,23 @@ const enabled = Boolean(measurementId) && import.meta.env.PROD; window.dataLayer = window.dataLayer || []; function gtag() { window.dataLayer.push(arguments); } window.gtag = gtag; + + // Consent Mode, declared before anything else, is what actually stops + // GA4 writing cookies. Passing `client_storage: "none"` to config does + // not: gtag does not recognise it there and forwards it as a custom + // event parameter, so every hit carried `ep.client_storage=none` while + // `_ga` and `_ga_` were set anyway. Measured in a real browser, not + // assumed — the first version of this file claimed to be cookieless and + // was not. + gtag("consent", "default", { + analytics_storage: "denied", + ad_storage: "denied", + ad_user_data: "denied", + ad_personalization: "denied", + }); + gtag("js", new Date()); gtag("config", measurementId, { - // No cookie, so no consent banner, so nothing to click past. - client_storage: "none", allow_google_signals: false, allow_ad_personalization_signals: false, // The path without its query string. See the note in the component