Una función compartida en el layout raíz del sitio convirtió un contador de exposición de pruebas A/B en un contador de vistas de página, inflando el tamaño de la muestra y haciendo que las tasas de conversión carecieran de sentido. La prueba, una división 50/50 de la página de inicio, reportó 178 hits para una variante y 57 para la otra, lejos de la división equitativa esperada.
Cómo el error pasó desapercibido para el aleatorizador
El desarrollador primero verificó el aleatorizador que asigna a los visitantes a una variante. Leyó el middleware, inspeccionó la lógica de las cookies y ejecutó un script que llamó a la función de asignación 10,000 veces; este produjo una división perfecta de 50/50. El aleatorizador en sí funcionaba; el problema era cómo se registraba la exposición.
Una sola función realizaba dos tareas:
- Establecer la variante – se ejecuta en cada carga de página para mantener la consistencia en la experiencia del visitante.
- Registrar el evento de exposición – debería dispararse solo una vez por visitante, en el momento en que la variante aparece por primera vez.
La función residía en el layout raíz, un componente que se renderiza en cada navegación. Debido a que el código de registro de exposición se ejecutaba cada vez que se renderizaba el layout, cada vista de página contaba como una nueva exposición. Las dos variantes de la página de inicio utilizaban árboles de layout ligeramente diferentes, por lo que sus tasas de vistas de página divergieron, creando la ilusión de un aleatorizador defectuoso.
Por qué importó el error de conteo
Los números de conversión (clics, registros, compras) se registraron correctamente. Pero el denominador (el número de exposiciones) era incorrecto. Las tasas de conversión calculadas parecían mucho más bajas que la realidad, y cualquier decisión basada en esas tasas no era confiable.
La prueba se ejecutó durante dos semanas antes de que la discrepancia saliera a la luz, lo que obligó al equipo a descartar todo el conjunto de datos.
La solución
La solución fue sencilla: dividir las responsabilidades en funciones separadas. El código de registro de exposición ahora verifica si el visitante ya ha sido contabilizado, disparándose solo una vez por usuario. El código de establecimiento de la variante permanece donde está, continuando su ejecución en cada navegación.
Tres lecciones para cualquiera que realice experimentos
- Separe el establecimiento de estado de los eventos únicos. Una función que tanto asigna una variante como registra una exposición entrará en conflicto porque la primera se repite mientras que la segunda no debe hacerlo.
- Evite la lógica de un solo paso en un layout raíz. Cualquier cosa colocada en un componente que se renderiza en cada carga de página se ejecutará repetidamente, convirtiendo el "una vez por visitante" en "una vez por vista de página".
- Cuando la división observada contradiga al aleatorizador, audite primero el contador. Los desarrolladores suelen probar la imparcialidad del aleatorizador, pero rara vez verifican que el mecanismo de conteo sea preciso.
Qué vigilar a continuación
Cualquier experimento que dependa de un único contador para la exposición debe ser auditado para determinar dónde reside ese contador en el árbol de componentes. Si el contador se encuentra en un layout global, añada una comprobación que vincule el evento a un identificador persistente, como una cookie o una bandera de local-storage. Los equipos también deberían incorporar una comprobación de coherencia en sus dashboards: si la distribución de variantes observada se desvía más allá de un pequeño margen estadístico, marque la prueba para una auditoría del contador antes de asumir que el aleatorizador está roto.
En resumen, un aleatorizador que funciona bien es inútil sin un recuento de exposición confiable. Dividir las responsabilidades y colocar los eventos únicos fuera de los componentes que se renderizan siempre mantiene la integridad de las pruebas A/B y ahorra semanas de análisis perdidos.
