1. Pega el fragmento
Coloca el código generado justo antes de la etiqueta de cierre body en todas las páginas. No tiene dependencias ni añade peticiones de red.
Herramienta gratuita
Elige tus categorías de cookies, escribe el texto, selecciona un aspecto y copia un banner de consentimiento sin dependencias que puedes pegar en cualquier sitio. Guarda la elección del visitante, mantiene bloqueados los scripts etiquetados hasta que se acepte su categoría y puede reabrirse desde un enlace del pie de página.
Tu banner de consentimiento
Pega esto justo antes de la etiqueta de cierre body, en todas las páginas.
<!-- Cookie consent banner - paste this just before </body> -->
<script>
(function () {
var CFG = {
"storageKey": "cookie_consent",
"position": "bar",
"theme": "light",
"accent": "#a6144d",
"title": "Usamos cookies",
"message": "Usamos cookies para que este sitio funcione, entender cómo se utiliza y mejorarlo. Puedes aceptarlo todo, rechazar lo opcional o elegir por categoría.",
"policyUrl": "https://example.com/privacy",
"policyLabel": "Lee nuestra política de privacidad",
"accept": "Aceptar todo",
"reject": "Rechazar opcionales",
"prefs": "Preferencias",
"save": "Guardar elecciones",
"categories": [
{
"id": "necessary",
"label": "Estrictamente necesarias",
"desc": "Imprescindibles para que el sitio funcione. Siempre activas y nunca piden consentimiento.",
"required": true
},
{
"id": "analytics",
"label": "Analítica",
"desc": "Mide cómo se usa el sitio para poder mejorarlo.",
"required": false
},
{
"id": "marketing",
"label": "Marketing",
"desc": "Se usa para personalizar anuncios y medir campañas.",
"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> Cómo usarlo
Coloca el código generado justo antes de la etiqueta de cierre body en todas las páginas. No tiene dependencias ni añade peticiones de red.
Cambia el tipo de una etiqueta de seguimiento a text/plain y añade data-consent="analytics". El banner la ejecuta en cuanto se acepta esa categoría, y nunca antes.
Añade un enlace en el pie que llame a window.showConsentPreferences() para que los visitantes puedan reabrir el panel. Cada decisión también lanza un evento consentchange que puedes escuchar.
Preguntas frecuentes
Te da la mecánica que esperan los reguladores: ninguna cookie opcional antes del consentimiento, rechazar tan fácil como aceptar, elección por categoría y una forma de cambiar de opinión después. El cumplimiento también depende de qué ejecutas realmente, de lo que diga tu política y de dónde estén tus visitantes, así que trata el código generado como un buen punto de partida y no como asesoramiento legal.
Dale a la etiqueta script el type="text/plain" y un atributo data-consent con el nombre de su categoría. El navegador no la ejecutará, y el banner la reescribe como etiqueta script real en cuanto se acepta esa categoría, en esta visita o en la siguiente, a partir de la decisión guardada.
En localStorage, bajo la clave que elijas, como un pequeño objeto JSON con un indicador por categoría y la fecha. El banner en sí no pone ninguna cookie y no se envía nada a un servidor, así que funciona en un sitio puramente estático.
Sí. La posición, el tema y el color de acento son opciones aquí, y cada elemento del CSS generado lleva el prefijo cc-, así que puedes sobrescribir las reglas desde tu propia hoja de estilos sin tocar el fragmento.
Para un sitio con unas pocas categorías, este fragmento suele bastar. En cuanto necesites registros de consentimiento, varios dominios o una analítica que respete la elección automáticamente, el gestor de consentimiento integrado de PulsePanda se encarga de todo.
Relacionado
PulsePanda incluye un gestor de consentimiento integrado: sin cookies por defecto y deja de recoger datos en cuanto alguien se da de baja. Sin un segundo proveedor ni código de pegamento.
Empezar gratis