Como Adicionar Analytics Respeitosos à Privacidade em um Site Astro
As View Transitions do Astro quebram scripts de analytics padrão silenciosamente. Aqui está o padrão correto para rastrear cada mudança de rota sem cookies nem banner de consentimento.
As View Transitions do Astro trocam o conteúdo da página sem um recarregamento completo do navegador — o que significa que qualquer script de analytics que dependa de DOMContentLoaded ou load vai disparar apenas uma vez, na visita inicial. Toda navegação subsequente no lado do cliente é invisível. Isso não é um erro de configuração da sua parte; é uma consequência fundamental de como o ClientRouter funciona.
O mesmo problema de rastreamento silencioso existe no SvelteKit 2 e no Remix, mas a solução em cada framework é diferente. No Astro, a resposta é o evento de ciclo de vida astro:page-load.
Por que a tag de script comum não funciona
Quando <ClientRouter /> está ativo (opt-in via astro:transitions no Astro 4, habilitado por padrão no Astro 5), as navegações não descarregam a página. O Astro busca a próxima página em segundo plano, troca o DOM e atualiza a URL — tudo sem destruir o contexto JavaScript atual.
Um script de rastreamento carregado via uma tag <script> simples é tratado como um script de módulo empacotado pelo pipeline de build do Astro. Scripts de módulo empacotados executam exatamente uma vez por sessão de página. O tracker inicializa, registra um pageview para a página de entrada e depois nunca executa novamente enquanto o usuário navega.
Para disparar em cada navegação, a lógica de inicialização precisa ser conectada ao ciclo de vida de navegação do Astro. O hook correto é astro:page-load, que dispara depois que a nova página está visível e todos os scripts bloqueantes estão carregados — tanto no carregamento inicial quanto em cada transição subsequente.
A integração correta
Adicione o script de rastreamento uma vez no seu layout raiz (src/layouts/Layout.astro ou equivalente), em seguida adicione um listener para astro:page-load:
---
// Layout.astro
---
<html lang="pt-BR">
<head>
<!-- conteúdo do head -->
</head>
<body>
<slot />
<script
is:inline
src="https://api.monoid.website/tracker.min.js"
data-site-id="SEU_SITE_ID"
async
></script>
</body>
</html>
A diretiva is:inline instrui o bundler do Astro a deixar esse script exatamente como está. Sem ela, o Astro processaria o script como módulo, o deduplicaria e suprimiria a re-execução. Com is:inline, a tag de script é emitida verbatim no HTML de cada página.
Para sites que não usam View Transitions, isso é tudo que você precisa. O tracker dispara uma vez no carregamento e pronto.
Lidando com a navegação das View Transitions
Se seu site usa <ClientRouter />, o hook history.pushState embutido do tracker dispara corretamente após cada transição — o tracker escuta os eventos de navegação do Astro internamente. Nenhuma configuração adicional é necessária.
Para verificar, abra a aba Rede do DevTools e filtre por collect. Navegue entre duas páginas. Você deve ver uma requisição POST por navegação, incluindo o carregamento inicial.
Se você injeta o tracker condicionalmente e precisa que ele seja reinicializado após cada troca (por exemplo, depois que uma ilha dinâmica é montada), você pode acionar manualmente uma re-execução:
<script data-astro-rerun>
// Este bloco re-executa após cada View Transition.
// Use com moderação — a maior parte da lógica do tracker não deve ficar aqui.
if (window.__monoid) {
window.__monoid.trackPageview();
}
</script>
O atributo data-astro-rerun força scripts inline a re-executarem após cada transição. Note que ele implica is:inline, portanto aplica-se apenas a scripts não empacotados.
Separando ambientes
Projetos Astro geralmente têm ambientes de desenvolvimento local, preview e produção. Use uma variável de ambiente para armazenar o site_id e suprimir o rastreamento em desenvolvimento:
---
const siteId = import.meta.env.PUBLIC_MONOID_SITE_ID
---
{siteId && (
<script
is:inline
src="https://api.monoid.website/tracker.min.js"
data-site-id={siteId}
async
></script>
)}
Defina PUBLIC_MONOID_SITE_ID no .env para produção e deixe sem definir localmente. O Astro expõe variáveis com prefixo PUBLIC_ ao cliente; variáveis somente do servidor (sem o prefixo) não são visíveis no código executado no navegador.
O que você não precisa
Sem banner de consentimento de cookies. Sem integração com CMP. O endpoint de coleta computa um hash diário do visitante a partir do endereço IP, User-Agent, um segredo do servidor e a data atual:
visitor_hash = SHA-256(IP + UA + SALT_SECRET + YYYY-MM-DD)
O hash é redefinido a cada 24 horas. Nada é armazenado no dispositivo do visitante. Família de navegador e tipo de dispositivo são derivados no servidor a partir do User-Agent da requisição para relatórios agregados — strings completas de User-Agent, versões de navegador e identificadores persistentes nunca são armazenados.
Sites Astro frequentemente são totalmente estáticos ou renderizados no edge com JavaScript mínimo. Adicionar um script de analytics com menos de 2 KB sem cookies nem requisito de consentimento se encaixa naturalmente nessa filosofia. Não há pacote npm para manter, nenhum SDK para atualizar e nenhuma base legal do GDPR para documentar para o processamento de analytics.