TL;DR, Resposta rápida
9 min de leituraO bfcache (back/forward cache) guarda na memória uma cópia completa da página quando o visitante sai dela, então um clique em voltar ou avançar a restaura na hora, sem recarregar. Chrome, Firefox e Safari têm um. Como a página não carrega de novo, um script de analytics que só conta pageviews no carregamento perde a restauração. Escute o pageshow e verifique event.persisted para contar as restaurações, e evite listeners de unload, Cache-Control: no-store e conexões abertas, que deixam a página inelegível.
O que é o bfcache?
O bfcache, abreviação de back/forward cache, é uma otimização do navegador que guarda na memória uma cópia completa da página quando o visitante sai dela, para que um clique em voltar ou avançar restaure essa página na hora, em vez de carregá-la de novo. O web.dev o define como "a browser optimization that enables instant back and forward navigation," e descreve o mecanismo: "instead of destroying a page when the user navigates away, we postpone destruction and pause JS execution. If the user navigates back soon, we make the page visible again and unpause JS execution."
Todos os principais navegadores têm um: o Chrome desde a versão 96, o Firefox e o Safari. Cliques em voltar e avançar são uma parte grande da navegação. O web.dev relata que "Chrome usage data shows that 1 in 10 navigations on desktop and 1 in 5 on mobile are either back or forward."
Para o analytics, o que importa é o que não acontece em uma restauração. Nenhum HTML é pedido, nenhum script roda desde o início e nenhum evento load dispara. O seu rastreador acorda exatamente onde foi pausado.

Qual é a diferença entre o bfcache e o cache HTTP?
O bfcache guarda a página inteira em funcionamento, enquanto o cache HTTP guarda respostas individuais. O web.dev explica assim: "bfcache is a snapshot of the entire page in memory, including the JavaScript heap, whereas the HTTP cache contains only the responses for previously made requests." Uma página servida pelo cache HTTP continua carregando: o navegador analisa o HTML, roda todos os scripts e dispara load, então o seu rastreador envia uma pageview normal. Uma página restaurada do bfcache pula tudo isso.
Timers e promises também pausam. O web.dev observa que "browsers pause any pending timers or unresolved promises for pages in bfcache" e os retomam na restauração, então um heartbeat ou um timer de engajamento recomeça depois do intervalo, em vez de contar o tempo em que a página ficou parada.
Quais páginas podem entrar no bfcache?
Uma página pode entrar no bfcache a menos que algo nela torne o cache inseguro, e os bloqueios mais comuns estão sob o seu controle. A tabela lista os que o web.dev e a documentação do Chrome destacam.
| Bloqueio | Efeito no bfcache | Correção |
|---|---|---|
Listener de unload | Inelegível no Chrome e no Firefox para desktop; no Firefox também no mobile, exceto no iOS | Use pagehide no lugar |
Cache-Control: no-store na página | Historicamente mantém a página fora do bfcache | Use no-cache ou max-age=0, a menos que a página seja sensível |
Listener de beforeunload incondicional | Não bloqueia mais nos navegadores modernos, mas bloqueava antes, segundo o web.dev | Adicione-o só enquanto houver alterações não salvas |
Referência a window.opener | Uma página com opener não nulo "can't safely be put into bfcache" | Use rel="noopener" |
| Conexão IndexedDB aberta | Alguns navegadores não guardam a página em cache | Feche no pagehide e reabra no pageshow |
fetch() ou XMLHttpRequest em andamento | Alguns navegadores não guardam a página em cache | Deixe as requisições terminarem ou cancele-as no pagehide |
| Conexão WebSocket ou WebRTC aberta | Bloqueia em alguns navegadores; o Chrome 149 e posteriores e o Safari não bloqueiam por WebSockets abertos | Feche no pagehide |
Algumas falhas não têm nada a ver com o seu código. O web.dev lista navegações de voltar ou avançar que não usam o bfcache "when the user quits the browser and starts it again," "when the user duplicates a tab," e "when the user closes a tab and reopens it," e observa que os navegadores descartam páginas em cache depois de um tempo para economizar memória. Uma taxa de acerto de 100% não é uma meta realista.
Os iframes seguem a página principal. Um iframe não é guardado em cache separadamente, e um iframe que usa uma API bloqueadora pode manter a página inteira fora do bfcache.
Como o pageshow e o pagehide informam o uso do bfcache?
Os eventos pageshow e pagehide informam o uso do bfcache pela propriedade persisted. No pageshow, persisted é true quando a página voltou do bfcache e false em um carregamento normal. No pagehide, persisted igual a true significa que o navegador pretende guardar a página em cache, embora o web.dev ressalte que isso "doesn't guarantee that a page will be cached."
window.addEventListener('pageshow', (event) => {
if (event.persisted) {
console.log('This page was restored from the bfcache.');
} else {
console.log('This page was loaded normally.');
}
});O pageshow "fires right after the load event when the page is initially loading and any time the page is restored from bfcache." Esse detalhe importa para o analytics, como mostra a próxima seção. Os navegadores Chromium também disparam os eventos de Page Lifecycle freeze e resume quando uma página entra e sai do bfcache, mas o web.dev aponta que medir a sua taxa de acerto do bfcache exige o pageshow.

Por que o analytics perde ou conta em dobro as navegações de volta?
O analytics perde as navegações de volta porque uma restauração do bfcache não roda os scripts da página de novo, então um rastreador que envia a pageview no carregamento fica em silêncio. O web.dev avisa os donos de sites que eles podem notar "a decrease in the total number of pageviews reported as Chrome enables bfcache for more users," e acrescenta que muitos sites "already underreporting pageviews from other browsers that implement bfcache, because many popular analytics libraries don't measure bfcache restores as new pageviews."
A contagem dupla vem da correção oposta feita sem cuidado. Como o pageshow também dispara em todo carregamento normal, um listener que envia uma pageview em todo pageshow sem verificar persisted envia duas pageviews por carregamento: uma da inicialização normal do rastreador e outra do listener.
Outras distorções vêm do mesmo mecanismo:
Painel em tempo real
Rastreamento de metas
Rastreamento sem cookies
- Lacunas no engajamento. Os timers pausados recomeçam na restauração, então timers de engajamento e heartbeats pulam o tempo em que a página ficou na memória.
- Eventos de saída que nunca são enviados. Uma página que entra no bfcache nunca dispara
unload. O guia de beforeunload vs pagehide explica por que os beacons de saída devem ficar nopagehidee novisibilitychange. - Páginas mais rápidas parecendo mais lentas. O web.dev explica que as restaurações substituem visitas repetidas, que estão entre os carregamentos mais rápidos de um conjunto de dados, então os dados de tempo de carregamento pendem para o lado mais lento mesmo quando os visitantes tiveram uma experiência mais rápida.
- Contagens misturadas. Uma navegação de volta que não usa o bfcache faz um recarregamento completo e é contada, enquanto uma que usa não é. O mesmo padrão de cliques gera números diferentes conforme a elegibilidade.
O guia de pageviews vs sessões vs usuários mostra como essas lacunas chegam às métricas por sessão.
- O tracker envia a pageview no carregamento
- Uma restauração do bfcache não dispara load
- O clique em voltar nunca é contado
- pageshow também dispara em todo carregamento normal
- Cada carregamento envia duas pageviews
- As restaurações são contadas, mas os carregamentos dobram
- O listener envia só quando event.persisted é true
- Um carregamento normal fica em uma pageview
- Cada restauração soma exatamente uma
Como contar corretamente as restaurações do bfcache?
Você conta as restaurações do bfcache adicionando um listener de pageshow que envia uma pageview só quando event.persisted é true e depois testando se cada clique em voltar gera exatamente um hit.
- Adicione o listener. O exemplo do web.dev para o Google Analytics envia
gtag('event', 'page_view')dentro deif (event.persisted), deixando o carregamento normal para a pageview padrão. - Marque o tipo de navegação. Para medir a sua taxa de acerto, o web.dev desativa a pageview padrão com
send_page_view: false, envia uma comnavigation_typevindo deperformance.getEntriesByType('navigation')[0].typee envianavigation_type: 'back_forward_cache'nas restaurações. Compare as contagens deback_forwardeback_forward_cache. - Rode o teste do DevTools. No Chrome DevTools, abra Application, depois Back-forward Cache, e clique em Run Test. Um resultado positivo mostra "Restored from back-forward cache"; uma falha lista os motivos e marca os que podem ser corrigidos como Actionable.
- Colete os motivos das visitas reais. A propriedade
notRestoredReasonsna entrada de navigation timing informa por que uma página não foi restaurada. A documentação do Chrome diz que ela "has shipped from Chrome 123," com motivos comounload-listenereresponse-cache-control-no-store. - Corrija os bloqueios. Troque
unloadporpagehide, retire ono-storedas páginas que não são sensíveis e feche as conexões IndexedDB ou WebSocket nopagehide.
As métricas de desempenho pedem o mesmo cuidado. O web.dev explica que ferramentas como o Chrome User Experience Report tratam as restaurações como visitas de página separadas, e a biblioteca web-vitals oferece suporte a elas. Em uma restauração, o Largest Contentful Paint é medido do timestamp do pageshow até o próximo frame pintado, enquanto o Cumulative Layout Shift e o INP voltam a 0.
Como o bfcache afeta os dados do Flowsery?
A documentação do Flowsery não descreve como o rastreador trata uma restauração do bfcache, então teste isso no seu próprio site antes de adicionar qualquer código. A visão de analytics em tempo real do Flowsery mostra cada pageview no seu painel no momento em que ela acontece, o que deixa a checagem rápida: abra uma página, clique em um link, aperte voltar e veja se a página restaurada aparece como uma nova pageview. Rode antes o teste de bfcache do DevTools para saber se a página foi restaurada e não recarregada. Se as restaurações não aparecerem e você quiser contá-las, o SDK npm do Flowsery expõe um método trackPageview() que você pode chamar a partir de um listener de pageshow que verifica event.persisted, o que evita a contagem dupla que um listener sem essa verificação causaria.
Perguntas frequentes
Todos os navegadores têm bfcache?
Sim, todos os principais navegadores têm um. O web.dev lista o Chrome desde a versão 96, o Firefox e o Safari. Cada navegador tem as próprias regras de elegibilidade, e é por isso que a mesma página pode ir para o cache em um navegador e ser recarregada em outro.
Uma restauração do bfcache dispara o evento load?
Não. Uma restauração torna a página pausada visível de novo e retoma o JavaScript dela, então load e DOMContentLoaded não disparam. O evento pageshow dispara, com persisted definido como true.
Por que as minhas pageviews caíram depois que o Chrome ampliou o bfcache?
Mais cliques em voltar e avançar viraram restaurações em vez de recarregamentos, e muitos scripts de analytics só contam pageviews no carregamento. O web.dev descreve exatamente essa queda. Adicione um listener de pageshow que envia uma pageview quando event.persisted é true se você quiser contar as restaurações.
O Cache-Control: no-store desativa o bfcache?
Na própria página, ele historicamente mantém as páginas fora do bfcache. O web.dev recomenda usá-lo só em páginas com informações sensíveis e usar no-cache ou max-age=0 em páginas que só precisam de conteúdo atualizado. Nenhum desses dois afeta a elegibilidade.
Como verificar se uma página pode entrar no bfcache?
No Chrome DevTools, vá em Application, depois em Back-forward Cache, e clique em Run Test. O painel informa se a página foi restaurada e, se não foi, lista os motivos do bloqueio. Para visitas reais, leia notRestoredReasons na entrada de navigation timing.
O bfcache funciona dentro de uma single-page app?
Não. O web.dev afirma que o bfcache "doesn't work for 'soft navigations' within a single-page app." Ele vale quando um visitante sai do app e volta com o botão voltar, o que pode restaurar o app inteiro em vez de iniciá-lo do zero, se a página for elegível.
O que acontece com timers e heartbeats enquanto uma página está no bfcache?
Os navegadores pausam os timers pendentes e as promises não resolvidas, e os retomam na restauração. Um heartbeat ou timer de engajamento continua depois da pausa, então o tempo que a página passou na memória não conta como engajamento.
Um listener de unload deixa a página fora do bfcache?
Sim, no Chrome e no Firefox em desktop, e no Firefox em dispositivos móveis, exceto no iOS. Troque unload por pagehide e a página continua elegível.
Como evito contar pageviews em dobro com um listener de pageshow?
pageshow dispara em todo carregamento normal e em toda restauração, então envie a pageview só quando event.persisted for true. A inicialização normal do tracker já cobre o carregamento comum. Depois aperte voltar em uma página de teste e confirme que cada clique gera exatamente um registro.
O Flowsery conta automaticamente as restaurações do bfcache?
A documentação do Flowsery não descreve isso, então teste no seu próprio site. Abra uma página, clique em um link, aperte voltar e veja na visão de analytics em tempo real se aparece uma nova pageview. Se não aparecer, chame trackPageview() do SDK npm dentro de um listener de pageshow que verifique event.persisted.
Este artigo foi útil?
Diga-nos o que pensa!
Veja-nos mais no Google
Um clique marca a Flowsery como fonte preferida e nossos artigos passam a aparecer mais acima nas suas Principais notícias, no modo IA e nas visões gerais com IA.
Antes de ir...
Flowsery
Analytics orientado para receitas para o seu site
Rastreie cada visitante, fonte e conversão em tempo real. Simples, poderoso e sem cookies.
Painel em tempo real
Rastreamento de metas
Rastreamento sem cookies
Termos relacionados do glossário
Como o tracking de SPA conta pageviews quando a página nunca recarrega
Um bom tracking de SPA registra uma pageview por tela, com o referrer certo. Veja como a History API, as pageviews virtuais e o GA4 se encaixam.


Por que a taxa de rejeição do GA4 é só a taxa de engajamento invertida
Sua taxa de rejeição do GA4 é a parcela de sessões não engajadas. Como o Google a define, como ela difere do Universal Analytics e onde adicioná-la.


O que o relatório de página de destino do GA4 conta e onde ele fica em branco
Em Reports, o relatório de página de destino do GA4 lista a primeira página de cada sessão. Onde achar, métricas padrão, linhas (not set) e como ver a origem.


Como o rastreamento de pesquisa no site do GA4 registra o que os visitantes digitam
Configure a pesquisa no site do GA4 com a medição aprimorada, adicione seus parâmetros, ache a dimensão Search term e rastreie buscas sem URL.


Como definir propriedades de usuário do GA4 e usá-las em relatórios
Defina propriedades de usuário do GA4 com gtag ou Tag Manager, registre cada uma como dimensão personalizada de usuário e respeite o limite de 25.


Como vincular o Search Console ao GA4 e publicar os relatórios
Veja como vincular o Search Console ao GA4 no Admin, quais papéis você precisa, como publicar os dois relatórios na Library e o que os dados não cruzam.
Artigos relacionados


O que aconteceu com a descontinuação dos cookies de terceiros no Chrome
No Chrome, a descontinuação dos cookies de terceiros foi de um plano de 2020 a um recuo em 2025. Cada anúncio do Google, o que o Chrome faz hoje e o impacto.


Por que o CNAME cloaking não esconde mais rastreadores do Safari ou do Brave
Rastreadores usavam o CNAME cloaking para se passar por um subdomínio seu. Veja o truque de DNS, o limite de 7 dias do Safari e como Brave e uBlock o revelam.


Como a sincronização de cookies cruza IDs de anúncios entre sites
Empresas de ad tech usam a sincronização de cookies para trocar IDs por redirecionamentos e pixels. Veja o que Safari, Firefox e Chrome fazem contra ela.

