GDPR-compliant cookie consent management with category-based controls and persistent storage for both anonymous and authenticated users.
The consent state is stored under the cookie key cookie_consent (set by components/cookie-consent.tsx and read by components/analytics/analytics-provider.tsx). The same key is mirrored in localStorage so the analytics provider can restore prior consent before any third-party script mounts and re-applies Google Consent Mode v2 signals. For authenticated users, the choices are additionally persisted to the user_consents table via POST /api/user/consents.
The consent dialog also checks browser Global Privacy Control. When navigator.globalPrivacyControl is true, marketing consent is forced off and the marketing toggle is disabled. This keeps sale, sharing, cross-context behavioral advertising, and targeted-advertising opt-out semantics aligned with the public /[locale]/privacy-choices page.
Cookie Categories
| Category | Default | Description |
|---|---|---|
| Necessary | Always On | Essential cookies for site functionality (session, auth, locale) |
| Analytics | Opt-in | Google Tag Manager, usage statistics |
| Marketing | Opt-in | Google Ads conversions, Meta Pixel, advertising cookies, remarketing |
How It Works
- Banner Display - Shows on first visit if no consent recorded
- User Choice - Accept all, reject non-essential, or customize by category
- Persistence - Stored in cookie + localStorage for anonymous users
- Database Sync - For logged-in users, consent is saved through
POST /api/user/consents, not by a browser-side Supabase upsert - Third-party Loading - GTM, gtag/Google Ads, Meta, X and Crisp mount only after the matching consent category is granted
- Consent Mode - Consent state is pushed via Consent Mode v2 (analytics_storage, ad_storage, ad_user_data, ad_personalization)
- Global Privacy Control - Browser GPC signals keep marketing/sharing/targeted-ad consent disabled even if the visitor clicks accept all
- Withdrawal - The footer Cookie settings control reopens the preference dialog after the banner has been dismissed
Preference Management
Users can update their preferences at any time via:
- Footer Cookie settings control
- Footer Your Privacy Choices link
- My Account page privacy section
- Clicking the cookie banner again (if not dismissed permanently)
Cookie Security & Accessibility
The consent cookie is set with the Secure flag in production, ensuring it is only transmitted over HTTPS. The cookie banner and preference modal implement full ARIA accessibility: role="dialog", aria-label, focus trapping, and keyboard-navigable category toggles.
Consent Mode v2 Strategy
Google Consent Mode v2 is implemented with a deny-by-default strategy. On page load, analytics_storage, ad_storage, ad_user_data, and ad_personalization are all set to denied. When the user grants consent for a category, the corresponding consent signals are updated to granted via gtag('consent', 'update', ...), then the relevant third-party script can mount. This keeps the implementation aligned with stricter EU/Swiss privacy-by-default interpretations.