Voltar ao blog

Seu Script de Analytics Provavelmente Está Desativando o Cache de Avançar/Voltar

O cache de avançar/voltar deixa a navegação pelo botão de voltar quase instantânea, mas um único listener de unload o desativa para a página inteira. Os scripts de tracking são os suspeitos de sempre — e o CrUX agora mede o estrago.

A navegação mais rápida da web é aquela em que nada é carregado. O back/forward cache (bfcache) entrega exatamente isso — e uma única linha no script do seu fornecedor de analytics pode desligá-lo para todas as páginas do seu site.

O bfcache é uma otimização do navegador que mantém um snapshot completo da página em memória — incluindo o heap do JavaScript — quando o usuário sai dela. Pressione o botão de voltar e o navegador restaura esse snapshot e retoma a execução, produzindo um carregamento quase instantâneo, sem nenhuma requisição de rede. Estima-se que as navegações de voltar e avançar correspondam a 10–20% de todas as navegações, então isso não é um caso de borda.

Um Listener Desqualifica a Página Inteira

A elegibilidade ao bfcache é frágil por design. O navegador não congela uma página que registrou um listener do evento unload, porque unload implica que a página espera ser destruída. No desktop, Chrome e Firefox tornam inelegível ao bfcache qualquer página com um listener de unload — sem exceções, sem crédito parcial.

O listener não precisa ser seu. Scripts de terceiros que registram unload de dentro da sua página, ou até de dentro de um subframe, desqualificam o documento de nível superior. O Lighthouse traz uma auditoria dedicada, a no-unload-listeners, justamente porque o código problemático costuma ser código que o autor do site nunca escreveu.

O beforeunload não desqualifica mais nos navegadores modernos, mas é pouco confiável e ainda é melhor evitá-lo, a não ser que o usuário tenha alterações não salvas.

Scripts de Tracking São o Infrator Habitual

O evento unload é o lugar clássico para disparar um último beacon — descarregar uma sessão, enviar um evento de "página fechada" — então scripts de tracking de comportamento e de anúncios recorrem a ele o tempo todo.

O fbevents.js do Facebook registra um handler de unload e aparece em cerca de 9% de todas as páginas da web, segundo o HTTP Archive. A tag do PayPal injeta um iframe que adiciona um evento de unload, bloqueando o bfcache em muitos fluxos de checkout. Scripts em subframes, como o hCaptcha, já fizeram o mesmo. Nenhum deles exige uma mudança no seu próprio código para começar a te custar caro — basta um fornecedor publicar uma atualização.

O CrUX Agora Te Mostra a Conta

Antes, isso era invisível nos dados de campo. Desde o dataset de março de 2024, o Chrome User Experience Report (CrUX) reporta um detalhamento de navigation_types — incluindo a fração de visitas servidas a partir do back/forward cache — então dá para ver quantos usuários reais estão perdendo o caminho instantâneo.

A correlação é gritante. A análise do CrUX encontrou uma forte relação estatística (ρ=0.87) entre uma alta fração de back_forward_cache e o instant_lcp_density — a parcela de carregamentos com LCP abaixo de 200 ms. Depois que a atualização do Google de março de 2026 aumentou o peso de LCP, INP e CLS no ranqueamento, um bloqueio de bfcache autoinfligido é uma desvantagem mensurável no percentil 75, não um erro de arredondamento.

Detectando e Corrigindo

Abra o DevTools, vá em Application → Back/forward cache e clique em Run Test. O Chrome lista todos os motivos de bloqueio, incluindo handlers de unload adicionados por terceiros.

Para detectar restaurações do bfcache no seu próprio código, nunca use unload. Use pageshow e verifique persisted:

window.addEventListener('pageshow', (event) => {
  if (event.persisted) {
    // restored from bfcache — no fresh page load fired
  }
})

Para impedir que terceiros te desqualifiquem, defina um response header que proíbe listeners de unload por completo:

Permissions-Policy: unload=()

Isso neutraliza handlers de unload de qualquer script — tags de fornecedores, extensões ou seu próprio código legado — de modo que a página permanece elegível ao bfcache independentemente do que for carregado.

O Tracker Que Nunca Encosta Nisso

A correção estrutural é usar uma instrumentação que, para começar, não tem motivo nenhum para escutar unload. Um tracker que prioriza a privacidade registra um pageview com uma única requisição keepalive e deixa a requisição sobreviver à página por conta própria — sem beacon de encerramento, sem handler de unload, nada para o navegador sinalizar:

fetch('/collect', {
  method: 'POST',
  keepalive: true,
  body: JSON.stringify({ site_id, path: location.pathname })
})

Quando um tracker precisa reagir ao fato de a página ir para segundo plano, o sinal correto é visibilitychange ou pagehide, ambos disparados sem tornar a página inelegível ao bfcache. O tracker do Monoid tem cerca de 2 KB, não define nenhum cookie e engancha no history.pushState para as mudanças de rota de SPA em vez de no ciclo de vida da página — então ele não tem nenhum listener de unload para registrar e nada para desativar o seu back/forward cache.

O analytics de vigilância cobra um imposto de performance de maneiras que não aparecem em um teste de laboratório. Um bloqueio de bfcache é um dos mais silenciosos: nenhum erro, nenhuma renderização lenta, apenas um botão de voltar que recarrega da rede quando deveria ter restaurado da memória.

Fontes

Comments

Loading comments…