Un usuario entra en tu web. Tarda 200 milisegundos en cargar el DOM, otros 300 en que React se inicialice, y el banner de consentimiento aparece medio segundo después. Para entonces, Google Analytics ya ha enviado el evento page_view, Meta Pixel ha disparado PageView, y Hotjar ha empezado a grabar la sesión. El usuario ve el banner, piensa un momento, y hace clic en "Rechazar todo". Pero sus datos ya están en camino a servidores en Estados Unidos, Irlanda y Singapur.
Este escenario ocurre en la inmensa mayoría de webs que "cumplen" con GDPR. Técnicamente tienen un banner. Técnicamente guardan las preferencias. Pero los scripts de tracking se cargan antes de que el usuario tenga oportunidad de decidir. Es cumplimiento cosmético, no cumplimiento real.
El problema se multiplica cuando tu aplicación sirve usuarios de diferentes países. GDPR en Europa requiere opt-in explícito antes de cualquier tracking. CCPA en California permite opt-out, pero tienes que respetar la señal "Do Not Sell". LGPD en Brasil tiene sus propias reglas. POPIA en Sudáfrica, PDPA en Tailandia, PIPL en China. Son 52 leyes de privacidad diferentes con requisitos que varían desde "puedes trackear por defecto" hasta "necesitas consentimiento explícito para cada servicio individual".
Implementar esto correctamente significa semanas de trabajo. Investigar cada ley, implementar detección geográfica, configurar cada servicio de analytics, crear un sistema de categorías, manejar el consentimiento granular, generar logs de auditoría para cuando venga el auditor de protección de datos. Y después de todo ese trabajo, descubres que tu implementación tiene un bug y los scripts siguen cargando antes del consentimiento.
Por qué la mayoría de banners no cumplen realmente
El problema fundamental es el orden de ejecución. En una aplicación React típica, el HTML incluye tags de script en el <head> o al final del <body>. Estos scripts empiezan a ejecutarse antes de que React monte ningún componente. Tu banner de consentimiento es un componente React que se renderiza después de que la aplicación hidrate. Para cuando el banner existe en el DOM, los scripts de tracking llevan ejecutándose cientos de milisegundos.
Algunas soluciones intentan arreglar esto con CSS. Añaden display: none al contenido hasta que el usuario consiente. Esto oculta el contenido visualmente, pero no impide que los scripts se ejecuten. Google Analytics sigue contando la visita. Los pixels de conversión siguen disparándose.
Otras soluciones usan el atributo type="text/plain" en los scripts de tracking y lo cambian a type="text/javascript" después del consentimiento. Esto funciona para scripts que tú controlas, pero no para scripts que se inyectan dinámicamente. Google Tag Manager, por ejemplo, inyecta scripts adicionales después de cargarse. Bloquear el script inicial de GTM no bloquea los scripts que GTM inyecta posteriormente.
El caso más problemático son los scripts de terceros que cargan más scripts. Meta Pixel carga un script inicial que después carga módulos adicionales según la configuración. TikTok Pixel hace lo mismo. Hotjar carga un script que después carga el grabador de sesiones. Bloquear el script padre no garantiza bloquear los hijos si ya se disparó la carga.
La única solución real es interceptar a nivel DOM. No basta con controlar qué scripts incluyes en tu HTML. Necesitas interceptar cualquier script que intente añadirse al DOM, venga de donde venga, y bloquearlo hasta que exista consentimiento válido.
Por qué creé esta librería
Necesitaba implementar consentimiento de cookies para una aplicación SaaS con presencia internacional. Usuarios en Europa que requerían GDPR estricto con opt-in explícito. Usuarios en California bajo CCPA con requisitos de opt-out y "Do Not Sell". Usuarios en Brasil con LGPD, en Canadá con PIPEDA, en Asia con variaciones de PDPA. Un mismo producto, decenas de leyes diferentes, y la expectativa de que todo funcionara sin que el equipo de desarrollo dedicara meses a investigar legislación de privacidad.
Las soluciones existentes tenían limitaciones. Los servicios de pago como Cookiebot o OneTrust cuestan cientos de euros al mes y añaden latencia porque cargan desde sus servidores. Las librerías open source que encontré solo mostraban el banner sin bloquear realmente los scripts, o requerían configuración manual de cada servicio, o no soportaban detección geográfica.
Lo que necesitaba era una librería que bloqueara scripts de verdad a nivel DOM, que detectara automáticamente la ubicación del usuario y aplicara la ley correcta, que tuviera los servicios más comunes preconfigurados para no tener que investigar qué cookies usa cada uno, y que generara logs de auditoría porque los auditores de protección de datos los piden.
El resultado es react-consent-shield: bloqueo real de scripts con MutationObserver, 52 leyes de privacidad con detección geográfica, 274 servicios preconfigurados desde Google Analytics hasta Yandex Metrica, sistema de consentimiento granular a nivel de servicio individual, cookie scanner para detectar cookies no declaradas, y generación de reports de auditoría con verificación criptográfica.
Instalación y uso básico
npm install react-consent-shield
El caso más simple requiere tres componentes: el provider que gestiona el estado, el banner que muestra las opciones, y opcionalmente el modal para configuración detallada:
import {
ConsentProvider,
ConsentBanner,
ConsentModal,
googleAnalytics,
metaPixel,
} from 'react-consent-shield';
function App() {
return (
<ConsentProvider
config={{
services: [googleAnalytics, metaPixel],
}}
>
<YourApp />
<ConsentBanner />
<ConsentModal />
</ConsentProvider>
);
}
Con esta configuración mínima, los scripts de Google Analytics y Meta Pixel están bloqueados hasta que el usuario consiente. El banner aparece automáticamente para usuarios nuevos. Las preferencias se persisten en localStorage y se respetan en visitas posteriores.
Los servicios se importan como presets. Cada preset incluye los patrones de script que hay que bloquear, los nombres de cookies que el servicio crea, la categoría de consentimiento a la que pertenece, y la información que se muestra al usuario sobre qué datos recoge.
Cómo funciona el bloqueo real de scripts
La librería usa MutationObserver para interceptar modificaciones al DOM. Cuando cualquier código intenta añadir un elemento <script> al documento, el observer lo detecta antes de que el navegador procese el script.
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
mutation.addedNodes.forEach((node) => {
if (node.nodeName === 'SCRIPT') {
const src = node.getAttribute('src');
if (shouldBlock(src)) {
// Convertir a elemento inerte
node.type = 'text/blocked';
node.setAttribute('data-consent-blocked', 'true');
node.setAttribute('data-original-src', src);
node.removeAttribute('src');
}
}
});
});
});
observer.observe(document.documentElement, {
childList: true,
subtree: true,
});
El observer se activa antes de que React monte. Se registra en el <head> del documento como un script inline que ejecuta inmediatamente. Esto garantiza que cualquier script de tracking que intente cargarse, ya sea en el HTML inicial o inyectado dinámicamente por otro script, pasa por el filtro.
Cuando el usuario da consentimiento, los scripts bloqueados se restauran:
function unblockScripts(category: string) {
const blocked = document.querySelectorAll(
`script[data-consent-blocked="true"][data-category="${category}"]`
);
blocked.forEach((script) => {
const newScript = document.createElement('script');
newScript.src = script.getAttribute('data-original-src');
newScript.type = 'text/javascript';
script.parentNode.replaceChild(newScript, script);
});
}
Este enfoque tiene una ventaja importante: funciona con cualquier script, no solo los que tú controlas. Si un script de terceros intenta inyectar otro script de tracking, también se bloquea. Si un tag manager intenta cargar pixels adicionales, también se bloquean. El bloqueo ocurre a nivel DOM, no a nivel de configuración.
Detección geográfica automática
Implementar manualmente la lógica de "si el usuario está en Alemania aplica GDPR, si está en California aplica CCPA, si está en Brasil aplica LGPD" es tedioso y propenso a errores. La librería incluye detección geográfica que determina automáticamente qué ley aplica.
<ConsentProvider
config={{
services: [googleAnalytics, metaPixel],
geoDetection: {
enabled: true,
fallbackLaw: 'GDPR',
},
}}
>
La detección usa la API de geolocalización del navegador cuando está disponible, con fallback a detección por timezone y idioma del navegador. El resultado determina qué ley de privacidad aplica:
| Región | Ley | Comportamiento |
|---|---|---|
| UE (27 países) | GDPR | Opt-in obligatorio, consentimiento explícito |
| Reino Unido | UK-GDPR | Opt-in obligatorio, post-Brexit |
| California | CCPA | Opt-out permitido, "Do Not Sell" |
| Virginia, Colorado, Connecticut | Leyes estatales US | Variaciones de opt-out |
| Brasil | LGPD | Opt-in para datos sensibles |
| Canadá | PIPEDA | Consentimiento implícito permitido en algunos casos |
| Sudáfrica | POPIA | Opt-in con excepciones |
| Singapur, Tailandia | PDPA | Variaciones regionales |
| China | PIPL | Requisitos estrictos de localización |
| Otros 40+ | Leyes locales | Configuración específica por jurisdicción |
El fallbackLaw determina qué reglas aplicar cuando la detección falla o el usuario está en una región sin ley específica de privacidad. Configurar GDPR como fallback significa aplicar las reglas más estrictas por defecto, lo que garantiza cumplimiento en el peor caso.
Cada ley tiene configuración diferente para categorías de cookies. GDPR requiere consentimiento para analytics y marketing. CCPA permite analytics por defecto pero requiere opción de opt-out para "venta" de datos. Algunas leyes asiáticas permiten cookies funcionales sin consentimiento pero requieren opt-in para personalización.
Los 274 servicios preconfigurados
Investigar qué cookies crea Google Analytics, qué dominios usa Meta Pixel, qué scripts carga Hotjar, consume horas. La librería incluye 274 servicios preconfigurados con toda esta información:
import {
// Analytics
googleAnalytics,
googleTagManager,
metaPixel,
tiktokPixel,
hotjar,
mixpanel,
amplitude,
segment,
heap,
fullstory,
microsoftClarity,
// Advertising
googleAds,
metaAds,
linkedInAds,
twitterAds,
pinterestTag,
snapchatPixel,
criteo,
// Regional
yandexMetrica, // Rusia
baiduAnalytics, // China
naverAnalytics, // Corea del Sur
// Privacy-focused
plausible,
fathom,
simpleAnalytics,
} from 'react-consent-shield';
Cada preset es un objeto con la configuración completa del servicio:
const googleAnalytics: ServicePreset = {
id: 'google-analytics',
name: 'Google Analytics',
category: 'analytics',
description: 'Análisis de tráfico y comportamiento de usuarios',
privacyPolicy: 'https://policies.google.com/privacy',
scripts: [
/googletagmanager\.com\/gtag/,
/google-analytics\.com\/analytics/,
/googleanalytics\.com/,
],
cookies: [
{ name: '_ga', duration: '2 years', description: 'Distingue usuarios' },
{ name: '_gid', duration: '24 hours', description: 'Distingue usuarios' },
{ name: '_gat', duration: '1 minute', description: 'Limita tasa de peticiones' },
],
dataCollected: [
'Páginas visitadas',
'Tiempo en página',
'Fuente de tráfico',
'Dispositivo y navegador',
'Ubicación aproximada',
],
};
Los patrones de scripts son expresiones regulares que matchean URLs de scripts que hay que bloquear. La librería intercepta cualquier script cuya URL matchee alguno de estos patrones.
Las cookies listan las cookies que el servicio crea. Esta información se muestra al usuario en el modal de configuración detallada y se usa para el cookie scanner que detecta cookies no declaradas.
Para servicios que no están en la lista, puedes crear presets personalizados:
const myCustomService: ServicePreset = {
id: 'my-analytics',
name: 'My Custom Analytics',
category: 'analytics',
scripts: [/my-analytics\.com\/track/],
cookies: [
{ name: 'ma_id', duration: '1 year', description: 'ID de usuario' },
],
};
<ConsentProvider
config={{
services: [googleAnalytics, myCustomService],
}}
>
Google Consent Mode v2
Google introdujo Consent Mode como forma de comunicar el estado de consentimiento a sus servicios. La versión 2, obligatoria desde marzo de 2024 para sitios que usan Google Ads en el EEE, añade señales adicionales para publicidad personalizada.
La librería integra Consent Mode automáticamente:
<ConsentProvider
config={{
services: [googleAnalytics, googleAds],
googleConsentMode: {
enabled: true,
defaultState: {
analytics_storage: 'denied',
ad_storage: 'denied',
ad_user_data: 'denied',
ad_personalization: 'denied',
functionality_storage: 'granted',
personalization_storage: 'denied',
security_storage: 'granted',
},
},
}}
>
Cuando el usuario modifica su consentimiento, la librería actualiza automáticamente las señales de Consent Mode:
// Usuario acepta analytics pero rechaza ads
gtag('consent', 'update', {
analytics_storage: 'granted',
ad_storage: 'denied',
ad_user_data: 'denied',
ad_personalization: 'denied',
});
Google Analytics en modo denied sigue enviando pings pero sin cookies ni identificadores persistentes. Esto permite obtener datos agregados de tráfico mientras respetas la decisión del usuario. Google Ads con ad_storage: denied no puede hacer remarketing pero sigue pudiendo atribuir conversiones de forma agregada.
El hook useGoogleConsentMode permite acceder al estado actual de las señales:
function ConsentDebugger() {
const { consentState, updateConsent } = useGoogleConsentMode();
return (
<div>
<p>Analytics: {consentState.analytics_storage}</p>
<p>Ads: {consentState.ad_storage}</p>
<p>Ad User Data: {consentState.ad_user_data}</p>
<p>Ad Personalization: {consentState.ad_personalization}</p>
</div>
);
}
Sistema de consentimiento granular total
La mayoría de banners ofrecen tres botones: "Aceptar todo", "Rechazar todo", y "Configurar". La configuración suele ser por categorías amplias: analytics, marketing, funcionales. Esto no da control real al usuario que quiere permitir Google Analytics pero no Meta Pixel, o que quiere Hotjar para feedback pero no quiere que se graben sus sesiones.
La librería soporta tres niveles de granularidad:
Nivel 1: Todo o nada
<ConsentProvider
config={{
services: [googleAnalytics, metaPixel, hotjar],
granularConsent: false,
}}
>
El usuario acepta o rechaza todo. Simple pero poco flexible.
Nivel 2: Por categorías
<ConsentProvider
config={{
services: [googleAnalytics, metaPixel, hotjar],
granularConsent: true,
categories: {
analytics: { required: false, defaultEnabled: false },
marketing: { required: false, defaultEnabled: false },
functional: { required: true, defaultEnabled: true },
},
}}
>
El usuario puede aceptar analytics pero rechazar marketing. Los servicios se agrupan automáticamente por su categoría en el preset.
Nivel 3: Por servicio individual
<ConsentProvider
config={{
services: [googleAnalytics, metaPixel, hotjar, mixpanel, amplitude],
granularConsent: true,
serviceLevel: true,
}}
>
El usuario ve cada servicio individualmente y puede decidir: "Quiero Google Analytics pero no Mixpanel. Quiero Hotjar pero solo el feedback widget, no la grabación de sesiones."
El modal de configuración detallada muestra cada servicio con su descripción, qué datos recoge, qué cookies crea, y un enlace a su política de privacidad:
<ConsentModal
showServiceDetails={true}
showCookieInfo={true}
showDataCollected={true}
showPrivacyLinks={true}
/>
Para implementaciones que necesitan control programático, los hooks exponen el estado completo:
function MyCustomUI() {
const {
services,
categories,
isServiceEnabled,
toggleService,
toggleCategory,
enableAll,
disableAll,
} = useConsent();
return (
<div>
{services.map(service => (
<label key={service.id}>
<input
type="checkbox"
checked={isServiceEnabled(service.id)}
onChange={() => toggleService(service.id)}
/>
{service.name}
</label>
))}
</div>
);
}
Cookie Scanner: detectar cookies no declaradas
El problema de las cookies no declaradas es común. Instalas un plugin de WordPress y crea cookies que no sabías. Un script de terceros inyecta tracking adicional. Un desarrollador añade localStorage para algo y nadie lo documenta.
El cookie scanner detecta cookies que existen en el navegador pero no están declaradas en ningún servicio configurado:
import { useCookieScanner } from 'react-consent-shield';
function CookieAudit() {
const { scan, results, isScanning } = useCookieScanner();
useEffect(() => {
scan();
}, []);
if (isScanning) return <p>Escaneando cookies...</p>;
return (
<div>
<h3>Cookies declaradas ({results.declared.length})</h3>
<ul>
{results.declared.map(cookie => (
<li key={cookie.name}>
{cookie.name} - {cookie.service}
</li>
))}
</ul>
<h3>Cookies NO declaradas ({results.undeclared.length})</h3>
<ul>
{results.undeclared.map(cookie => (
<li key={cookie.name} style={{ color: 'red' }}>
{cookie.name} - ORIGEN DESCONOCIDO
</li>
))}
</ul>
</div>
);
}
El scanner compara las cookies actuales del navegador contra la lista de cookies declaradas en todos los servicios configurados. Las cookies que no matchean ningún servicio aparecen como "no declaradas".
Esto es crítico para auditorías de cumplimiento. Un auditor de protección de datos puede pedir la lista de todas las cookies que tu sitio crea. Si hay cookies que no están documentadas en tu política de privacidad, tienes un problema. El scanner te permite detectar esto antes de que lo haga el auditor.
El scanner también detecta cookies de terceros que se crean sin tu conocimiento:
const { results } = useCookieScanner({
includeThirdParty: true,
includeSessionStorage: true,
includeLocalStorage: true,
});
// results.thirdParty contiene cookies de otros dominios
// results.localStorage contiene claves de localStorage
// results.sessionStorage contiene claves de sessionStorage
Audit logging y reports para auditorías
Cuando un auditor de protección de datos te visita, necesita ver evidencia de que tu sistema de consentimiento funciona correctamente. No basta con mostrarle el banner. Quiere ver registros de cuándo cada usuario dio consentimiento, qué opciones eligió, si cambió de opinión, y que estos registros no han sido manipulados.
La librería genera logs de auditoría con verificación criptográfica:
<ConsentProvider
config={{
services: [googleAnalytics, metaPixel],
auditLog: {
enabled: true,
hashAlgorithm: 'SHA-256',
includeUserAgent: true,
includeTimestamp: true,
storage: 'localStorage', // o 'server' para enviar a tu backend
},
}}
>
Cada acción de consentimiento genera un registro:
{
id: 'consent-log-1701432000000',
timestamp: '2025-12-01T12:00:00.000Z',
action: 'consent-updated',
previousState: {
analytics: false,
marketing: false,
},
newState: {
analytics: true,
marketing: false,
},
services: {
'google-analytics': true,
'meta-pixel': false,
'hotjar': true,
},
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...',
geoLocation: 'DE',
lawApplied: 'GDPR',
hash: 'a1b2c3d4e5f6...',
previousHash: '9z8y7x6w5v...',
}
El campo hash es un SHA-256 del contenido del registro más el hash del registro anterior. Esto crea una cadena donde modificar cualquier registro invalida todos los siguientes. Si el auditor ve que los hashes no coinciden, sabe que alguien manipuló los logs.
Para acceder a los logs programáticamente:
import { useAuditLog } from 'react-consent-shield';
function AuditViewer() {
const { logs, exportLogs, verifyIntegrity } = useAuditLog();
const handleExport = () => {
const data = exportLogs({ format: 'json' });
downloadFile(data, 'consent-audit-log.json');
};
const handleVerify = async () => {
const isValid = await verifyIntegrity();
alert(isValid ? 'Logs íntegros' : 'ALERTA: Logs manipulados');
};
return (
<div>
<button onClick={handleExport}>Exportar logs</button>
<button onClick={handleVerify}>Verificar integridad</button>
<table>
<thead>
<tr>
<th>Fecha</th>
<th>Acción</th>
<th>Servicios</th>
<th>Hash</th>
</tr>
</thead>
<tbody>
{logs.map(log => (
<tr key={log.id}>
<td>{new Date(log.timestamp).toLocaleString()}</td>
<td>{log.action}</td>
<td>{Object.keys(log.services).filter(s => log.services[s]).join(', ')}</td>
<td>{log.hash.substring(0, 16)}...</td>
</tr>
))}
</tbody>
</table>
</div>
);
}
La librería también genera reports de cumplimiento en formato JSON y HTML:
import { generateComplianceReport } from 'react-consent-shield';
const report = generateComplianceReport({
format: 'html', // o 'json'
includeServiceDetails: true,
includeCookieInventory: true,
includeAuditSummary: true,
includeLawConfiguration: true,
});
// El report incluye:
// - Lista de todos los servicios configurados
// - Inventario completo de cookies
// - Resumen de logs de auditoría
// - Configuración de cada ley de privacidad
// - Scripts bloqueados y desbloqueados
// - Resultado del cookie scanner
El report HTML está formateado para imprimir y entregar a auditores. Incluye tablas con todos los servicios, sus cookies, qué datos recogen, y el estado actual del consentimiento.
Características adicionales
Verificación de edad
Para sitios accesibles a menores, COPPA (USA) y GDPR-K (artículo 8 de GDPR) requieren verificación de edad:
<ConsentProvider
config={{
services: [googleAnalytics],
ageVerification: {
enabled: true,
method: 'birthdate', // 'checkbox' | 'year' | 'birthdate'
minimumAge: 16,
parentalConsentRequired: true,
blockTrackingIfUnderage: true,
},
}}
>
Si el usuario indica que es menor de la edad mínima, todos los scripts de tracking permanecen bloqueados independientemente de otras opciones.
Compartir consentimiento entre subdominios
Para aplicaciones con múltiples subdominios (app.example.com, blog.example.com, shop.example.com), el consentimiento dado en uno debe aplicar a todos:
<ConsentProvider
config={{
services: [googleAnalytics],
storage: {
type: 'cookie',
domain: '.example.com', // Nota el punto inicial
sameSite: 'lax',
},
}}
>
La cookie de consentimiento se crea con dominio .example.com, lo que la hace accesible desde cualquier subdominio.
Versionado de consentimiento
Cuando añades un nuevo servicio o cambias la configuración, puede ser necesario pedir consentimiento de nuevo:
<ConsentProvider
config={{
services: [googleAnalytics, metaPixel, newService],
consentVersion: '2.0',
onVersionChange: (oldVersion, newVersion) => {
// Opcionalmente mostrar el banner de nuevo
return true; // true = pedir consentimiento de nuevo
},
}}
>
La librería detecta cambios en la lista de servicios y puede invalidar el consentimiento anterior automáticamente, mostrando el banner aunque el usuario ya hubiera elegido antes.
Personalización del banner
La librería incluye 8 variantes de banner prediseñadas:
<ConsentBanner
variant="default" // Barra inferior estándar
// variant="fullwidth" // Barra de ancho completo
// variant="modal" // Modal centrado
// variant="floating" // Flotante con sombra
// variant="card" // Tarjeta compacta
// variant="minimal" // Solo texto y botones
// variant="corner" // Esquina inferior
// variant="sidebar" // Panel lateral
position="bottom" // 'top' | 'bottom' | 'bottom-left' | 'bottom-right'
theme="light" // 'light' | 'dark' | 'auto'
/>
Todos los textos son personalizables:
<ConsentBanner
texts={{
title: 'Usamos cookies',
description: 'Este sitio usa cookies para mejorar tu experiencia.',
acceptAll: 'Aceptar todas',
rejectAll: 'Rechazar todas',
customize: 'Personalizar',
privacyPolicy: 'Política de privacidad',
}}
/>
La librería incluye traducciones para 10 idiomas:
<ConsentProvider
config={{
services: [googleAnalytics],
language: 'es', // 'en' | 'es' | 'de' | 'fr' | 'pt' | 'it' | 'nl' | 'pl' | 'ja' | 'zh'
}}
>
Para idiomas no incluidos, puedes proporcionar traducciones personalizadas:
<ConsentProvider
config={{
services: [googleAnalytics],
translations: {
title: 'Käytämme evästeitä',
description: 'Tämä sivusto käyttää evästeitä...',
acceptAll: 'Hyväksy kaikki',
rejectAll: 'Hylkää kaikki',
// ... resto de textos
},
}}
>
La accesibilidad es WCAG 2.2 AA completa: navegación por teclado, soporte para lectores de pantalla, focus trap en modales, contraste suficiente en todos los temas.
Casos de uso reales
E-commerce con múltiples regiones
<ConsentProvider
config={{
services: [
googleAnalytics,
googleAds,
metaPixel,
criteo,
hotjar,
],
geoDetection: { enabled: true, fallbackLaw: 'GDPR' },
googleConsentMode: { enabled: true },
granularConsent: true,
auditLog: { enabled: true },
}}
>
La tienda online detecta automáticamente si el usuario está en Europa (GDPR estricto), California (CCPA con opt-out), o resto del mundo. Google Consent Mode permite seguir midiendo conversiones agregadas incluso cuando usuarios rechazan cookies.
SaaS B2B con requisitos de compliance
<ConsentProvider
config={{
services: [
mixpanel,
amplitude,
segment,
intercom,
fullstory,
],
granularConsent: true,
serviceLevel: true,
auditLog: {
enabled: true,
storage: 'server',
endpoint: '/api/consent-logs',
},
complianceReport: { enabled: true },
}}
>
El producto SaaS permite control granular por servicio porque sus clientes enterprise lo exigen. Los logs de auditoría se envían al servidor para almacenamiento centralizado. Los reports de compliance se generan para incluir en documentación de seguridad.
Blog personal con analytics respetuosos
<ConsentProvider
config={{
services: [plausible],
banner: {
variant: 'minimal',
position: 'bottom-right',
},
}}
>
Plausible no usa cookies y puede no requerir consentimiento en algunas jurisdicciones, pero mostrar un banner demuestra transparencia y genera confianza.
Testing y calidad
La librería tiene 323 tests con 100% de cobertura en todas las métricas:
| Métrica | Cobertura |
|---|---|
| Statements | 100% |
| Branches | 100% |
| Functions | 100% |
| Lines | 100% |
Los tests cubren:
- Bloqueo de scripts para cada uno de los 274 servicios
- Detección geográfica para las 52 leyes soportadas
- Traducciones completas en los 10 idiomas
- Integración con Google Consent Mode
- Cookie scanner con diferentes configuraciones de navegador
- Generación y verificación de audit logs
- Accesibilidad con lectores de pantalla simulados
- Renderizado de todas las variantes de banner
Compatibilidad verificada:
- React 18 y React 19
- Next.js 14 y Next.js 15
- TypeScript 5.3+
- Node.js 18+
- Chrome 80+, Firefox 75+, Safari 13+, Edge 80+
El paquete está publicado en NPM como react-consent-shield. El código fuente está en github.com/686f6c61/react-consent-shield. La demo interactiva está en react-consent-shield.onrender.com donde puedes probar todas las configuraciones en tiempo real.