A veces el problema no es que una herramienta no haga lo que quieres. A veces el problema es que lo hace… pero en silencio. Así me encontré yo al intentar medir los tests que coloco al final de mis artículos, como una forma de saber si quien los lee realmente se queda con algo. Porque una cosa es que una página reciba visitas, y otra muy distinta es que enseñe.
Para esos tests estoy usando un plugin bastante apañado. Tiene sus limitaciones, sí, pero también una interfaz limpia y un flujo cómodo para el lector. Lo que no tiene (y esto es lo que nos interesa) es ningún tipo de integración automática con Google Tag Manager. Ni eventos nativos, ni variables de capa de datos, ni siquiera un triste atributo con algo útil. Nada. Como si todo lo que ocurre durante el test sucediese en una dimensión paralela, inaccesible desde fuera. Así que tuve que ingeniármelas para poder medir las interacciones y dejar de depender de los informes bastante limitados de la versión gratuita del propio plugin.
¡Atención!
Este artículo es más avanzado que el resto que hemos tratado en Detrás de los datos. Trataré de hacerlo lo más ameno posible, pero es bastante más técnico que el resto.
El problema
El plugin que usé para los tests (AYS Quiz Maker) no lanza eventos automáticos. No hay dataLayer.push
, ni customEvent
, ni siquiera una mínima clase de estado que puedas detectar fácilmente. Todo pasa «silenciosamente».
Lo interesante es que al final no hizo falta tocar el plugin ni instalar cosas raras. Todo se resolvió desde Google Tag Manager con un poco de cuidado y un script que detecta el test automáticamente y lanza los eventos necesarios.
El reto fue doble. Por un lado, el plugin no utiliza eventos de ningún tipo, así que no puedes engancharte a ningún onClick
predecible. Por otro, la forma en que muestra el resultado de cada pregunta no es cuando le das a «Siguiente», sino cuando haces clic directamente en la opción. Es decir, no hay un único punto de control. Tienes que leer el DOM en el momento exacto en el que se actualiza, y no antes. Y, claro, todo esto sin usar let
, const
ni funciones flecha porque el entorno de GTM solo admite JavaScript ES5 (no sé lo que son, pero me dieron bastantes dolores de cabeza a la hora de generar el código).
La solución
La solución pasó por crear un pequeño script en GTM (con bastante ayuda de o3 y GPT 4.5) que escuchara todo lo que el plugin no dice. Un «listener» para capturar el título del test, la puntuación, el texto de la pregunta, la respuesta elegida y si era correcta o no. Gracias a este fragmento de código, todo esto lo enviamos al dataLayer
, y de ahí directo a Google Analytics.
Consejo
Si tienes acceso a ChatGPT Plus, el modelo 4.5 a día de hoy puede ser más resolutivo a nivel de código que los propios modelos razonadores. Utiliza bien tus mensajes ya que solo permite 50 a la semana.
Después de cerca de una hora iterando, este es el código final:
<script>
(function() {
function initQuizListener(quizContainer) {
var hasFiredFinish = false;
var quizTitle = 'unknown';
// Try to get quiz title
var titleEl = quizContainer.querySelector('.ays-fs-title');
if (titleEl) {
quizTitle = titleEl.innerText.replace(/\s+/g, ' ').trim();
}
quizContainer.addEventListener('click', function(e) {
var el = e.target;
// Answer clicked
if (el.tagName === 'LABEL' && el.htmlFor) {
setTimeout(function() {
var inputEl = document.getElementById(el.htmlFor);
if (!inputEl) return;
var field = inputEl.closest('.ays-field');
var step = quizContainer.querySelector('.step.active-step');
var questionEl = step.querySelector('.ays_quiz_question p');
var questionText = questionEl ? questionEl.innerText.replace(/\s+/g, ' ').trim() : 'unknown';
var answerText = el.innerText.trim();
var result = 'none';
if (field.classList.contains('correct_div')) result = 'correct';
if (field.classList.contains('wrong_div')) result = 'wrong';
dataLayer.push({
event: 'quizAnswer',
quizTitle: quizTitle,
question: questionText,
answer: answerText,
result: result
});
}, 150);
}
// Start quiz
if (el.classList.contains('start_button')) {
dataLayer.push({
event: 'quizStart',
quizTitle: quizTitle
});
}
// Previous
if (el.classList.contains('ays_previous')) {
dataLayer.push({
event: 'quizPrevious',
quizTitle: quizTitle
});
}
// Finish button
if (el.name === 'ays_finish_quiz' || el.classList.contains('ays_finish')) {
var tryCount = 0;
var maxTries = 20;
var pollForScore = setInterval(function() {
var scoreEl = quizContainer.querySelector('.ays_score_percent');
if (scoreEl) {
var scoreText = scoreEl.innerText.trim();
if (scoreText && !hasFiredFinish) {
hasFiredFinish = true;
clearInterval(pollForScore);
dataLayer.push({
event: 'quizFinish',
quizTitle: quizTitle,
finalScore: scoreText
});
}
}
tryCount++;
if (tryCount > maxTries) {
clearInterval(pollForScore);
}
}, 300);
}
});
}
// Init on any quiz container
var checkInterval = setInterval(function() {
var quizContainers = document.querySelectorAll('[id^="ays-quiz-container-"]');
if (quizContainers.length > 0) {
clearInterval(checkInterval);
for (var i = 0; i < quizContainers.length; i++) {
initQuizListener(quizContainers[i]);
}
}
}, 500);
})();
</script>
Este pequeño script permite hacer todo esto:
- Detectar cuando un usuario inicia un test.
- Recuperar el texto de la pregunta.
- Recuperar la respuesta escogida y si es correcta o incorrecta.
- Detectar el final del test y extraer la puntuación final.
Y por último y más importante: enviar todo esto al dataLayer
.


Variables necesarias en GTM
Para que todo esto funcione, es necesario configurar estas variables personalizadas en GTM:
Variable | Tipo | Valor de la Capa | Detalles |
---|---|---|---|
DLV | question_text | Variable de capa de datos | question | Texto de la pregunta |
DLV | answer_text | Variable de capa de datos | answer | Texto de la respuesta elegida |
DLV | question_result | Variable de capa de datos | result | “correct” o “wrong” |
DLV | quiz_name | Variable de capa de datos | quizTitle | Nombre del test |
DLV | quiz_score | Variable de capa de datos | finalScore | Puntuación final (“70%”) |



Contenedor descargable
Como sé que es posible que alguien que se enfrentaba al mismo problema que yo acabe en este artículo de forma orgánica a través de Google, he decidido dejar el contenedor de Google Tag Manager listo para subir a la plataforma como descargable.
Este archivo JSON
contiene todo lo necesario para medir los tests y enviarlos a GA4, tan solo es necesario cambiar la ID de Google Analytics. A cambio, solo te pediré tu nombre y tu correo.
Newsletter mensual - Contenedor GTM Ays Quiz Listener
¡Una vez cubierto se desplegará un popup con el enlace de descarga! (También te llegará por correo)
Conclusión
Medir la eficacia de un contenido va más allá de conocer su alcance. Incorporar tests al final de los artículos es una forma directa de evaluar comprensión, de saber si los conceptos han calado y si el lector ha podido seguir el hilo hasta el final. Implementar su medición con Google Tag Manager ha supuesto integrar esa información en los flujos habituales de análisis, sin depender de soluciones externas ni adaptar el contenido a limitaciones técnicas.
Este tipo de datos, centrados en el aprendizaje, permiten observar patrones que de otro modo pasarían desapercibidos. Saber qué preguntas generan más errores o qué temas resultan más claros ofrece una base objetiva para seguir mejorando. Es, en definitiva, una forma de cerrar el proceso de creación de contenido con una mirada crítica y útil. Porque no se trata solo de escribir y publicar, sino también de entender qué se transmite realmente.
Y como no podría ser de otra forma, aquí está el test: