Por que las capturas de pantalla de tus mapas de calor de Matomo salen rotas (y como arreglarlo)

Las capturas de los mapas de calor de Matomo fallan porque tu pagina se vuelve a renderizar en otro servidor, sin cookies, sin fuentes y sin acceso CORS. Te cuento que provoca cada fallo y como solucionarlo.

La captura de pantalla de Matomo funciona en dos pasos, y justo en el hueco entre uno y otro es donde se rompe todo.

Primero, cuando alguien visita tu pagina, el JavaScript de seguimiento de Matomo serializa el DOM en una cadena HTML (usando una biblioteca que se llama TreeMirror) y la manda a tu servidor de Matomo. Despues, el servidor renderiza ese HTML para generar la imagen de fondo que aparece en la vista del mapa de calor.

El problema de fondo es que tu pagina se esta re-renderizando en un contexto totalmente distinto. El servidor de Matomo no tiene cookies, no tiene sesiones, viene de otro origen y no tiene ni idea de lo que hicieron tus frameworks de JavaScript con la pagina despues de cargarla. Todo lo que funcionaba porque corria en un navegador real con las credenciales de tu dominio puede romperse cuando ese mismo HTML se renderiza en frio en otro servidor.

Cuando entiendes esto, la mayoria de fallos en las capturas de los mapas de calor empiezan a tener sentido.

Como se ven las capturas rotas

Estos son los problemas tipicos que te vas a encontrar:

  • La imagen hero carga bien en el navegador, pero en el mapa de calor sale como un icono roto
  • Una cuadricula de productos con scroll solo muestra la primera fila; el resto queda cortado
  • La navegacion fija se monta encima del contenido de la pagina en la captura
  • Las fuentes de tu marca se reemplazan por fuentes genericas del sistema
  • Recursos con rutas relativas tipo /assets/banner.webp directamente no cargan
  • Paginas SPA que se capturan a mitad de renderizado con la mitad del contenido sin aparecer

Todos estos problemas tienen causas tecnicas concretas. Vamos a verlos.

CORS bloqueando tus imagenes y fuentes

Este es el problema mas habitual. Tu imagen hero, fotos de productos o imagenes de fondo aparecen como cajas vacias o iconos rotos en la captura del mapa de calor.

Pasa porque tus imagenes cargan sin problema en el navegador, que tiene tus cookies y el contexto de sesion. Pero cuando el servidor de Matomo intenta cargar https://cdn.yoursite.com/hero.jpg, el CDN ve un origen que no reconoce y rechaza la peticion. CORS de toda la vida.

La solucion en el servidor es sencilla: mete Access-Control-Allow-Origin: * en las cabeceras de respuesta de tu CDN. La documentacion de Matomo lo explica en su guia de configuracion de mapas de calor.

Si no tienes control sobre el CDN o no quieres tocar la configuracion del servidor, la alternativa es incrustar los recursos directamente en el DOM como URIs de datos en base64 antes de que Matomo haga la captura. Asi, el HTML serializado lleva cada imagen en linea y el servidor no necesita pedir nada. Esto aplica a src, srcset, imagenes de fondo en CSS, referencias SVG e imagenes de poster de video.

Contenedores con scroll que cortan tu contenido

Tienes una seccion con una altura fija y barra de desplazamiento. En la captura del mapa de calor, solo se renderiza la parte visible. Todo lo de abajo desaparece.

Los elementos con overflow: hidden o overflow: auto recortan el contenido a su altura renderizada. Matomo serializa el DOM tal como esta visualmente en ese momento, asi que el HTML capturado refleja el clientHeight, no el scrollHeight completo.

Para arreglarlo, no uses alturas fijas en contenedores de contenido. Usa min-height en vez de height, y no pongas overflow: hidden en elementos que tengan contenido desplazable.

Encabezados fijos y sticky que tapan la pagina

Tu navegacion sticky va perfecta en el navegador, pero en la captura se planta encima del contenido y tapa lo que hay debajo.

Los elementos con position: fixed y position: sticky se posicionan respecto al viewport. En el servidor no hay viewport, asi que colapsan sobre el contenido que tienen debajo.

Matomo anade una clase matomoHeatmap al elemento <html> cuando hace el renderizado de la captura en el servidor. Puedes aprovechar esto para escribir reglas CSS que solo apliquen durante la captura:

css
html.matomoHeatmap .your-sticky-header {
  position: relative;
  top: auto;
}

Esto pasa tu encabezado sticky a flujo normal en la captura sin cambiar como se ve la pagina para los usuarios reales. La documentacion de Matomo lo trata en su FAQ sobre corregir encabezados superpuestos en mapas de calor y aplicar hojas de estilo personalizadas durante la captura.

Si prefieres no mantener esas reglas CSS extra, el planteamiento general es detectar los elementos de encabezado y navegacion con posicionamiento fixed o sticky, pasarlos a position: relative, limpiar sus valores de top/bottom/left/right y, en el caso de los fixed, meter un div de relleno para que el layout no se desplace. Despues de la captura, todo se restaura.

URLs relativas que dejan de funcionar

Algunas imagenes y hojas de estilo cargan bien en tu sitio pero faltan en la captura de Matomo, aunque no sean de origen cruzado. Esto descoloca hasta que te das cuenta de lo que pasa.

Tu pagina usa URLs relativas tipo /images/banner.jpg. En el navegador, eso se resuelve contra tu dominio. En el contexto de renderizado de Matomo, /images/banner.jpg se resuelve contra el servidor de Matomo. El archivo no existe alli.

Se arregla usando URLs absolutas en todas partes, o metiendo una etiqueta <base href="https://yoursite.com/"> en tu <head>. Si ninguna de las dos te vale, un script de pre-captura puede recorrer el documento buscando URLs relativas en atributos src, href, srcset y background-image de CSS, y reescribirlas como absolutas usando el origen actual de la pagina.

Fuentes personalizadas que aparecen como fuentes del sistema

Tus fuentes de marca han desaparecido. La captura muestra la fuente del sistema que tenga el servidor, que suele ser bastante fea.

Las reglas @font-face referencian archivos de fuentes alojados en CDNs o en tu servidor. Cuando el servidor de Matomo intenta cargar esos archivos, CORS lo bloquea o el CDN exige un user agent de navegador. El servidor termina usando una fuente por defecto.

La solucion: aloja las fuentes en un servidor con cabeceras CORS permisivas. Google Fonts ya lo hace, pero muchas fuentes auto-alojadas no. Si cambiar las cabeceras no es opcion, puedes incrustar las fuentes directamente en la pagina: descarga los archivos de fuentes, conviertelos a URIs de datos en base64 e inyecta reglas @font-face con esos URIs de datos en etiquetas <style> dentro del <head>. Asi el HTML serializado lleva sus propias definiciones de fuentes y se renderiza bien se sirva donde se sirva.

Iframes, videos y SPAs

Unos cuantos casos especiales mas que merece la pena conocer.

Los iframes muchas veces tienen dimensiones CSS fijas que no coinciden con su contenido real. Si el iframe es del mismo origen, puedes leer la altura real del contenido con contentDocument.body.scrollHeight y redimensionar. Si es de origen cruzado, vas a necesitar una altura de respaldo generosa.

Los videos con autoplay se capturan a mitad de reproduccion y muestran un fotograma cualquiera. Pausalos y lleva la posicion al fotograma 0 antes de capturar para que la imagen muestre el primer fotograma.

Las aplicaciones de pagina unica (SPA) son lo mas complicado. Las apps de React, Vue y Angular cargan contenido de forma dinamica, y Matomo puede capturar el DOM antes de que tu framework acabe de renderizar. La URL puede no coincidir con lo que muestra tu enrutador. No hay una solucion universal. Lo mejor que puedes hacer es configurar las reglas de coincidencia de URL de Matomo para tus rutas SPA y usar la API JavaScript de Matomo para lanzar la grabacion cuando el renderizado haya terminado.

Arreglarlo todo de golpe con Matomo Heatmap Helper

La mayoria de sitios reales tienen varios de estos problemas a la vez. Arreglarlos todos a mano significa tocar configuraciones de CDN, reescribir URLs, refactorizar CSS y escribir scripts de captura a medida.

Matomo Heatmap Helper es una extension gratuita y de codigo abierto para Chrome y Firefox que se encarga de todo lo anterior. Codigo fuente en GitHub.

Te cuento como funciona. Instalas la extension, metes tu URL de Matomo y token de API, y eliges en que sitios activarla. En las paginas que coincidan aparece una barra de herramientas. Haz clic en "Interactive" y despues en los elementos que necesitan arreglo: contenedores con scroll, encabezados sticky, secciones con imagenes que no cargan. Les aparece un icono de candado para indicar que se van a procesar.

Cuando le das al boton de captura, la extension ejecuta una secuencia. Primero descarga e incrusta imagenes y fuentes de origen cruzado, luego expande los elementos restringidos y quita los encabezados sticky, maneja iframes y videos, convierte URLs relativas a absolutas y lanza la API de captura de Matomo. Despues de la captura, revierte todos los cambios. Tu pagina vuelve a estar como estaba.

Antes de hacer la captura

Lista rapida de comprobaciones:

  1. Asegurate de que la pagina se ha renderizado del todo, sobre todo contenido SPA y secciones con carga diferida
  2. Bloquea los contenedores que cortan contenido o necesitan expandirse
  3. Mira si hay encabezados sticky o fixed que puedan tapar contenido
  4. Comprueba que tus imagenes y fuentes principales se ven bien
  5. Haz la captura y confirma que la verificacion es correcta
  6. Abre la vista del mapa de calor y revisa el resultado antes de ponerte a analizar

Dos opciones

Estos problemas con las capturas de pantalla no son bugs de tu sitio. Son efectos secundarios de que Matomo serializa tu pagina y la vuelve a renderizar en otro sitio. Cualquier web que use CDNs, fuentes web, contenedores con scroll o encabezados sticky se va a topar con alguna combinacion de ellos.

Puedes arreglar cada problema a nivel de infraestructura: anadir cabeceras CORS, usar URLs absolutas, refactorizar contenedores con overflow, cambiar el posicionamiento sticky durante la captura. Es lo correcto a largo plazo si controlas el servidor, pero lleva tiempo y algunos problemas no tienen soluciones limpias del lado del servidor.

O puedes arreglarlos en el momento de la captura con Matomo Heatmap Helper. Usa el modo interactivo para indicarle que partes de tu pagina necesitan ayuda y saca capturas limpias sin tocar el codigo de produccion.