Introducción
CookiePilot es una plataforma de gestión del consentimiento (CMP), conforme al RGPD, al artículo 22.2 de la LSSI (Ley 34/2002) y a Google Consent Mode v2.
Para quién es
- Propietarios de webs: despliegue sin necesidad de programar.
- Desarrolladores: API, eventos, integraciones con GTM.
- Agencias: marca blanca, gestión multidominio.
Inicio rápido
Paso 1: Regístrate
- Crea una cuenta en app.cookiepilot.io/register.
- Añade tu dominio en el panel y copia la clave de API (formato
cp_live_...).
Paso 2: Instala el código
Una instalación directa son dos scripts en el <head>, en este orden.
Paso 2a: Consentimiento por defecto (stub inline). Pega esto lo primero, antes que cualquier otro script (cookiepilot.js, GA, GTM, etiquetas de publicidad y seguimiento):
<script>"use strict";(function(){window.dataLayer=window.dataLayer||[];var d={ad_storage:"denied",ad_user_data:"denied",ad_personalization:"denied",analytics_storage:"denied",functionality_storage:"denied",personalization_storage:"denied",security_storage:"granted",wait_for_update:500},h=false;try{for(var i=0;i<window.dataLayer.length;i++){var x=window.dataLayer[i];if(x&&x[0]==="consent"&&x[1]==="default"){h=true;break}}}catch(err){}if(!h&&window.dataLayer.length)window.dataLayer.unshift(["consent","default",d]);window.gtag=function(){window.dataLayer.push(arguments)};if(!h)window.gtag("consent","default",d);var a=document.cookie.match(/(^|)cookiepilot_consent=([^;]+)/);if(a){try{var e=JSON.parse(decodeURIComponent(a[2]));window.gtag("consent","update",{analytics_storage:e.analytics?"granted":"denied",ad_storage:e.marketing?"granted":"denied",ad_user_data:e.marketing?"granted":"denied",ad_personalization:e.marketing?"granted":"denied",functionality_storage:e.preferences?"granted":"denied",personalization_storage:e.preferences?"granted":"denied",security_storage:"granted"})}catch(err){}}})();</script>
Este snippet inline pone de inmediato cada categoría en denied (con wait_for_update: 500), de modo que el estado por defecto de Google Consent Mode v2 queda listo antes de que se cargue nada más. Para un visitante recurrente lee el consentimiento guardado directamente de la cookie y dispara un consent update.
Paso 2b: Script del banner. Añádelo justo después del stub inline:
<!-- CookiePilot -->
<script async src="https://cdn.cookiepilot.io/cookiepilot.js" data-cpkey="TWOJ_KLUCZ"></script>
Paso 3: Configura el banner
En el panel: Dominio → Configuración → Apariencia:
- posición del banner (arriba, abajo, modal),
- colores y textos,
- un botón flotante de «Configuración de cookies» para los visitantes recurrentes.
Integración con Google Tag Manager
Con GTM instalas CookiePilot con una sola etiqueta Custom HTML que fija el estado de consentimiento por defecto y carga el banner en la fase más temprana de GTM. No necesitas un archivo stub aparte ni una segunda etiqueta.
Etiqueta: CookiePilot - Consent Init + Banner
En GTM, crea una etiqueta Custom HTML (Etiquetas → Nueva → HTML personalizado) y pega:
<script>"use strict";
(function() {
window.dataLayer=window.dataLayer||[];var d={ad_storage:"denied",ad_user_data:"denied",ad_personalization:"denied",analytics_storage:"denied",functionality_storage:"denied",personalization_storage:"denied",security_storage:"granted",wait_for_update:500},h=false;try{for(var i=0;i<window.dataLayer.length;i++){var x=window.dataLayer[i];if(x&&x[0]==="consent"&&x[1]==="default"){h=true;break}}}catch(err){}if(!h&&window.dataLayer.length)window.dataLayer.unshift(["consent","default",d]);window.gtag=function(){window.dataLayer.push(arguments)};if(!h)window.gtag("consent","default",d);var a=document.cookie.match(/(^|)cookiepilot_consent=([^;]+)/);if(a){try{var e=JSON.parse(decodeURIComponent(a[2]));window.gtag("consent","update",{analytics_storage:e.analytics?"granted":"denied",ad_storage:e.marketing?"granted":"denied",ad_user_data:e.marketing?"granted":"denied",ad_personalization:e.marketing?"granted":"denied",functionality_storage:e.preferences?"granted":"denied",personalization_storage:e.preferences?"granted":"denied",security_storage:"granted"})}catch(err){}}
var s = document.createElement('script');
s.src = 'https://cdn.cookiepilot.io/cookiepilot.js?cpkey=' + encodeURIComponent('TWOJ_KLUCZ');
document.head.appendChild(s);
})();
</script>
Activador: Consent Initialization - All Pages. La etiqueta debe dispararse una vez por página. Las etiquetas de Google (GA4, Google Ads), Facebook Pixel y demás etiquetas de marketing NO usan el activador Consent Initialization; se disparan más tarde (Consent Checks o un activador dependiente del consentimiento). Guarda la etiqueta y publica el contenedor de GTM.
Orden y activadores
| Orden | Etiqueta | Activador |
|---|---|---|
| 1 | CookiePilot - Consent Init + Banner | Consent Initialization - All Pages |
| 2 | GA4, Google Ads, UET | All Pages (Consent Mode gestiona el consentimiento por sí mismo) |
| 3 | Facebook Pixel, TikTok, LinkedIn, etc. | Custom Event cookiepilot_consent_update + condición de consentimiento (ver abajo) |
Etiquetas ajenas a Google (Facebook Pixel, TikTok, LinkedIn)
Google Consent Mode solo cubre las etiquetas de Google. Para cualquier otro script, el widget envía un evento al dataLayer en cada cambio de consentimiento:
dataLayer.push({
event: 'cookiepilot_consent_update',
cookiepilot_consent: {
necessary: true,
analytics: true,
marketing: true,
preferences: false
}
});
El evento también se dispara en cada visita de un usuario recurrente (cuando el widget lee la cookie de consentimiento), así que el activador de GTM funciona en cada visita, no solo en la primera decisión.
Patrón común (haz esto una vez)
Configuras estas tres piezas una sola vez y luego las reutilizas para todas las etiquetas ajenas a Google.
- Activador (Activadores → Nuevo → Evento personalizado): nombre del evento
cookiepilot_consent_update. Sin condiciones, sin «Una vez por página» (la etiqueta debe poder dispararse de nuevo tras una decisión cambiada). - Variable de capa de datos para cada categoría que uses:
- Nombre
cookiepilot_consent.marketing→ variable, p. ej.dlv.cp_marketing - Nombre
cookiepilot_consent.analytics→ variable, p. ej.dlv.cp_analytics - Nombre
cookiepilot_consent.preferences→ variable, p. ej.dlv.cp_preferences
- Nombre
- Grupo de activadores o una condición en el activador:
dlv.cp_marketing equals true(para etiquetas de marketing) o el campo que corresponda.
En cada uno de los ejemplos de abajo, el activador es el mismo Custom Event con una condición añadida sobre la variable adecuada.
Facebook Pixel
Etiqueta en GTM: Etiquetas → Nueva → HTML personalizado.
<script>
!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;
n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,
document,'script','https://connect.facebook.net/en_US/fbevents.js');
fbq('init', 'YOUR_PIXEL_ID');
fbq('track', 'PageView');
</script>
- Activador:
cookiepilot_consent_update+ condicióndlv.cp_marketing equals true. - Opciones de disparo de la etiqueta: Once per page.
Opcionalmente, para un pleno cumplimiento con Facebook Limited Data Use, añade una segunda etiqueta que llame a fbq('consent','revoke') con el activador dlv.cp_marketing equals false.
TikTok Pixel
Etiqueta en GTM: Etiquetas → Nueva → HTML personalizado.
<script>
!function (w, d, t) {
w.TiktokAnalyticsObject=t;var ttq=w[t]=w[t]||[];ttq.methods=["page","track","identify","instances","debug","on","off","once","ready","alias","group","enableCookie","disableCookie","holdConsent","revokeConsent","grantConsent"],ttq.setAndDefer=function(t,e){t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}};for(var i=0;i<ttq.methods.length;i++)ttq.setAndDefer(ttq,ttq.methods[i]);ttq.instance=function(t){for(var e=ttq._i[t]||[],n=0;n<ttq.methods.length;n++)ttq.setAndDefer(e,ttq.methods[n]);return e},ttq.load=function(e,n){var r="https://analytics.tiktok.com/i18n/pixel/events.js",o=n&&n.partner;ttq._i=ttq._i||{},ttq._i[e]=[],ttq._i[e]._u=r,ttq._t=ttq._t||{},ttq._t[e]=+new Date,ttq._o=ttq._o||{},ttq._o[e]=n||{};n=document.createElement("script");n.type="text/javascript",n.async=!0,n.src=r+"?sdkid="+e+"&lib="+t;e=document.getElementsByTagName("script")[0];e.parentNode.insertBefore(n,e)};
ttq.load('YOUR_TIKTOK_PIXEL_ID');
ttq.grantConsent();
ttq.page();
}(window, document, 'ttq');
</script>
- Activador:
cookiepilot_consent_update+ condicióndlv.cp_marketing equals true. - Opciones de disparo de la etiqueta: Once per page.
ttq.grantConsent() es la nueva API de TikTok (introducida en 2024). Sin ella, TikTok recibe datos con hash sin consentimiento, lo que incumple sus condiciones.
LinkedIn Insight Tag
<script type="text/javascript">
_linkedin_partner_id = "YOUR_LINKEDIN_PARTNER_ID";
window._linkedin_data_partner_ids = window._linkedin_data_partner_ids || [];
window._linkedin_data_partner_ids.push(_linkedin_partner_id);
</script>
<script type="text/javascript">
(function(l) {
if (!l){window.lintrk = function(a,b){window.lintrk.q.push([a,b])};
window.lintrk.q=[]}
var s = document.getElementsByTagName("script")[0];
var b = document.createElement("script");
b.type = "text/javascript";b.async = true;
b.src = "https://snap.licdn.com/li.lms-analytics/insight.min.js";
s.parentNode.insertBefore(b, s);})(window.lintrk);
</script>
- Activador:
cookiepilot_consent_update+ condicióndlv.cp_marketing equals true. - Opciones de disparo de la etiqueta: Once per page.
Hotjar
<script>
(function(h,o,t,j,a,r){
h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};
h._hjSettings={hjid:YOUR_HOTJAR_ID,hjsv:6};
a=o.getElementsByTagName('head')[0];
r=o.createElement('script');r.async=1;
r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv;
a.appendChild(r);
})(window,document,'https://static.hotjar.com/c/hotjar-',".js?sv=");
</script>
- Activador:
cookiepilot_consent_update+ condicióndlv.cp_analytics equals true. - Opciones de disparo de la etiqueta: Once per page.
Hotjar va bajo analytics, no marketing (mide el comportamiento, no la publicidad). Revisa tu propia política de cookies, algunas empresas clasifican Hotjar de otra forma.
Microsoft Clarity
<script type="text/javascript">
(function(c,l,a,r,i,t,y){
c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);
})(window, document, "clarity", "script", "YOUR_CLARITY_PROJECT_ID");
</script>
- Activador:
cookiepilot_consent_update+ condicióndlv.cp_analytics equals true. - Opciones de disparo de la etiqueta: Once per page.
Pinterest Tag
<script>
!function(e){if(!window.pintrk){window.pintrk = function () {
window.pintrk.queue.push(Array.prototype.slice.call(arguments))};var
n=window.pintrk;n.queue=[],n.version="3.0";var
t=document.createElement("script");t.async=!0,t.src=e;var
r=document.getElementsByTagName("script")[0];
r.parentNode.insertBefore(t,r)}}("https://s.pinimg.com/ct/core.js");
pintrk('load', 'YOUR_PINTEREST_TAG_ID');
pintrk('page');
</script>
- Activador:
cookiepilot_consent_update+ condicióndlv.cp_marketing equals true. - Opciones de disparo de la etiqueta: Once per page.
Microsoft Ads (UET)
UET admite Google Consent Mode desde finales de 2023, así que no necesitas un activador Custom Event. Añade la etiqueta de la forma estándar (All Pages, Once per page) y UET lee ad_storage de GCM por sí mismo, que es lo que fija el widget.
Mapeo de categorías (resumen)
| Etiqueta | Categoría | Campo en cookiepilot_consent |
|---|---|---|
| Facebook Pixel | marketing | marketing |
| TikTok Pixel | marketing | marketing |
| LinkedIn Insight | marketing | marketing |
| marketing | marketing | |
| Hotjar | analytics | analytics |
| Microsoft Clarity | analytics | analytics |
| Mixpanel, Amplitude | analytics | analytics |
| Intercom, Drift, Crisp | preferences | preferences |
| GA4, Google Ads, UET | (GCM, sin activador) | gestionado por gtag('consent','update') |
Referencia de la API
CookiePilot expone el objeto window.CookiePilot:
| Método | Descripción |
|---|---|
CookiePilot.getConsent() | El estado de consentimiento actual, o null si no se ha tomado ninguna decisión. |
CookiePilot.acceptAll() | Consentir todas las categorías. |
CookiePilot.rejectAll() | Rechaza todo salvo necessary. |
CookiePilot.updateConsent(partial) | Actualiza las categorías seleccionadas, p. ej. { analytics: true }. |
CookiePilot.showSettings() | Abre el modal de preferencias. |
CookiePilot.hideSettings() | Cierra el modal de preferencias. |
CookiePilot.showMyConsent() / hideMyConsent() | Muestra/oculta el botón flotante. |
Ejemplo
const consent = CookiePilot.getConsent();
// { necessary: true, analytics: true, marketing: false, preferences: false }
CookiePilot.updateConsent({ analytics: true });
document.getElementById('cookie-settings').addEventListener('click', () => {
CookiePilot.showSettings();
});
Enlace «Gestionar cookies» en el pie de página
<a href="#" onclick="CookiePilot.showSettings(); return false;">Gestionar cookies</a>
Eventos JavaScript
El widget lanza un evento nativo cookiepilot:consent en window. El listener debe registrarse antes de que el widget se cargue si quieres captar el evento para un visitante recurrente (el disparo se produce de inmediato en cuanto arranca el widget):
<script>
window.addEventListener('cookiepilot:consent', (e) => {
if (e.detail.marketing) {
fbq('init', 'YOUR_PIXEL_ID');
}
});
</script>
<script src="https://cdn.cookiepilot.io/cookiepilot.js" data-cpkey="TWOJ_KLUCZ"></script>
e.detail contiene la misma carga útil que getConsent(). Para integraciones basadas en GTM, usa el evento del dataLayer descrito arriba en lugar de este, porque el dataLayer es un array persistente y GTM recoge los eventos históricos.
Categorías de consentimiento
| Categoría | Descripción | Por defecto |
|---|---|---|
necessary | Necesarias para que la web funcione | Siempre activas |
analytics | Estadísticas y analítica | Requiere consentimiento |
marketing | Publicidad y remarketing | Requiere consentimiento |
preferences | Personalización, idioma | Requiere consentimiento |
Mapeo a Google Consent Mode
| Categoría de CookiePilot | Campos de Consent Mode |
|---|---|
analytics | analytics_storage |
marketing | ad_storage, ad_user_data, ad_personalization |
preferences | functionality_storage, personalization_storage |
| (siempre) | security_storage: granted |
Google Consent Mode v2
La versión 2 añadió ad_user_data y ad_personalization (obligatorios desde marzo de 2024 en la UE/EEE para la publicidad de Google).
| Parámetro | Descripción |
|---|---|
ad_storage | Cookies de publicidad |
analytics_storage | Cookies de analítica |
ad_user_data | Envío de datos del usuario a Google |
ad_personalization | Personalización de anuncios |
functionality_storage | Cookies funcionales |
personalization_storage | Cookies de personalización |
security_storage | Siempre granted |
Cómo funciona:
- El stub pone cada campo en
deniedde forma síncrona, conwait_for_update: 500. - Tras la decisión del usuario, el widget dispara
gtag('consent', 'update', {...})usando el mapeo de arriba. - Para un visitante recurrente, el paso 2 se dispara de inmediato en cuanto arranca el widget, en función de la cookie.
Configuración de la apariencia
En el panel: Dominio → Configuración:
- Apariencia: posición, colores, disposición (BAR / BOX / MODAL).
- Textos: título, descripción, etiquetas de los botones, descripciones de las categorías. 13 idiomas (EN, PL, DE, FR, ES, IT, NL, PT, SV, CS, RO, EL, HU).
- Botón de consentimiento: un botón flotante de «Configuración de cookies» que se muestra tras la primera decisión (abajo a la izquierda/derecha).
- CSS personalizado: un campo para tus propios estilos. El widget se renderiza en el Shadow DOM, así que los selectores CSS del documento principal no funcionarán. Usa únicamente este campo.
Accesibilidad (WCAG 2.1 AA)
- ✅ Navegación por teclado (Tab, Shift+Tab, Enter, Escape).
- ✅ Etiquetas ARIA, role="dialog", aria-modal.
- ✅ Focus trap en el modal.
- ✅ Compatibilidad con lectores de pantalla (live regions al cambiar de estado).
- ✅ Diseño responsive.
Integraciones
WordPress
Tenemos un plugin oficial: CookiePilot en WordPress.org.
- Administración de WordPress → Plugins → Añadir nuevo → busca «CookiePilot».
- Instala y activa.
- Ajustes → CookiePilot → pega la clave de API del panel.
El plugin inserta el stub y la etiqueta en el <head> por sí mismo (en el orden correcto, por delante de otros scripts) y ofrece un shortcode [cookiepilot_settings] para un enlace «Gestionar cookies» en el pie de página.
Si prefieres no usar el plugin, usa «Insert Headers and Footers» y pega el snippet del Paso 2 del Inicio rápido en la sección Header.
Shopify
- Tienda → Temas → Editar código.
- En
theme.liquid, pega el snippet antes de</head>.
Next.js
// app/layout.tsx
import Script from 'next/script';
export default function RootLayout({ children }) {
return (
<html>
<head>
<Script
src="https://cdn.cookiepilot.io/cookiepilot.js"
data-cpkey="TWOJ_KLUCZ"
strategy="beforeInteractive"
/>
</head>
<body>{children}</body>
</html>
);
}
strategy="beforeInteractive" garantiza que el script del banner se ejecute pronto. Recuerda que el stub inline del Paso 2a (consentimiento por defecto) se añade por separado, en el <head> por delante de este script, por ejemplo mediante next/script con dangerouslySetInnerHTML o directamente en app/layout.tsx.
Preguntas frecuentes
¿El script ralentiza la web?
El bundle ronda los 12 KB comprimido con gzip y se carga de forma asíncrona. Sin impacto en los Core Web Vitals.
¿Cuánto tiempo se conserva el consentimiento?
La cookie con la decisión del usuario: 365 días por defecto (configurable en el panel). Eventos de analítica: 2 años (TTL de ClickHouse).
¿El evento cookiepilot_consent_update se dispara para los visitantes recurrentes?
Sí. El widget lee la cookie al arrancar y envía el evento al dataLayer. El activador Custom Event de GTM se dispara en cada visita, no solo en la primera decisión.
¿Dónde reporto un problema?
kontakt@cookiepilot.io o el chat del panel.
Lista de verificación tras el despliegue
Una vez instalado CookiePilot, verifica la configuración antes de lanzar campañas de publicidad.
1. Prueba antes de que el usuario dé su consentimiento
- Abre la web en modo incógnito y borra las cookies del dominio.
- Abre DevTools → Network y recarga la página.
- Antes de hacer clic en el consentimiento, confirma que:
- no se crean cookies de analítica/marketing, p. ej.
_ga,_gcl_*,_fbp,_ttp, - las etiquetas de marketing no envían peticiones a Meta/TikTok/LinkedIn antes del consentimiento de marketing,
- el
dataLayertiene el estado por defectodeniedparaad_storage,ad_user_data,ad_personalizationyanalytics_storage.
- no se crean cookies de analítica/marketing, p. ej.
2. Prueba tras aceptar el consentimiento
- Haz clic en «Aceptar todo».
- En DevTools, comprueba que apareció el evento
cookiepilot_consent_update. - Para las etiquetas de Google, comprueba en GTM Preview / Tag Assistant que Consent Mode cambió el estado a
grantedpara las categorías correspondientes. - Para GA4, comprueba en DebugView que los eventos empiezan a llegar tras el consentimiento.
- Para Meta Pixel / TikTok / LinkedIn, comprueba que las etiquetas se disparan solo después del evento
cookiepilot_consent_updatey de la condición de consentimiento de marketing.
3. Prueba rechazando el consentimiento
- Borra las cookies y recarga la página.
- Haz clic en «Rechazar todo».
- Confirma que las cookies y peticiones de marketing siguen sin activarse.
- Confirma que las funciones esenciales de la web siguen funcionando.
4. Errores frecuentes
- La etiqueta de GA4/Google Ads se dispara en
Consent Initializationen lugar de en un activador posterior. - El Meta Pixel o el TikTok Pixel no tiene condición sobre
cookiepilot_consent.marketing. - Un rastreador antiguo, escrito a fuego en el código, sigue en el
<head>antes de CookiePilot. - La documentación o la plantilla todavía tiene una URL de script desactualizada o un atributo identificador antiguo en lugar del
cookiepilot.jsactual condata-cpkey.
Evidencia de consentimiento, exportaciones y DSAR
CookiePilot registra los eventos de consentimiento para que puedas reconstruir el contexto de la decisión de un visitante. Un registro puede incluir la hora del evento, el tipo de evento, el dominio, la URL de la página o de origen, la versión del consentimiento, las categorías y la consent string cuando está disponible, la dirección IP anonimizada, el hash del user-agent, el tipo de dispositivo y el navegador.
Exportaciones
- Prueba de consentimiento de un visitante: JSON, CSV o HTML imprimible.
- Registro de auditoría del dominio: CSV o JSON para un rango de fechas seleccionado.
- Las exportaciones se limitan a tu organización y a los dominios a los que tienes acceso.
Flujo de DSAR
Un Owner o Admin puede iniciar una solicitud de acceso a datos desde una fila de consentimiento o desde la página de DSAR del panel. El panel encuentra los eventos del visitante, muestra el rango y permite descargar los archivos de prueba. Una solicitud de supresión requiere un motivo y queda registrada en el rastro de actividad de la organización.
Límites
Las exportaciones de auditoría de dominio usan el rango de fechas seleccionado y pueden truncarse en conjuntos de resultados muy grandes. La conservación del registro de consentimiento sigue el plan activo y la política de la cuenta, por lo que la documentación pública no promete un número fijo de años.