Como lidamos com capturas de tela quebradas nos heatmaps do Matomo

As capturas de tela dos heatmaps quebram na maioria dos sites modernos por causa de como o Matomo serializa e re-renderiza o DOM. Esses são os padrões que encontramos repetidamente, e uma pequena extensão open source que criamos pra resolver.

Se você já abriu um heatmap do Matomo e encontrou um retângulo em branco onde deveria estar sua imagem hero, ou uma grade de produtos que corta depois da primeira linha, ou um header fixo sentado bem em cima do conteúdo da página, você não é o primeiro. As capturas de tela dos heatmaps quebram na maioria dos sites modernos por padrão. O motivo é estrutural — não é algo que se resolve ajustando a configuração de rastreamento.

O script de rastreamento do Matomo serializa o DOM da sua página em HTML e envia pro seu servidor Matomo. O servidor então re-renderiza esse HTML num contexto completamente diferente pra gerar a captura que você vê. Sem cookies. Sem sessão. Origem diferente. Nada do ambiente que seu framework JavaScript configurou. Um monte de coisas que funcionavam porque estavam rodando num navegador real param silenciosamente quando o mesmo HTML é re-renderizado a frio em outro lugar.

Quando você entende isso, a lista de bugs começa a fazer sentido.

Os padrões que encontramos repetidamente

A maioria dos sites tem pelo menos três desses. Alguns têm todos os seis.

  • CORS bloqueia suas imagens e fontes hospedadas no CDN, porque o servidor do Matomo não tem credenciais pro seu domínio. As imagens viram ícones quebrados. As fontes caem para as do sistema.
  • Containers com scroll (overflow: hidden ou overflow: auto com altura fixa) cortam tudo que está abaixo da área visível. O Matomo serializa o DOM no estado atual, então o que não estava na tela no momento da captura não aparece no snapshot.
  • Headers sticky e fixed colapsam sobre o conteúdo por baixo. Suas posições são calculadas em relação ao viewport, e no servidor não existe viewport — então eles caem pro lugar onde estão no DOM.
  • URLs relativas como /images/hero.jpg resolvem pro servidor do Matomo em vez do seu. O arquivo não existe lá, então simplesmente falha sem barulho.
  • Fontes customizadas carregadas via @font-face caem pras fontes do sistema quando os arquivos de fonte são protegidos por CORS ou bloqueiam o user-agent do servidor do Matomo.
  • Single page applications são capturadas antes de o React ou o Vue terminarem de renderizar, deixando metade da página faltando no snapshot.

A maioria desses problemas tem correções no nível de infraestrutura. Adicione cabeçalhos CORS no seu CDN. Troque pra URLs absolutas. Use o hook CSS matomoHeatmap pra sobrescrever o posicionamento sticky durante a captura. A própria documentação do Matomo cobre vários deles, e escrevemos um post mais detalhado que passa por cada problema e como corrigir no servidor se for esse o caminho que você quer.

O problema é que o trabalho se espalha por configuração de CDN, CSS e sua configuração de rastreamento, e parte dele é impossível de corrigir se você não controla os assets. Chegamos nessa parede em clientes suficientes pra acabarmos fazendo outra coisa.

O que acabamos construindo

Começamos com um script pequeno que colávamos no DevTools antes de cada captura. Ele embutia imagens e fontes como data URIs, expandia containers com scroll, desfazia o sticky dos headers, reescrevia URLs relativas pra absolutas. Com o tempo foi crescendo e virou uma extensão do Chrome que usávamos internamente em todos os clientes.

É isso que é o Matomo Heatmap Helper. Abrimos o código.

A configuração é uma tela só. Você coloca sua URL do Matomo, um token de API, e escolhe em quais sites a barra de ferramentas deve aparecer. Em qualquer página correspondente, uma barra pequena aparece.

O trabalho acontece na hora da captura. Quando você aperta o botão de screenshot, a extensão faz as coisas que seriam demoradas de fazer de forma estática. Ela embute imagens e fontes como data URIs em base64 pra o servidor do Matomo nunca precisar buscar nada cross-origin. Ela expande containers com scroll até a altura total do conteúdo. Converte headers sticky e fixed pro fluxo normal. Reescreve URLs relativas pra absolutas, redimensiona iframes, pausa vídeos no frame zero, e dá tempo pro conteúdo de SPAs renderizar. Depois chama a API de screenshot do Matomo, aguarda o resultado, e reverte cada alteração. Sua página ao vivo volta como estava.

O motivo disso funcionar é que você consegue interagir com os elementos antes da captura. Containers com scroll customizados, um header sticky com problema, uma seção onde os assets não estão carregando: você clica neles no modo Interactive, eles recebem um ícone de cadeado, e o pipeline sabe o que fazer com eles. O script de rastreamento sozinho não consegue fazer isso, porque ele captura qualquer estado em que o DOM estava no momento em que rodou. Deixar uma pessoa indicar pra extensão quais elementos precisam de tratamento é o que resolve os casos que o script nunca conseguiria.

A extensão só se comunica com a sua instância do Matomo. Seu token de API fica no chrome.storage.local, que é isolado das páginas que você visita. Sem telemetria, sem rastreamento de uso. O código está no GitHub. Issues e pull requests são bem-vindos.

Por que disponibilizamos

Como agência Parceira Oficial do Matomo, heatmaps quebrados eram um problema que encontrávamos em quase todo projeto de cliente. Os eventos eram rastreados corretamente, mas as capturas eram inutilizáveis — que é justamente a parte que a maioria dos stakeholders olha.

O Matomo nos deu muito como agência. Usamos a extensão diariamente no trabalho com clientes e continuamos corrigindo casos específicos que encontramos em sites. Se você encontrar algum problema não resolvido de heatmap, abra uma issue no GitHub e vemos se conseguimos adicionar uma correção na extensão.

No que estamos trabalhando

O Matomo Heatmap Helper surgiu de um projeto maior. O Martez conecta o Matomo com Meta Ads e Google Ads, pra que ROAS, CLV e atribuição multi-touch fiquem do lado do seu web analytics em vez de numa planilha separada. Está em beta privado. Se isso for relevante pra você, pode entrar na lista de espera.

De qualquer forma, a extensão de heatmap é uma coisa à parte, e continua assim. Criamos porque precisávamos.

Como lidamos com capturas de tela quebradas nos heatmaps do Matomo - Martez Blog