1. Collez le snippet
Déposez le code généré juste avant la balise de fermeture body, sur chaque page. Il n'a aucune dépendance et n'ajoute aucune requête réseau.
Outil gratuit
Choisissez vos catégories de cookies, rédigez le texte, sélectionnez une apparence — et récupérez un bandeau de consentement sans dépendances à coller sur n'importe quel site. Il enregistre le choix du visiteur, garde les scripts tagués bloqués tant que leur catégorie n'est pas acceptée, et peut être rouvert depuis un lien de pied de page.
Votre bandeau de consentement
Collez ceci juste avant la balise de fermeture body, sur chaque page.
<!-- Cookie consent banner - paste this just before </body> -->
<script>
(function () {
var CFG = {
"storageKey": "cookie_consent",
"position": "bar",
"theme": "light",
"accent": "#a6144d",
"title": "Nous utilisons des cookies",
"message": "Nous utilisons des cookies pour faire fonctionner ce site, comprendre son utilisation et l'améliorer. Vous pouvez tout accepter, refuser ce qui est optionnel ou choisir par catégorie.",
"policyUrl": "https://example.com/privacy",
"policyLabel": "Lire notre politique de confidentialité",
"accept": "Tout accepter",
"reject": "Refuser l'optionnel",
"prefs": "Préférences",
"save": "Enregistrer mes choix",
"categories": [
{
"id": "necessary",
"label": "Strictement nécessaires",
"desc": "Indispensables au fonctionnement du site. Toujours actifs, sans demande de consentement.",
"required": true
},
{
"id": "analytics",
"label": "Analytique",
"desc": "Mesure l'utilisation du site afin de l'améliorer.",
"required": false
},
{
"id": "marketing",
"label": "Marketing",
"desc": "Sert à personnaliser les publicités et à mesurer les campagnes.",
"required": false
}
]
};
var KEY = CFG.storageKey;
var doc = document;
var box = null;
function read() {
try { return JSON.parse(localStorage.getItem(KEY) || 'null'); } catch (e) { return null; }
}
function save(consent) {
consent.necessary = true;
consent.date = new Date().toISOString();
try { localStorage.setItem(KEY, JSON.stringify(consent)); } catch (e) {}
unblock(consent);
window.dispatchEvent(new CustomEvent('consentchange', { detail: consent }));
if (typeof window.onConsentChange === 'function') window.onConsentChange(consent);
}
// Scripts the site parked behind a category run only once it is granted. Park
// one by giving its tag type="text/plain" and data-consent="analytics".
// (Deliberately described, not shown: a literal script tag written out here
// would close this one early and truncate everything below it.)
function unblock(consent) {
var parked = doc.querySelectorAll('script[type="text/plain"][data-consent]');
for (var i = 0; i < parked.length; i++) {
var old = parked[i];
if (!consent[old.getAttribute('data-consent')]) continue;
var next = doc.createElement('script');
for (var a = 0; a < old.attributes.length; a++) {
var at = old.attributes[a];
if (at.name !== 'type' && at.name !== 'data-consent') next.setAttribute(at.name, at.value);
}
next.text = old.text;
old.parentNode.replaceChild(next, old);
}
}
function styles() {
var dark = CFG.theme === 'dark';
var bg = dark ? '#161622' : '#ffffff';
var fg = dark ? '#f4f4f8' : '#141a47';
var muted = dark ? 'rgba(244,244,248,.72)' : 'rgba(20,26,71,.7)';
var line = dark ? 'rgba(255,255,255,.14)' : 'rgba(20,26,71,.12)';
var el = doc.createElement('style');
el.textContent = [
'.cc-root{position:fixed;z-index:2147483000;font:400 14px/1.55 system-ui,-apple-system,Segoe UI,Roboto,sans-serif;color:' + fg + ';box-sizing:border-box}',
'.cc-root *,.cc-root *::before,.cc-root *::after{box-sizing:inherit}',
'.cc-card{background:' + bg + ';border:1px solid ' + line + ';box-shadow:0 18px 48px rgba(0,0,0,.18);border-radius:14px;padding:20px}',
'.cc-bar{left:0;right:0;bottom:0;padding:16px}',
'.cc-bar .cc-card{display:flex;flex-wrap:wrap;gap:16px;align-items:center;justify-content:space-between;max-width:1120px;margin:0 auto}',
'.cc-box{left:16px;bottom:16px;max-width:400px}',
'.cc-modal{inset:0;display:flex;align-items:center;justify-content:center;padding:16px;background:rgba(10,10,20,.5)}',
'.cc-modal .cc-card{max-width:520px;width:100%}',
'.cc-title{margin:0 0 6px;font-size:16px;font-weight:700}',
'.cc-text{margin:0;color:' + muted + '}',
'.cc-text a{color:' + CFG.accent + ';font-weight:600}',
'.cc-actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}',
'.cc-bar .cc-actions{margin-top:0}',
'.cc-btn{appearance:none;cursor:pointer;border:1px solid ' + line + ';border-radius:999px;padding:9px 18px;font:600 14px inherit;background:transparent;color:' + fg + '}',
'.cc-btn-main{background:' + CFG.accent + ';border-color:' + CFG.accent + ';color:#fff}',
'.cc-btn:focus-visible{outline:2px solid ' + CFG.accent + ';outline-offset:2px}',
'.cc-cats{display:none;margin:14px 0 0;padding:14px 0 0;border-top:1px solid ' + line + '}',
'.cc-cats.cc-open{display:block}',
'.cc-cat{display:flex;gap:10px;align-items:flex-start;margin-bottom:12px}',
'.cc-cat input{margin:3px 0 0;accent-color:' + CFG.accent + '}',
'.cc-cat strong{display:block;font-size:14px}',
'.cc-cat span{display:block;color:' + muted + ';font-size:13px}',
'@media(max-width:640px){.cc-bar .cc-card{display:block}.cc-bar .cc-actions{margin-top:14px}.cc-btn{flex:1 1 auto}}'
].join('');
doc.head.appendChild(el);
}
function build() {
var stored = read() || {};
var root = doc.createElement('div');
root.className = 'cc-root cc-' + CFG.position;
root.setAttribute('role', CFG.position === 'modal' ? 'dialog' : 'region');
root.setAttribute('aria-label', CFG.title);
if (CFG.position === 'modal') root.setAttribute('aria-modal', 'true');
var card = doc.createElement('div');
card.className = 'cc-card';
var copy = doc.createElement('div');
var h = doc.createElement('p');
h.className = 'cc-title';
h.textContent = CFG.title;
var p = doc.createElement('p');
p.className = 'cc-text';
p.textContent = CFG.message + ' ';
if (CFG.policyUrl) {
var link = doc.createElement('a');
link.href = CFG.policyUrl;
link.textContent = CFG.policyLabel;
p.appendChild(link);
}
copy.appendChild(h);
copy.appendChild(p);
var cats = doc.createElement('div');
cats.className = 'cc-cats';
var inputs = {};
for (var i = 0; i < CFG.categories.length; i++) {
var c = CFG.categories[i];
var row = doc.createElement('label');
row.className = 'cc-cat';
var cb = doc.createElement('input');
cb.type = 'checkbox';
cb.checked = c.required || stored[c.id] === true;
cb.disabled = !!c.required;
var txt = doc.createElement('div');
var name = doc.createElement('strong');
name.textContent = c.label;
var desc = doc.createElement('span');
desc.textContent = c.desc;
txt.appendChild(name);
txt.appendChild(desc);
row.appendChild(cb);
row.appendChild(txt);
cats.appendChild(row);
inputs[c.id] = cb;
}
copy.appendChild(cats);
var actions = doc.createElement('div');
actions.className = 'cc-actions';
function button(label, main, onClick) {
var b = doc.createElement('button');
b.type = 'button';
b.className = 'cc-btn' + (main ? ' cc-btn-main' : '');
b.textContent = label;
b.addEventListener('click', onClick);
actions.appendChild(b);
return b;
}
function decide(granted) {
var consent = {};
for (var i = 0; i < CFG.categories.length; i++) {
var c = CFG.categories[i];
consent[c.id] = c.required ? true : granted === null ? !!inputs[c.id].checked : granted;
}
save(consent);
close();
}
var prefsBtn = button(CFG.prefs, false, function () {
var open = cats.classList.toggle('cc-open');
prefsBtn.setAttribute('aria-expanded', open ? 'true' : 'false');
saveBtn.style.display = open ? '' : 'none';
});
prefsBtn.setAttribute('aria-expanded', 'false');
button(CFG.reject, false, function () { decide(false); });
button(CFG.accept, true, function () { decide(true); });
var saveBtn = button(CFG.save, false, function () { decide(null); });
saveBtn.style.display = 'none';
card.appendChild(copy);
card.appendChild(actions);
root.appendChild(card);
doc.body.appendChild(root);
box = root;
}
function close() {
if (box && box.parentNode) box.parentNode.removeChild(box);
box = null;
}
function open() {
if (!box) build();
}
function start() {
styles();
var stored = read();
if (stored) unblock(stored);
else build();
window.showConsentPreferences = open;
}
if (doc.readyState === 'loading') doc.addEventListener('DOMContentLoaded', start);
else start();
})();
</script> Comment l'utiliser
Déposez le code généré juste avant la balise de fermeture body, sur chaque page. Il n'a aucune dépendance et n'ajoute aucune requête réseau.
Passez le type d'une balise de tracking à text/plain et ajoutez data-consent="analytics". Le bandeau l'exécute dès que cette catégorie est acceptée — et jamais avant.
Ajoutez un lien de pied de page qui appelle window.showConsentPreferences() pour rouvrir le panneau. Chaque décision déclenche aussi un événement consentchange que vous pouvez écouter.
FAQ
Il vous donne les mécanismes attendus par les autorités : aucun cookie optionnel avant consentement, un refus aussi simple que l'acceptation, un choix par catégorie et la possibilité de revenir sur sa décision. La conformité dépend aussi de ce que vous exécutez réellement, du contenu de votre politique et du pays de vos visiteurs : considérez le code généré comme une base solide, pas comme un conseil juridique.
Donnez à la balise de script le type="text/plain" et un attribut data-consent nommant sa catégorie. Le navigateur ne l'exécute pas, et le bandeau la réécrit en véritable balise de script dès que la catégorie est acceptée — lors de cette visite ou de la suivante, à partir de la décision enregistrée.
Dans localStorage, sous la clé que vous choisissez, en un petit objet JSON avec un indicateur par catégorie et la date. Aucun cookie n'est déposé par le bandeau lui-même et rien n'est envoyé à un serveur : il fonctionne donc sur un site purement statique.
Oui. La position, le thème et la couleur d'accent sont des options ici, et chaque élément du CSS généré est préfixé par cc-, ce qui vous permet de surcharger les règles depuis votre propre feuille de style sans toucher au snippet.
Pour un site unique avec quelques catégories, ce snippet suffit généralement. Dès que vous avez besoin de journaux de consentement, de plusieurs domaines ou d'une analytique qui respecte automatiquement le choix, le gestionnaire de consentement intégré de PulsePanda prend le relais.
Associé
PulsePanda intègre un gestionnaire de consentement — sans cookies par défaut, et la collecte s'arrête dès qu'une personne se retire. Pas de second prestataire, pas de code de liaison.
Commencer gratuitement