Cookies & marketing
Regle de base : aucun outil collectant des donnees ne se charge avant le consentement de l'utilisateur. Le template implemente le consentement avec vanilla-cookieconsent et Google Consent Mode v2.
Popup de consentement (scripts/modules/cookiesConsent.js)
- Lib
vanilla-cookieconsent3.1 (CSS importe). Charge en lazy depuisscripts/index.js(requestIdleCallback/ fallbacksetTimeout) pour ne pas bloquer le LCP. - Lit les traductions depuis un noeud
#cc_translations(JSON injecte cote serveur, alimente par le dictionnaire /cookiesSettings). - Categories :
necessary(active, read-only),functional(desactivee par defaut — embeds tiers : Weezevent, WeezPay, Airbnb, Google Maps) etanalytics(desactivee par defaut ;autoCleardes cookies_ga*/_gid).
⚠️ Le popup ne s'affiche actuellement jamais (bug pre-existant, voir
domain/assets-substitues.md§7bis). Consequence : la categoriefunctionalne peut pas etre acceptee, donc les embeds restent sur leur placeholder.
Embeds tiers consentis (embed block + scripts/modules/consentEmbed.js)
Le gating est implemente une seule fois, dans le bloc embed (et reutilise par map) :
- Le serveur rend la charge utile dans un
<template data-embed-payload>. Le navigateur ne fetch rien a l'interieur d'un<template>: pas d'iframe src, pas de<script>. « Avant consentement » signifie donc zero requete reseau vers le tiers — pas une iframe cachee qui a deja appele. C'est structurel, pas declaratif. consentEmbed.js(lazy, charge seulement si.js-embedexiste) affiche un placeholder avec un bouton « gerer les cookies » tant que la categorie n'est pas acceptee.- A l'acceptation, il clone le contenu du
<template>dans le DOM. Les<script>clones d'un<template>ne s'executent pas — ils sont donc recrees un par un.
releaseEmbeds() est appele inconditionnellement apres run() : onConsent ne se declenche que si un consentement existe deja, donc sans cet appel un nouveau visiteur ne verrait ni le widget ni le placeholder (charge utile inerte + aucun placeholder dessine).
Verification (Chrome reel) : sur /contact/ avant consentement -> 0 requete tierce, 0 iframe dans le DOM, 1 placeholder.
- Cookie de consentement : expiration 180 jours.
- A chaque consentement/changement, appelle
updateGTMConsent()qui poussegtag('consent','update', { analytics_storage: 'granted'|'denied' }).
Le popup ne s'affiche que si CookieConsent:Enabled=true (appsettings.json -> CookieConsentOptions, src/Web/Options/CookieConsentOptions.cs). Le _MasterLayout n'inclut _cookiesConsent.cshtml que dans ce cas. Mettre Enabled=false quand un CMP tiers (OneTrust, Didomi...) est integre.
Les classes du popup sont preservees de PurgeCSS via la safelist deep: [/^cookie/] (voir ../architecture/frontend-build.md).
Google Analytics 4 (Views/Partials/layout/marketing/_googleAnalytics4.cshtml)
- Inclus inconditionnellement dans le
<head>du_MasterLayout, mais Consent Mode v2 protege les donnees :gtag('consent','default', { analytics_storage: 'denied' })est pose avant tout, donc rien n'est stocke tant que le visiteur n'a pas accepte. - Ne s'injecte que si
Model.GoogleAnalytics4Id(propriete du document typemarketingSettings) est renseigne. anonymize_ip: true(LPD / RGPD).preconnect/dns-prefetchvers googletagmanager pour la latence.
Ajouter un outil marketing / analytics
Procedure (README "Guide de developpement") :
- Creer un partial sous
Views/Partials/layout/marketing/. - L'inclure dans
Views/Layouts/_MasterLayout.cshtml(fin du<head>), conditionne au consentement le cas echeant. - Mettre a jour
scripts/modules/cookiesConsent.js(acceptCookies()/ handlers de consentement) pour injecter/activer le script dynamiquement au moment du consentement - sinon il faudrait recharger la page. - Si l'outil pose des classes/cookies dynamiques, penser a la safelist PurgeCSS et a l'
autoClearde la categorie concernee.

