# Consent Mode v2: GDPR, CCPA e integración con CMPs

## Qué es Consent Mode v2

Consent Mode v2 es un mecanismo de Google que permite a los tags de Google
(GA4, Google Ads, Floodlight) adaptar su comportamiento según el consentimiento
del usuario. Introducido en 2024 como requisito para mantener la personalización
de anuncios en el EEE y UK.

### Los 4 parámetros de consentimiento

| Parámetro | Controla |
|-----------|----------|
| `analytics_storage` | Cookies de medición (GA4: `_ga`, `_ga_*`) |
| `ad_storage` | Cookies de publicidad (Google Ads, Floodlight) |
| `ad_user_data` | Envío de datos de usuario a Google para publicidad |
| `ad_personalization` | Remarketing y personalización de anuncios |

Cuando un parámetro está `denied`, Google no almacena cookies pero sí
registra eventos "sin cookies" (pings anónimos) para el modelado estadístico.

## Implementación base con gtag

El código de Consent Mode debe ejecutarse ANTES del snippet de GTM o gtag.
El orden importa: si GTM carga primero, puede crear cookies antes del consentimiento.

```html
<!-- 1. Snippet de Consent Mode — ANTES de GTM -->
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}

  gtag('consent', 'default', {
    analytics_storage: 'denied',
    ad_storage: 'denied',
    ad_user_data: 'denied',
    ad_personalization: 'denied',
    wait_for_update: 500,  // ms para esperar la respuesta del CMP
  });

  gtag('set', 'ads_data_redaction', true);  // Redactar URLs de click si denied
  gtag('set', 'url_passthrough', true);     // Pasar info de click en URL para atribución
</script>

<!-- 2. Snippet de GTM — DESPUÉS de Consent Mode -->
<script>
  (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
  new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
  j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
  'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
  })(window,document,'script','dataLayer','GTM-XXXXXXX');
</script>
```

### Actualizar consentimiento tras decisión del usuario

```javascript
// Llamar después de que el usuario acepta en el banner del CMP
function otorgarConsentimiento(opciones) {
  gtag('consent', 'update', {
    analytics_storage: opciones.analytics ? 'granted' : 'denied',
    ad_storage: opciones.publicidad ? 'granted' : 'denied',
    ad_user_data: opciones.publicidad ? 'granted' : 'denied',
    ad_personalization: opciones.publicidad ? 'granted' : 'denied',
  });
}

// Llamar cuando el usuario rechaza todo
function rechazarConsentimiento() {
  gtag('consent', 'update', {
    analytics_storage: 'denied',
    ad_storage: 'denied',
    ad_user_data: 'denied',
    ad_personalization: 'denied',
  });
}
```

## Integración con CMPs

### Cookiebot

Cookiebot dispara el evento `CookiebotOnAccept` / `CookiebotOnDecline`.
Integración directa disponible en GTM como template oficial de la galería.

```javascript
// Listener para Cookiebot
window.addEventListener('CookiebotOnAccept', function() {
  gtag('consent', 'update', {
    analytics_storage: Cookiebot.consent.statistics ? 'granted' : 'denied',
    ad_storage: Cookiebot.consent.marketing ? 'granted' : 'denied',
    ad_user_data: Cookiebot.consent.marketing ? 'granted' : 'denied',
    ad_personalization: Cookiebot.consent.marketing ? 'granted' : 'denied',
  });
}, false);
```

### OneTrust

OneTrust usa categorías de cookies mapeadas a grupos:

| Grupo OneTrust | Parámetro Consent Mode |
|---------------|----------------------|
| `C0002` (Performance) | `analytics_storage` |
| `C0004` (Targeting) | `ad_storage`, `ad_user_data`, `ad_personalization` |

```javascript
// Template GTM disponible en: OneTrust > GTM Integration
// O implementación manual:
window.OneTrust?.OnConsentChanged(function(event) {
  const activas = event.detail;
  gtag('consent', 'update', {
    analytics_storage: activas.includes('C0002') ? 'granted' : 'denied',
    ad_storage: activas.includes('C0004') ? 'granted' : 'denied',
    ad_user_data: activas.includes('C0004') ? 'granted' : 'denied',
    ad_personalization: activas.includes('C0004') ? 'granted' : 'denied',
  });
});
```

### Usercentrics

Usercentrics expone el objeto `UC_UI` y el evento `ucEvent`:

```javascript
window.addEventListener('ucEvent', function(e) {
  if (e.detail?.event === 'consent_status') {
    const servicios = e.detail;
    gtag('consent', 'update', {
      analytics_storage: servicios['Google Analytics'] ? 'granted' : 'denied',
      ad_storage: servicios['Google Ads'] ? 'granted' : 'denied',
      ad_user_data: servicios['Google Ads'] ? 'granted' : 'denied',
      ad_personalization: servicios['Google Ads'] ? 'granted' : 'denied',
    });
  }
});
```

## Modelado de conversiones en GA4

Cuando `analytics_storage` o `ad_storage` está `denied`, GA4 no puede
atribuir conversiones directamente. Google utiliza ML para estimar las
conversiones faltantes basándose en usuarios con consentimiento similar.

**Condiciones para que el modelado funcione**:
- Mínimo 1,000 conversiones observables por semana.
- Tasa de consentimiento > 0% (si nadie acepta, no hay datos base).
- Consent Mode implementado correctamente (los pings anónimos llegan).

**Verificar que los pings llegan**: En GA4 > Admin > Data streams > tu stream >
Measurement Protocol. Debe mostrar eventos incluso de usuarios sin consentimiento
(aparecen como eventos anónimos sin `client_id`).

## GDPR: base legal por tipo de tracking

| Tipo de tracking | Base legal posible | Requiere banner |
|-----------------|-------------------|-----------------|
| Analytics de medición interna | Interés legítimo (debatible) | Sí, en la mayoría de países |
| Analytics para mejora de producto | Interés legítimo | Sí |
| Retargeting / remarketing | Consentimiento explícito | Sí, siempre |
| Conversiones para optimización de anuncios | Consentimiento explícito | Sí, siempre |

**Práctica recomendada**: usar consentimiento explícito para todo tracking
publicitario y analítico. El interés legítimo es cuestionable y está siendo
restringido en interpretaciones recientes del GDPR.

**Registro de consentimiento**: almacenar en base de datos:
- Fecha y hora de la decisión
- Versión de la política de privacidad aceptada
- Opciones específicas seleccionadas por el usuario
- IP anonimizada (últimos 2 octetos a 0)

## CCPA: opt-out en lugar de opt-in

En California (CCPA), el modelo es inverso al GDPR: tracking activo por
defecto, con obligación de ofrecer opt-out.

```javascript
// URL de opt-out requerida por CCPA
// El usuario llega desde el enlace "No vender mi información personal"
if (new URLSearchParams(location.search).has('ccpa_opt_out')) {
  gtag('consent', 'update', {
    ad_storage: 'denied',
    ad_user_data: 'denied',
    ad_personalization: 'denied',
  });
  // Persistir la preferencia en localStorage
  localStorage.setItem('ccpa_opt_out', 'true');
}

// Al cargar la página, verificar opt-out previo
if (localStorage.getItem('ccpa_opt_out') === 'true') {
  gtag('consent', 'update', {
    ad_storage: 'denied',
    ad_user_data: 'denied',
    ad_personalization: 'denied',
  });
}
```

**US Privacy String**: formato `1YNN` (versión 1, aviso notificado, opt-out no,
LSPA no). Incluir en requests de publicidad si se usa un ad server compatible.

## Verificación con Consent Mode Inspector

En Chrome DevTools > Application > Cookies:
- Antes de aceptar: no deben existir `_ga`, `_ga_*`, `_gcl_*`, `_fbp`
- Después de aceptar analytics: `_ga` y `_ga_MEASUREMENTID` deben aparecer
- Después de aceptar publicidad: `_gcl_au` (Google Ads) debe aparecer

En la consola del browser:
```javascript
// Ver estado actual del consentimiento
window.dataLayer.filter(e => e[0] === 'consent')
// Debe mostrar el 'default' y los 'update' aplicados
```

Con la extensión **Consent Mode Inspector** de Google (Chrome Web Store):
muestra en tiempo real el estado de cada parámetro y los cambios al interactuar
con el banner de consentimiento.

## Checklist de cumplimiento pre-lanzamiento

- [ ] Consent Mode inicializado ANTES del snippet de GTM
- [ ] Default: los 4 parámetros en `denied`
- [ ] Banner de CMP visible en primera visita para usuarios del EEE
- [ ] `gtag('consent', 'update', ...)` se ejecuta al aceptar/rechazar
- [ ] Sin cookies `_ga`, `_fbp` antes del consentimiento (verificar en DevTools)
- [ ] Registro de consentimiento almacenado en base de datos
- [ ] Enlace "No vender mi información" visible en footer (para CCPA)
- [ ] Política de privacidad actualizada con tecnologías de tracking usadas
