Check Google’s current Consent Mode documentation before implementing; parameters and regional requirements change.
Loading
Section titled “Loading”- Load GA4 only in production builds with a measurement ID:
import.meta.env.PROD && PUBLIC_GA_ID(or the stack’s equivalent). Local and preview builds send nothing. - Load after the main content; never block rendering.
- Add GA hosts to the CSP (
script-src,connect-src,img-src).
Consent Mode v2 defaults
Section titled “Consent Mode v2 defaults”<script is:inline async src={`https://www.googletagmanager.com/gtag/js?id=${GA_ID}`}></script><script is:inline define:vars={{ GA_ID }}> window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} // Denied by default where consent is required (EEA, UK, CH) gtag('consent', 'default', { ad_storage: 'denied', ad_user_data: 'denied', ad_personalization: 'denied', analytics_storage: 'denied', region: ['AT','BE','BG','HR','CY','CZ','DK','EE','FI','FR','DE','GR','HU','IE','IT','LV','LT','LU','MT','NL','PL','PT','RO','SK','SI','ES','SE','IS','LI','NO','GB','CH'] }); // Elsewhere: analytics only, no ads signals gtag('consent', 'default', { ad_storage: 'denied', ad_user_data: 'denied', ad_personalization: 'denied', analytics_storage: 'granted' }); gtag('js', new Date()); gtag('config', GA_ID);</script>- Review the regional default against your own legal advice and the laws where your users are (including India’s DPDP; see privacy).
Banner
Section titled “Banner”- Shown where consent is required. “Accept analytics” and “Decline” are equally prominent. No pre-ticked boxes.
- On accept:
gtag('consent', 'update', { analytics_storage: 'granted' }); store the choice; offer a way to change it (footer link). - Static sites cannot read the visitor’s country header; a timezone check (
Europe/*) is a pragmatic approximation. Document the approach in the privacy notice.
Events
Section titled “Events”- Names in
snake_case; at most a handful of parameters each; use GA4 recommended event names where one exists (search,sign_up,purchase). - MUST NOT send personal data (names, emails, phone numbers, user IDs that identify a person) in events or page URLs.
- Mark only the few events that represent real success as key events.
View transitions / SPAs
Section titled “View transitions / SPAs”- With client-side navigation, set
send_page_view: falseand sendpage_viewon each navigation event (for Astro:astro:page-load) to avoid double or missing counts.
Settings
Section titled “Settings”- Data retention set deliberately (for example 14 months) and stated in the privacy notice.
- Separate data streams or properties for each site, or one property with a hostname dimension; decide once and record it.
Checklist
Section titled “Checklist”- Production only; previews untracked
- Consent defaults and banner where required
- CSP updated
- No personal data in events or URLs
- Page views correct with client-side navigation
- Privacy notice describes GA4 use