# CMP 7817 Gestionnaire de consentement cookies (RGPD/ePrivacy) — un seul fichier JavaScript, sans dépendance, servi depuis 7817.fr via votre URL de licence. Le script, une fois chargé, n'effectue aucun appel réseau : aucune donnée ne quitte le navigateur du visiteur. - **Zéro dépendance** — JavaScript vanilla. - **Zéro appel réseau du script** — le CMP ne contacte aucun serveur pendant son fonctionnement. Tout le stockage se fait dans le navigateur du visiteur (cookie ou `localStorage`, sur votre propre domaine). Seul le chargement initial du fichier provient de 7817.fr, comme n'importe quelle ressource web, sans cookie ni traçage. - **Pas de TCF IAB** — pas de liste de partenaires publicitaires à gérer. - **~26 Ko minifié (~13 Ko compressé gzip)**, CSS et logo (badge « Gérer mes cookies », encodé en base64) compris. - Le bandeau initial affiche un petit crédit « Avec 7817.fr », lien vers https://7817.fr — non désactivable par configuration, comme le badge « Gérer mes cookies ». ## Installation Votre licence CMP, achetée depuis votre compte 7817.fr pour un domaine vérifié, vous délivre une URL personnalisée. Elle est valable 1 an et se renouvelle depuis votre compte (un rappel est envoyé 7 jours avant l'échéance) ; le renouvellement, même tardif, conserve la même URL. L'installation consiste à ajouter **deux balises script** à vos pages, juste avant `` (ou à l'endroit où vous placiez votre code de mesure d'audience) : **1. La configuration (optionnelle)** — toujours placée **avant** la balise du CMP : ```html ``` Si votre site a une barre d'onglets fixe en bas de l'écran sur mobile (footer app-like), le badge rond du CMP se superpose dessus une fois le consentement donné. Remontez-le uniquement sur mobile avec `manageLinkBottomMobile` (hauteur de votre barre + marge, en px) sans toucher au placement desktop. Toutes les clés ont une valeur par défaut : cette balise peut être omise entièrement, le CMP fonctionne sans configuration. **2. Le CMP** — votre URL de licence, telle qu'affichée sur votre compte : ```html ``` Cette URL est liée à votre domaine licencié. Les mises à jour du CMP sont automatiques : vous n'avez jamais de fichier à remplacer. **Important : placez ces deux balises dans le ``, avant tout iframe.** Avec ce placement, les iframes YouTube, YouTube (mode confidentialité), Dailymotion, Vimeo et Google Maps déjà présentes dans votre HTML sont bloquées **automatiquement**, sans aucune modification à faire dessus — voir "Iframes bloquées automatiquement" ci-dessous. Si le CMP est chargé plus bas dans la page (ex. juste avant ``), cette interception automatique ne fonctionne plus : les iframes ont déjà été insérées avant que le CMP n'existe. **3. Neutralisez vos scripts et les autres iframes tiers** (voir ci-dessous) — c'est l'étape indispensable pour tout ce qui n'est pas couvert par l'interception automatique (tous les scripts : GA4, pixels... ; les iframes de domaines non listés). Une fois terminé, relancez un scan 7817 pour vérifier que le blocage est effectif. ## Next.js Coller les deux balises ` ``` Fonctionne aussi pour les scripts inline (sans `src`) — le contenu est simplement recopié tel quel à l'activation. ### Iframes Remplacez `src` par `data-7817-src` et ajoutez `data-7817-category` : ```html ``` Tant que la catégorie n'est pas consentie, le CMP affiche à la place un encart « Contenu bloqué — accepter les cookies "Publicité" pour afficher » avec un bouton qui, cliqué, accorde directement cette catégorie (consentement granulaire, sans rouvrir tout le panneau) et charge l'iframe en place. ### Iframes bloquées automatiquement Convertir une à une des dizaines ou des centaines d'iframes existantes n'est pas réaliste. Pour les embeds les plus courants, le CMP les intercepte **sans aucune modification du HTML**, à condition que le CMP soit chargé dans le `` (voir Installation) : un observateur posé dès l'exécution du script voit chaque iframe au moment de son insertion par le navigateur et applique le même traitement que la convention manuelle (retrait du `src`, placeholder, activation au consentement) — aucune vidéo ne s'affiche et aucun cookie tiers n'est posé tant que la catégorie correspondante n'est pas consentie. Domaines couverts par défaut (tous en catégorie `marketing`) : - `youtube.com` - `youtube-nocookie.com` - `dailymotion.com` - `vimeo.com` - `google.com/maps` Cela fonctionne aussi pour une iframe ajoutée dynamiquement après le chargement (script tiers, carrousel, lazy-load) et pour une iframe dont le `src` est modifié après coup. Configurable via `CMP7817Config` : ```html ``` Une règle qui pointe vers une catégorie absente de votre configuration (ex. retirée via `categories: { marketing: null }`) est ignorée avec un avertissement dans la console — jamais de blocage sur une catégorie que le panneau ne peut pas accorder. **Limite honnête** : ce blocage empêche fiablement l'affichage du contenu et le dépôt de cookies tiers avant consentement (vérifié : aucune vidéo, aucun cookie tant que la catégorie n'est pas accordée). Il n'empêche en revanche pas à 100 % une tentative de connexion très brève et immédiatement annulée vers le domaine bloqué (visible en tant que requête "canceled" dans l'onglet Network), le temps que le script réagisse — ce que même la plupart des CMP du marché ne garantissent pas pour ce type de blocage sans modification du HTML. Si un zéro-requête strict est indispensable pour votre cas d'usage, la conversion manuelle (`data-7817-src`) reste la seule garantie complète, puisque le `src` n'existe alors jamais dans le HTML livré au navigateur. Une iframe déjà convertie à la main (`data-7817-src`) n'est jamais retouchée par l'interception automatique. Cette liste reste volontairement courte : uniquement des embeds vidéo/cartes universels, pas un catalogue extensible — les scripts tiers (GA4, pixels...) et les iframes d'autres domaines restent à neutraliser manuellement (voir ci-dessus). ### Catégories par défaut `necessaire` (toujours active, non désactivable), `analytics`, `marketing`, `personnalisation`. Redéfinissables via `CMP7817Config.categories` : ```html ``` Pour **retirer** une catégorie par défaut inutilisée (ne pas afficher un interrupteur qui ne pilote rien), passez `null` : ```html ``` `necessaire` peut être retirée comme les autres, avec `necessaire: null` — réservé aux sites qui n'utilisent réellement aucun cookie strictement nécessaire (pas de panier, pas de connexion), pour ne pas afficher un interrupteur verrouillé qui ne correspond à rien. ## Exemples courants ### Google Analytics 4 (gtag.js) ```html ``` ### Google Tag Manager ```html ``` Le GTM lui-même sert souvent de conteneur pour d'autres tags (Ads, Analytics…) : pensez à filtrer *dans* GTM selon les catégories de consentement si vous y ajoutez d'autres outils, ou neutralisez chaque tag individuellement en dehors de GTM. ### Meta Pixel ```html ``` ### Iframe YouTube / Dailymotion / Google Maps ```html ``` ## API ```js CMP7817.version // "1.6.0" CMP7817.consent(category) // boolean — la catégorie est-elle consentie ? CMP7817.getConsents() // { necessaire: true, analytics: false, ... } CMP7817.show() // rouvre le panneau (toggles pré-remplis avec le choix mémorisé) CMP7817.reset() // efface le consentement et recharge la page CMP7817.on(event, callback) // "ready" | "consentGiven" | "consentUpdated" | "consentWithdrawn" ``` Les mêmes événements sont aussi émis en `CustomEvent` sur `document`, préfixés `cmp7817:` — utile si votre code s'exécute avant le chargement du CMP : ```js document.addEventListener('cmp7817:consentGiven', function (e) { console.log(e.detail); // { necessaire: true, analytics: true, ... } }); ``` `consentGiven` est émis à la première décision de l'utilisateur, `consentUpdated` à chaque modification ultérieure qui n'ajoute que des catégories, `consentWithdrawn` quand une catégorie déjà active est retirée (juste avant le rechargement de page — voir FAQ). ## FAQ **Dois-je convertir mes 100 iframes YouTube une par une ?** Non, si le CMP est chargé dans le `` : l'interception doit se poser avant que le navigateur n'atteigne la première iframe dans le HTML, sinon la requête est déjà partie quand le CMP démarre. Les domaines couverts par défaut (YouTube, Dailymotion, Vimeo, Google Maps) sont bloqués automatiquement, sans toucher au HTML — voir "Iframes bloquées automatiquement". Cette couverture reste limitée aux domaines listés : les iframes d'autres services et tous les scripts tiers nécessitent toujours la conversion manuelle. Un scan 7817 permet de vérifier qu'aucune requête n'échappe encore au blocage. **Pourquoi la page se recharge quand je retire une catégorie déjà acceptée ?** Un script déjà exécuté (compteurs, timers, connexions ouvertes par un tracker) continue de tourner même si le CMP ne le réactivera plus au prochain chargement. Le seul moyen fiable de vraiment arrêter un script en cours d'exécution est de recharger la page. Accorder une nouvelle catégorie, en revanche, n'entraîne pas de rechargement : les scripts concernés sont simplement activés en place. **Le CMP envoie-t-il des données quelque part ?** Non. Le consentement est stocké localement (cookie ou `localStorage`) sur le domaine du site qui l'installe. Aucune télémétrie, aucun tracking du CMP lui-même. Le chargement du fichier depuis 7817.fr apparaît dans nos journaux serveur comme toute requête web (adresse IP, referer), sans cookie ni rapprochement avec vos visiteurs — voir la politique de confidentialité de 7817.fr. **Mon URL de licence fonctionne-t-elle sur un autre domaine ?** Non : la licence est liée au domaine vérifié choisi à l'achat (sous-domaines inclus). Pour équiper un autre domaine, achetez une licence pour ce domaine depuis votre compte. **Que se passe-t-il si je ne renouvelle pas ma licence à temps ?** La licence est valable 1 an. À l'échéance, sans renouvellement, l'URL cesse immédiatement de répondre (le CMP ne se charge plus). Un rappel est envoyé 7 jours avant l'échéance. Un renouvellement, même effectué après la coupure, réactive la même URL — rien à modifier sur votre site. **Comment le scanner 7817 détecte-t-il le CMP sur un site audité ?** Deux marqueurs stables : `window.CMP7817.version` (objet global) et l'attribut `data-cmp7817-version` présent sur l'élément racine injecté dans le DOM (`#cmp7817-root`), même quand le bandeau est fermé. **Combien de temps dure un consentement ?** `consentDuration` (en jours), 180 par défaut, plafonné à 390 (13 mois, la limite recommandée par la CNIL) quelle que soit la valeur configurée. **Cookies bloqués par le navigateur, que se passe-t-il ?** Le CMP détecte l'indisponibilité des cookies au chargement et bascule automatiquement sur `localStorage`, avec le même format de données. **Compatibilité navigateurs ?** Navigateurs evergreen (Chrome, Firefox, Safari, Edge récents). JavaScript ES2017, `CustomEvent` — aucune API exotique. `crypto.randomUUID()` est utilisé si disponible, avec repli automatique sinon. **Un utilisateur refuse une catégorie après l'avoir déjà acceptée — les cookies posés entre-temps par le script tiers (ex. `_ga`, `_ga_XXXXXXX` pour GA4) sont-ils supprimés ?** Non. Le CMP arrête bien la ré-exécution du script au rechargement (voir ci-dessus) et supprime son **propre** cookie `cmp7817`, mais il ne connaît pas les cookies que le script tiers a lui-même posés pendant qu'il tournait — il n'existe pas de liste fiable et universelle des noms de cookies par outil tiers, et en deviner certains (regex sur `_ga`, `_fbp`…) donnerait une fausse impression d'exhaustivité. Si vous devez garantir la suppression effective de cookies tiers au retrait du consentement, prévoyez leur nettoyage explicite dans le script neutralisé lui-même (la plupart des outils exposent une fonction d'opt-out, ex. `gtag('consent', 'update', {...})` ou la désactivation `window['ga-disable-XXXXXXX'] = true` pour GA4) — c'est une responsabilité du script intégré, pas du CMP. **Accessibilité ?** Navigation clavier complète, focus trap dans le panneau ouvert, attributs `role="dialog"`, `aria-modal`, `aria-labelledby`. Échap ferme sans enregistrer de choix (équivalent à continuer sans répondre). Par défaut (`backdropBlocking: true`), le contenu de la page est inaccessible tant qu'aucun choix n'a été fait — passez `backdropBlocking: false` pour revenir à un bandeau non bloquant, contenu accessible et défilable derrière.