Session replay

Grabaciones, privacidad por defecto y reproductor.

La grabación de sesiones reconstruye lo que vio y hizo un visitante. Growth Lab usa rrweb y aplica valores de privacidad restrictivos por defecto.

Activar

En Sitios → Privacidad, activa Grabar sesiones y define la tasa de muestreo.

replay.js (≈57 KB gzip) se descarga solo si la grabación está activa y el visitante concedió permiso de replay. Un sitio que no graba nunca paga esos bytes.

Muestreo

La tasa de muestreo se decide por visitante, no por página: un visitante se graba durante toda su sesión o no se graba nada.

Muestrear por página produciría grabaciones con agujeros —el visitante aparece de pronto en el carrito sin que se vea cómo llegó—, que son peores que no tener grabación.

Privacidad por defecto

Sin configurar nada:

Elemento Comportamiento
Todos los <input> Enmascarados
input[type=password] Bloqueado siempre, incluso si desactivas el enmascarado
Campos de tarjeta (autocomplete="cc-*", name*=card) Bloqueados
/checkout, /checkouts, /account, /admin, /orders No se graban
Fuentes No se recopilan
Canvas No se graba

Control por marcado

<!-- Reemplaza el texto por asteriscos -->
<p data-growthlab-mask>Pedido #A-99120 de Ana Pérez</p>

<!-- Excluye el elemento entero de la grabación -->
<div data-growthlab-block>Datos de facturación</div>

<!-- Equivalentes por clase -->
<p class="gl-mask">...</p>
<div class="gl-block">...</div>

En Sitios → Privacidad puedes añadir selectores globales de enmascarado y bloqueo, y rutas que nunca se graben.

Barrido de PII en el servidor

Además del enmascarado de rrweb en el cliente, el colector aplica una pasada de redacción sobre el chunk serializado antes de guardarlo: correos, tarjetas con Luhn válido, teléfonos, IBAN y CURP.

Esta segunda capa existe porque el enmascarado del cliente puede fallar: un SDK desactualizado, un selector mal puesto, un campo inyectado dinámicamente. Es la única garantía que sobrevive a un error en el cliente.

Los patrones se aplican en orden de especificidad. Una tarjeta se etiqueta como tarjeta y no como teléfono, porque una redacción mal etiquetada lleva a conclusiones equivocadas en una auditoría.

Cómo se almacena

SDK ─→ session-collector ─→ bucket privado (gzip)
                        └─→ BullMQ ─→ worker-sessions ─→ metadatos

Los chunks van comprimidos al bucket privado. Nunca pasan por la cola: pesan cientos de kilobytes y saturarían Redis en minutos de tráfico real. La cola solo lleva metadatos.

El bucket es privado. El reproductor accede a los chunks mediante URLs firmadas de 5 minutos generadas en el servidor. Las credenciales del bucket nunca llegan al navegador.

Idempotencia

Los chunks se deduplican por (sesión, secuencia). El SDK reintenta con sendBeacon al ocultarse la página, así que el mismo chunk llega legítimamente dos veces; sin deduplicación se duplicarían fotogramas en el reproductor.

Los chunks pueden llegar fuera de orden —un beacon de la página anterior suele llegar después del primer chunk de la siguiente—, así que el worker fusiona en lugar de sobrescribir: las claves se unen, los tiempos toman mínimo y máximo, los contadores acumulan.

Reproductor

Filtros

Por conversión, por error, por rage click, por dead click, por variante, por dispositivo, por país, por URL y por duración.

Filtrar por variante es lo que hace útil el replay junto a un A/B: ver diez sesiones de la variante que perdió explica el por qué que la estadística no da.

Retención

Por defecto 30 días, configurable hasta 365. El servicio cron elimina los objetos del bucket antes de borrar la fila de metadatos, de modo que un fallo de almacenamiento deja un registro reintentable en lugar de un objeto huérfano.

Qué no se graba