Consentimiento de cookies para Next.js, Gatsby y sitios estáticos: guía de integración para desarrolladores

El problema del consentimiento en sitios estáticos

Los frameworks modernos de JavaScript como Next.js, Gatsby y Nuxt.js introdujeron un cambio de paradigma en cómo se construyen y entregan las páginas web. Las páginas se prerenderizan en tiempo de compilación o en el servidor y luego se hidratan en el cliente. Esto crea un desafío único para el consentimiento de cookies: el banner de consentimiento debe estar listo antes de que se ejecute cualquier script de seguimiento, pero la propia página puede estar ya renderizada y en caché en el edge.

Los CMP tradicionales se diseñaron para páginas renderizadas en servidor con PHP o HTML simple, donde el documento se carga linealmente de arriba abajo. En un mundo de frameworks con code splitting, carga diferida (lazy loading) y renderizado en servidor por streaming, esas suposiciones dejan de cumplirse. Hacer bien el consentimiento en estos entornos requiere entender el pipeline de renderizado.

Por qué el momento importa más de lo que crees

En una página HTML estándar, colocar un script de CMP en el <head> antes de otros scripts es sencillo. En Next.js App Router o Gatsby, la situación es más compleja:

El principio central es este: el consentimiento debe establecerse a nivel de script, no a nivel de componente. Un componente de React que renderiza un banner de consentimiento llega demasiado tarde si solo se vuelve interactivo después de la hidratación.

Integración con Next.js App Router

Next.js 13+ con App Router introdujo una nueva forma de manejar scripts. Este es el enfoque recomendado para la integración de consentimiento:

Paso 1: Cargar el script del CMP en el layout raíz

Usa el componente Script de Next.js con la estrategia beforeInteractive en tu layout.tsx raíz. Esto le indica a Next.js que inyecte el script en el documento HTML inicial, antes de que comience la hidratación:

La estrategia beforeInteractive es crítica. La estrategia predeterminada afterInteractive carga los scripts después de la hidratación, lo cual es demasiado tarde para el consentimiento. Con beforeInteractive, el script del CMP se incluye en el HTML renderizado en servidor y se ejecuta mientras la página se carga.

Paso 2: Establecer el consentimiento predeterminado antes de las etiquetas de Google

Antes de tu snippet de Google Tag Manager o gtag.js, incluye un script inline que establezca los estados de consentimiento predeterminados. Esto garantiza que, incluso si GTM se carga antes de que aparezca el banner del CMP, respete los valores denegados por defecto:

Este script inline debe colocarse en el <head> de tu layout raíz, antes de los scripts del CMP y de GTM. En Next.js, puedes usar una etiqueta <script> normal dentro del elemento <head> de tu layout para este propósito.

Paso 3: Manejar los cambios de ruta

En la navegación de una single-page application, el script del CMP se carga una vez, pero los cambios de ruta no desencadenan una recarga completa de la página. Tu CMP debe persistir a través de las navegaciones del lado del cliente. FlexyConsent maneja esto automáticamente: una vez cargado, permanece activo en todos los cambios de ruta sin necesidad de reinicialización.

Integración con Next.js Pages Router

Para proyectos que aún usan Pages Router, el enfoque es similar pero utiliza _document.tsx en lugar del layout raíz. Coloca el script del CMP en el componente <Head> de tu clase Document personalizada. La estrategia beforeInteractive funciona de la misma forma en Pages Router.

La diferencia clave es que _document.tsx solo se renderiza en el servidor, por lo que cualquier lógica de consentimiento aquí está garantizada en el payload HTML inicial.

Integración de sitios estáticos con Gatsby

Gatsby genera HTML completamente estático en tiempo de compilación. No hay renderizado en servidor en tiempo de petición, lo que simplifica algunos aspectos pero complica otros:

El enfoque de compilación de Gatsby implica que cada archivo HTML en tu CDN incluirá el script de consentimiento. Esto es en realidad ideal: no hay lógica de servidor que pueda fallar o almacenarse en caché de forma incorrecta.

Consideraciones para Nuxt.js

Nuxt.js (basado en Vue) tiene sus propios patrones. En Nuxt 3, usa el composable useHead o la configuración de app head en nuxt.config.ts para añadir el script del CMP globalmente. Nuxt admite la opción body: false (que coloca los scripts en el head) y el atributo async para una carga no bloqueante.

Para el modo de renderizado en servidor de Nuxt, se aplica el mismo principio: el script del CMP debe estar en la respuesta HTML inicial, no inyectado dinámicamente por un componente de Vue después del montaje.

Cómo evitar el cambio de diseño

Los banners de consentimiento son famosos por causar Cumulative Layout Shift (CLS), una métrica de Core Web Vitals que afecta al posicionamiento SEO. Cuando un banner aparece después de que la página se ha renderizado, empuja el contenido hacia abajo o lo superpone de forma inesperada.

Estrategias para minimizar el CLS provocado por banners de consentimiento:

El enfoque agnóstico a frameworks de FlexyConsent

FlexyConsent se diseñó para funcionar con cualquier framework —o sin framework— operando a nivel de script en lugar de a nivel de componente. Esto es importante por varias razones:

Consejo para desarrolladores: La prueba más simple para verificar una integración correcta del CMP es abrir la pestaña Network del navegador, filtrar por dominios de Google y recargar la página. No deberían dispararse peticiones a Google antes de que aparezca el comando de consentimiento por defecto en la consola. Si lo hacen, tu CMP está cargando demasiado tarde.

El plan gratuito de FlexyConsent admite páginas vistas ilimitadas y funciona con Next.js, Gatsby, Nuxt, Astro, SvelteKit, Remix y HTML plano. La integración es la misma en todos ellos: una etiqueta de script, correctamente colocada.

← Blog Leer todo →