Google Analytics 4 loads on every visit to borrissol.com viaDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/constanza101/borrissol/llms.txt
Use this file to discover all available pages before exploring further.
gtag.js, but it operates in a cookieless mode by default. Cookies are only set after the visitor explicitly clicks Accept on the cookie banner. This is achieved through Google Consent Mode v2 Advanced — the most privacy-preserving GA4 integration pattern available, and the one required for full GDPR compliance in EU markets like Spain and France.
How Consent Mode v2 works in this project
Consent Mode v2 separates the GA4 loading decision (always load) from the cookie decision (only set after consent). The flow on every page visit is:Consent Mode initialized — denied by default
Before the GA4 snippet loads,
Layout.astro initializes Consent Mode with all storage types set to denied. This is the “Advanced” pattern: the script loads, but Google is explicitly told it may not write cookies or read device storage.GA4 loads via gtag.js
The GA4 measurement script loads in the
<head> of every page via Layout.astro. In denied state it fires a cookieless ping — Google uses this to model anonymous, aggregate traffic data without storing any PII.Cookie banner is shown to new visitors
CookieBanner.astro checks localStorage for a previously saved consent decision. If no value is found, the banner is displayed with two actions: Accept and Decline.Consent state updated on user action
When the visitor clicks Accept, the banner calls
gtag('consent', 'update', { analytics_storage: 'granted' }) and saves 'accepted' to localStorage. GA4 then sets its measurement cookies and begins full tracking for that session and all future sessions.When the visitor clicks Decline, 'rejected' is saved to localStorage. The banner is dismissed and GA4 continues in cookieless mode for all future visits.Consent restored on return visits
On every page load,
Layout.astro reads localStorage inside the same inline script that sets the consent default. If the saved value is 'accepted', it calls gtag('consent', 'update', { analytics_storage: 'granted' }) immediately — before the GA4 snippet fires — so returning visitors never see the banner again and GA4 operates in full mode from the first pageview. CookieBanner.astro also reads localStorage independently to decide whether to show the banner at all.The cookie banner (CookieBanner.astro)
The banner is a minimal two-button component rendered server-side by Astro and activated client-side:
- Accept — updates consent to
granted, saves'accepted'tolocalStorage, hides the banner - Decline — saves
'rejected'tolocalStorage, keeps GA4 in cookieless mode, hides the banner
localStorage, not in a cookie itself — keeping the pre-consent state clean.
The privacy policy text visible in
PrivacySection.astro is translated for all four languages via ui.ts. The keys cookie.accept, cookie.decline, cookie.text, and privacy.* cover all banner and policy copy.Layout.astro integration
Layout.astro is responsible for the correct script ordering in <head>:
- Consent Mode default initialization (inline
<script>— must run synchronously) gtag.jsloader (<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXX">)- GA4 configuration call (
gtag('config', 'G-XXXXXXXX'))
What happens in denied state
In denied state (the default for new visitors and visitors who clicked Decline):- GA4 fires a cookieless ping on each pageview
- Google applies modeled data — statistical inference that estimates traffic patterns from consented users and applies them to cookieless sessions
- No PII is stored. No
_gaor_gidcookies are written. No device fingerprinting occurs. - The site remains fully functional; the only difference is that individual sessions are not tracked
GDPR compliance summary
| Requirement | Implementation |
|---|---|
| No cookies before consent | ✅ Consent Mode denied default blocks all GA4 cookies |
| Explicit consent required | ✅ Two-action banner (Accept / Decline), no pre-ticked boxes |
| Consent persisted | ✅ localStorage — restored on return visits without re-asking |
| Right to withdraw | ✅ Visitor can clear browser localStorage/cookies at any time |
| Privacy policy | ✅ Inline PrivacySection.astro on every home page, translated in all 4 languages |
| Third-party analytics | ✅ GA4 only — no other tracking scripts |
Adding tracking beyond GA4
If a second analytics service (e.g. a heatmap tool) is added in the future:- Add the new consent category to the
gtag('consent', 'default', …)defaults inLayout.astro - Gate the tool’s initialization behind a
gtag('consent', 'update', …)grant - Update the privacy policy copy in
ui.tsfor all four languages to disclose the new tool