Caso real 05 · Analítica · GA4 + GTM

Saber quién lee de verdad: engagement del blog medido de punta a punta

Qué artículos se leen hasta el final, dónde se abandonan y qué componentes se usan. Lo construí completo: plugin, dataLayer, Tag Manager, GA4 y dashboard. Y encontré dos fallos que no estaban en el código.

Caso real, cliente anonimizado. El nombre del cliente, las personas y los datos internos se omiten por confidencialidad. Las cifras salen de logs, Search Console, GA4 y del propio código. Si un dato de negocio no se midió, no aparece.
5eventos de lectura nuevos
11variables de dataLayer
9dimensiones y métricas propias
5 de 5eventos atribuidos por artículo
Contexto

El punto de partida.

El blog medía vistas y algunos clics sueltos. No había forma de saber si un artículo se leía o se abandonaba en el primer párrafo, ni de segmentar por categoría o idioma.

Complicación técnica: la plantilla de artículo estaba montada con un page builder, sin contenedor semántico del cuerpo. Medir el scroll de toda la página habría mezclado header, barra lateral y footer.

Síntomas observados

  • El scroll de GA4 solo registra el 90 % de la página completa.
  • Sin dimensiones de categoría, idioma ni longitud del artículo.
  • Imposible calcular una tasa de finalización por artículo.
Diagnóstico

Hipótesis descartadas antes de tocar nada.

Lo que parecía obvio y no era. Descartar bien ahorra días de trabajo en la dirección equivocada.

Scroll nativo de GA4

Mide la página, no el artículo, y solo a un umbral.

Tocar las plantillas del page builder

Añadía riesgo en cada rediseño. Mejor detectar el cuerpo desde el DOM.

Herramienta externa de mapas de calor

Útil, pero no alimenta GA4 ni permite cruzar con conversión.

Implementación

Qué hice, paso a paso.

Detectar el cuerpo real

Un mu-plugin localiza el rango de bloques de texto del artículo y excluye header, footer, índice, compartir, relacionados y categorías.

Eventos con contexto

article_view, reading_depth (25/50/75/100), article_complete, reading_session_end y category_click, todos con categoría, idioma, ID, título y número de palabras.

Tag Manager y GA4

11 variables de dataLayer, 5 activadores de evento y 5 etiquetas de GA4, más 7 dimensiones y 2 métricas personalizadas.

Fallo 1: nada llegaba

El plugin empujaba al dataLayer, pero el workspace de GTM llevaba 8 días sin publicar. Además, una propiedad antigua de GA4 que se creía pausada seguía recibiendo eventos.

Fallo 2: atribución incompleta

El desglose por artículo solo funcionaba para un evento. El plugin enviaba el título en todos; faltaba el parámetro en 4 etiquetas de GTM.

Dashboard

Looker Studio con embudo de abandono, finalización por artículo y uso de componentes, filtrable por categoría e idioma.

Bajo el capó

El código que importa.

Fragmentos simplificados y sin datos del cliente, para que se vea el enfoque técnico real.

Evento que envía el pluginjavascript
window.dataLayer.push({
  event: 'reading_depth',
  percent: 75,
  max_percent: 75,
  post_id: 18234,
  post_title: 'How to …',
  post_category: 'Guides',
  content_language: 'en',
  word_count: 1840,
  reading_time_min: 8
});
Umbrales medidos sobre el cuerpo, no sobre la páginajavascript
const start = body.getBoundingClientRect().top + scrollY;
const end   = start + body.offsetHeight - innerHeight;
const pct   = Math.min(100, Math.max(0, (scrollY - start) / (end - start) * 100));
[25, 50, 75, 100].forEach(t => { if (pct >= t && !sent.has(t)) { sent.add(t); push(t); } });
Decisiones

Por qué así y no de otra forma.

Parámetros en todos los eventos

Cada evento lleva el contexto completo del artículo. Así cualquier informe se puede cortar por post sin cruces.

Arreglar en GTM, no en el plugin

El dato ya salía bien del sitio; el fallo estaba aguas abajo.

Resultado

Qué cambió, con datos verificables.

IndicadorAntesDespuésContexto
Eventos de lectura15profundidad, finalización, sesión, categorías
Definiciones propias en GA4097 dimensiones + 2 métricas
Eventos atribuidos por artículo1 de 55 de 5parámetro añadido en GTM
Propiedad antigua activaSin detectarIdentificadalimpieza aparte

Cómo lo validé

  • DebugView de GA4 con los 5 eventos y sus parámetros.
  • Red del navegador filtrada por el ID de medición correcto.
  • Contraste de totales entre el pivot por artículo y el total del evento.
Lo que me llevo

Cuando «no llegan los datos», recorro la cadena entera en orden: dataLayer, contenedor publicado, parámetros de cada etiqueta y definiciones en GA4.

  • WordPress
  • JavaScript
  • Google Tag Manager
  • GA4
  • Looker Studio
Para tu web

Checklist rápida: ¿te está pasando lo mismo?

  • ¿Tu workspace de GTM está publicado?
  • ¿Hay propiedades antiguas recibiendo datos?
  • ¿Tus dimensiones personalizadas existen antes de lanzar la medición?
  • ¿Cada evento lleva el contexto completo?
¿Te suena?

¿Tienes un problema parecido?

Preguntas frecuentes

Dudas habituales sobre este tipo de problema.

¿GA4 no mide ya el scroll?

Solo al 90 % de la página completa. No distingue el artículo del resto ni mide finalización.

¿Las dimensiones personalizadas son retroactivas?

No. Acumulan desde que se registran.

¿Hace falta tocar el tema?

No en este caso: el cuerpo del artículo se detecta desde el DOM.

WordPress · SEO técnico · IA

Cuéntame qué está frenando tu web.

Si ya tienes un WordPress en producción, reviso el contexto y te digo con honestidad si lo que necesitas es desarrollo, SEO técnico, rendimiento o automatización.