Glossário

Por que beforeunload vs pagehide decide se o analytics sobrevive

Taras Shynkarenko
Taras Shynkarenko
Atualizado: 7 min de leitura
Por que beforeunload vs pagehide decide se o analytics sobrevivePor que beforeunload vs pagehide decide se o analytics sobrevive

TL;DR, Resposta rápida

7 min de leitura

A escolha entre beforeunload vs pagehide importa porque beforeunload não dispara de forma confiável no celular e, no Firefox, desqualifica a página do back-forward cache. O pagehide dispara nas mesmas navegações sem esse custo de bfcache, e o MDN recomenda visibilitychange primeiro, pagehide como alternativa, junto com sendBeacon para enviar o analytics antes de a página desaparecer.

Por que beforeunload vs pagehide importa para enviar analytics?

Escolher certo entre beforeunload vs pagehide decide se um evento de analytics realmente chega ao servidor antes de o usuário sair da página. O MDN documenta que o beforeunload não dispara de forma confiável, principalmente no celular: um usuário que troca para outro app e depois fecha o navegador pelo gerenciador de apps nunca chega a disparar o evento. Use pagehide ou visibilitychange para enviar dados em vez de beforeunload, e reserve o beforeunload para a única tarefa que ele ainda cumpre bem, avisar o usuário sobre alterações não salvas. Errar nisso é um dos motivos mais silenciosos pelos quais uma configuração de monitoramento de usuários reais subconta as saídas.

O que o evento beforeunload realmente faz?

O evento beforeunload dispara pouco antes de a página ser descarregada e pode mostrar uma caixa de diálogo de confirmação nativa do navegador para avisar o usuário sobre alterações não salvas. A própria orientação do MDN é adicionar o listener só quando houver alterações não salvas para proteger, e removê-lo assim que essas alterações forem salvas, em vez de deixá-lo anexado durante toda a vida da página. Esse caso de uso restrito também é o único para o qual ele ainda serve, já que sua confiabilidade como sinal geral de saída não existe.

Uma mão passando por aplicativos abertos no celular, o momento do alternador de apps que pula eventos de saída no celular.

Por que o beforeunload é pouco confiável no celular?

O beforeunload é pouco confiável no celular porque um navegador fechado pelo seletor de apps, ou um app colocado em segundo plano e nunca reaberto, pula o evento por completo, o que o MDN aponta diretamente no cenário de trocar de app e depois fechar. Uma aba de desktop fechada pelos controles da janela dispara o evento; a mesma sequência num celular, colocar o app em segundo plano e fechá-lo pelo gerenciador de apps, pula o evento por completo. Qualquer chamada de analytics que dependa só do disparo do beforeunload perde dados exatamente na plataforma onde as sessões terminam desse jeito.

Mesmo fechamento, resultado diferente
Fechamento de aba no desktop
  • O usuário clica nos controles da janela
  • O beforeunload dispara
Troca de app no celular
  • O usuário coloca o app em segundo plano e depois o fecha pelo gerenciador de apps
  • O beforeunload nunca dispara
O exemplo do MDN sobre a troca de apps mostra que o mesmo caminho de saída pula o evento por completo no celular.

Como o beforeunload afeta o back-forward cache?

O efeito do beforeunload sobre o back-forward cache muda de navegador para navegador: o Firefox não coloca uma página no bfcache se ela tiver um listener de beforeunload anexado, enquanto o guia de bfcache do web.dev aponta que o beforeunload não desqualifica mais uma página do bfcache em outros navegadores modernos, embora antes desqualificasse. O web.dev ainda chama o evento de "pouco confiável, então evite usá-lo a menos que seja absolutamente necessário", e recomenda adicionar o listener de forma condicional, só enquanto existirem alterações não salvas, em vez de em todo carregamento de página. Uma página que pula o bfcache recarrega do zero numa navegação para trás, em vez de ser restaurada instantaneamente da memória.

Uma pessoa fechando um notebook, o momento em que uma página é ocultada antes de o navegador mostrar outra.

O que o evento pagehide faz de diferente?

O evento pagehide dispara quando o navegador oculta a página atual enquanto apresenta outra página do histórico de sessão, como um clique no botão voltar, e diferente de beforeunload e unload, um listener de pagehide não torna a página inelegível para o bfcache. O MDN recomenda visibilitychange primeiro como o sinal mais confiável, com pagehide como alternativa para navegadores onde visibilitychange não está disponível. Anexe a lógica de envio ao pagehide quando a página precisar de um listener seguro para o bfcache que ainda assim dispare nos mesmos momentos de navegação que o beforeunload deveria capturar, o que também é o momento em que um relógio de timeout de sessão continuaria correndo contra uma página que ninguém está olhando.

EventoDispara de forma confiável no celular?Bloqueia o bfcache?Melhor uso
unloadNão, o MDN chama de "extremamente pouco confiável" no celularSim, no Chrome e Firefox de desktopEvitar; só código legado
beforeunloadNão, segundo o exemplo de troca de app do MDNNão nos navegadores modernos, segundo o web.devSó para avisar sobre alterações não salvas
pagehideSinal alternativo segundo o MDNNãoEnviar analytics quando visibilitychange não está disponível
visibilitychangeSinal principal recomendado pelo MDNNãoEnviar analytics ao ocultar a aba, primeira escolha

Onde o sendBeacon se encaixa ao lado do pagehide?

O sendBeacon se encaixa ao lado do pagehide como mecanismo de entrega, já que ele enfileira uma requisição POST assíncrona que o navegador continua tentando enviar mesmo enquanto a página desaparece, sem atrasar a navegação que o usuário já está fazendo. O MDN recomenda combiná-lo com o evento visibilitychange como gatilho principal e pagehide como alternativa, em vez de dispará-lo a partir de unload ou beforeunload. Uma única chamada de sendBeacon é limitada a cerca de 64 KiB; uma carga maior que isso precisa de fetch() com a opção keepalive no lugar.

Como um script de analytics deve combinar esses eventos?

Um script de analytics deve escutar visibilitychange e verificar document.visibilityState === "hidden" como gatilho principal de envio, adicionar pagehide como alternativa para navegadores ou situações em que visibilitychange não dispara, e chamar sendBeacon nos dois handlers para enviar a carga sem bloquear a navegação. O script leve da Flowsery pesa menos de 10 KB justamente para que essa lógica de listeners adicione peso desprezível a uma página que já está tentando sair. Pular direto para o beforeunload nessa tarefa é o atalho que mais custa dados no celular, e é o mesmo atalho que desinfla silenciosamente uma contagem de bounce rate vs exit rate quando o último evento de uma página nunca chega ao servidor.

Enviando analytics antes de a página desaparecer
1
Escute visibilitychange. Verifique document.visibilityState === "hidden" como sinal principal.
2
Adicione pagehide como alternativa. Cobre os casos em que visibilitychange não dispara.
3
Envie com sendBeacon. Enfileira um POST assíncrono que não atrasa a navegação.
4
Deixe beforeunload só para alterações não salvas. Adicione condicionalmente, remova depois de salvar.
A ordem que o MDN e o web.dev recomendam para um envio de saída confiável e seguro para o bfcache.

Perguntas frequentes

O beforeunload ainda é útil para alguma coisa?

O beforeunload ainda é útil para avisar o usuário sobre alterações não salvas por meio de uma caixa de diálogo de confirmação nativa do navegador. A própria recomendação do MDN é anexar o listener só enquanto existirem alterações não salvas e removê-lo assim que forem salvas, em vez de usá-lo como sinal geral de saída de página.

Por que o pagehide não bloqueia o back-forward cache como o beforeunload bloqueava antes?

O pagehide não bloqueia o bfcache porque foi projetado como parte da Page Lifecycle API especificamente para sinalizar uma transição de página sem os efeitos colaterais que unload e beforeunload carregam. O MDN afirma claramente que, diferente de unload e beforeunload, um listener de pagehide não torna a página inelegível para o bfcache.

O visibilitychange deveria substituir o pagehide por completo?

O visibilitychange deveria ser o sinal principal, com o pagehide mantido como alternativa, segundo a própria orientação do MDN. Alguns navegadores ou contextos não disparam visibilitychange em todo cenário de saída, então o pagehide cobre os casos que o visibilitychange perde em vez de substituí-lo por completo.

O que acontece se uma chamada de analytics usar fetch em vez de sendBeacon na saída da página?

Uma chamada fetch comum iniciada durante a saída da página pode ser cancelada antes de o navegador terminar de enviá-la, já que a página já está sendo descarregada. O sendBeacon existe justamente para evitar isso: o navegador aceita a requisição e continua tentando entregá-la independentemente de a página já ter desaparecido, até seu limite de cerca de 64 KiB.

O back-forward cache afeta o analytics de alguma forma?

O back-forward cache restaura uma página da memória numa navegação para trás ou para frente em vez de recarregá-la, o que significa que o JavaScript da página não roda de novo e nenhuma lógica de pageview que dependa de um carregamento novo dispara de novo. Um evento pageshow com event.persisted === true é o sinal de que uma restauração aconteceu, algo que a lógica de analytics precisa verificar separadamente de um primeiro carregamento.

Por que o Firefox trata o beforeunload de forma diferente dos outros navegadores para o bfcache?

O Firefox desqualifica uma página do bfcache se ela tiver um listener de beforeunload anexado, uma postura mais rígida do que a de navegadores que pararam de desqualificar páginas com beforeunload do bfcache depois de terem feito isso antes. A escolha mais segura entre navegadores continua sendo adicionar um listener de beforeunload só quando existirem alterações não salvas, já que isso mantém o listener fora da página durante as navegações em que a elegibilidade para o bfcache mais importa.

Flowsery
Flowsery

Teste gratuito

Painel em tempo real

Rastreamento de metas

Rastreamento sem cookies

O que acontece se um payload de analytics ultrapassar o limite de 64 KiB do sendBeacon?

Uma chamada sendBeacon, limitada a cerca de 64 KiB, rejeita de vez um payload maior, que nunca chega ao servidor. Trocar para fetch com a opção keepalive dá conta de payloads acima desse limite e ainda sobrevive a uma página que já está descarregando.

O evento unload é um fallback mais seguro que o beforeunload?

Unload é pior, não mais seguro. O MDN o chama de extremamente pouco confiável no celular, e ele ainda bloqueia o back-forward cache no Chrome e no Firefox no desktop, exatamente o custo que o pagehide existe para evitar. Vale tratá-lo como código legado a evitar, não como um fallback a usar.

Adicionar listeners de pagehide e visibilitychange deixa a página mais pesada?

O Flowsery entrega seu script com menos de 10 KB justamente para que essa lógica de listeners agregue peso insignificante a uma página que já está tentando sair. O custo real está no tamanho do payload do sendBeacon, não nos listeners em si.

Como o envio no pagehide afeta o rastreamento de timeout de sessão?

O pagehide dispara no momento exato em que uma página fica escondida atrás de outra no histórico de sessão, que é também o momento em que um relógio de timeout de sessão continuaria rodando contra uma página que ninguém mais está vendo. Enviar os dados nesse instante encerra a sessão na hora certa, em vez de acumular tempo ocioso contra uma aba que o usuário já abandonou.

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

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

O que estes números revelam sobre a taxa de rejeição média por setorO que estes números revelam sobre a taxa de rejeição média por setor
Glossário

O que estes números revelam sobre a taxa de rejeição média por setor

Nove setores rastreados mostram uma taxa de rejeição média por setor documentada, entre 35.76% e 48.38%, segundo dados da Databox de setembro de 2024.

7 min de leitura
Por que visualizações de página vs sessões vs usuários nunca batem em um mesmo relatórioPor que visualizações de página vs sessões vs usuários nunca batem em um mesmo relatório
Glossário

Por que visualizações de página vs sessões vs usuários nunca batem em um mesmo relatório

Comparar visualizações de página vs sessões vs usuários mostra três contagens separadas que se encaixam uma na outra e raramente batem no mesmo número.

9 min de leitura
Como as regras de tempo limite da sessão inflam suas análisesComo as regras de tempo limite da sessão inflam suas análises
Glossário

Como as regras de tempo limite da sessão inflam suas análises

Um tempo limite da sessão encerra a sessão de um visitante inativo, e a regra padrão de 30 minutos explica por que o mesmo tráfego mostra números diferentes.

8 min de leitura
Como saber o que é uma boa taxa de conversão para o seu siteComo saber o que é uma boa taxa de conversão para o seu site
Glossário

Como saber o que é uma boa taxa de conversão para o seu site

Benchmarks respondem o que é uma boa taxa de conversão de forma diferente para ecommerce, SaaS e leads, e um número mediano esconde mais do que revela.

8 min de leitura
O que é uma sessão em web analyticsO que é uma sessão em web analytics
Glossário

O que é uma sessão em web analytics

Em web analytics, uma sessão é um grupo de interações de um visitante, encerrado por inatividade, meia-noite ou troca de campanha.

8 min de leitura
Como funciona o session replay e o que ele não vêComo funciona o session replay e o que ele não vê
Glossário

Como funciona o session replay e o que ele não vê

O session replay reconstrói uma visita a partir de mutações do DOM e eventos de entrada, não de vídeo. Veja o que captura, o que o mascaramento esconde.

9 min de leitura

Artigos relacionados