Guia de integração
Analytics no Next.js
Um client component no layout raiz conta a primeira pageview e cada navegação feita pelo roteador do Next. Funciona com App Router e com Pages Router.
Antes de começar
- Next.js 13 ou mais novo (App Router) ou qualquer versão com Pages Router.
- A
site_keydo site e o domínio (ehttp://localhost:3000, se quiser medir em dev) em Allowed origins.
Instalação
1Instale o SDK
O pacote é o mesmo SDK do snippet de script, com tipos TypeScript.
npm install @racoelho/analytics.env.local NEXT_PUBLIC_ANALISA_SITE_KEY=YOUR_SITE_KEYO prefixo
NEXT_PUBLIC_é necessário porque a chave é usada no navegador. Ela é pública por natureza — quem protege o envio é a lista de Allowed origins.2Crie o client component (App Router)
O SDK precisa de
window, então ele vive num componente com'use client'. A instância é criada uma vez, no primeirouseEffect; nas trocas de rota, o efeito roda de novo e registra a nova página.app/analytics.tsx 'use client' import { useEffect } from 'react' import { usePathname } from 'next/navigation' import { Analytics } from '@racoelho/analytics' let analytics: Analytics | null = null /** Para eventos em client components: getAnalytics()?.track(…) */ export function getAnalytics() { return analytics } export function AnalyticsTracker() { const pathname = usePathname() useEffect(() => { if (!analytics) { // primeira carga: o construtor já envia a pageview analytics = new Analytics({ siteKey: process.env.NEXT_PUBLIC_ANALISA_SITE_KEY! }) return } // navegação no cliente: conta a nova página analytics.pageview() }, [pathname]) return null }3Coloque o componente no layout raiz
Dentro do
<body>, depois do conteúdo. O layout continua sendo um Server Component.app/layout.tsx import { AnalyticsTracker } from './analytics' export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <html lang="en"> <body> {children} <AnalyticsTracker /> </body> </html> ) }4Usa Pages Router? Faça no
_appMesma ideia: crie a instância uma vez e chame
pageview()no eventorouteChangeCompletedo roteador.pages/_app.tsx import type { AppProps } from 'next/app' import { useEffect } from 'react' import { useRouter } from 'next/router' import { Analytics } from '@racoelho/analytics' let analytics: Analytics | null = null export default function App({ Component, pageProps }: AppProps) { const router = useRouter() useEffect(() => { // cria uma vez; o construtor envia a primeira pageview analytics ??= new Analytics({ siteKey: process.env.NEXT_PUBLIC_ANALISA_SITE_KEY! }) const onRouteChange = () => analytics?.pageview() router.events.on('routeChangeComplete', onRouteChange) return () => router.events.off('routeChangeComplete', onRouteChange) }, [router.events]) return <Component {...pageProps} /> }
Eventos e metas
Em qualquer client component, importe getAnalytics() e chame track(nome, propriedades). O ?. evita erro se o clique acontecer antes do primeiro efeito rodar.
'use client'
import { getAnalytics } from '@/app/analytics'
export function SignupButton() {
return (
<button
onClick={() => {
// evento próprio, com propriedades
getAnalytics()?.track('signup_click', { plan: 'pro' })
}}
>
Criar conta
</button>
)
}// depois do login
getAnalytics()?.identify({ user_id: user.id, traits: { plan: user.plan } })
// no logout
getAnalytics()?.reset()Crie no painel uma meta do tipo evento com o nome signup_click. Com identify(), as sessões anônimas anteriores ao login ficam ligadas ao usuário.
Navegação entre páginas
O SDK manda a pageview da primeira carga sozinho, mas não escuta as navegações do roteador — por isso o useEffect com pathname (App Router) ou o routeChangeComplete (Pages Router). Trocar só a query string não conta como nova página: o SDK registra o caminho. No modo de desenvolvimento, o React roda o efeito duas vezes; o SDK descarta a pageview repetida do mesmo caminho em menos de 2,5 segundos.
Confira se está funcionando
- Abra o site publicado numa janela comum, sem bloqueador de anúncios.
- Nas ferramentas do navegador, aba Network, filtre por
v1/i: deve aparecer umPOSTcom status200em até 3 segundos (ou quando você sai da página). - No painel, os eventos aparecem em cerca de 30 segundos.
- Navegue entre duas páginas pelo
<Link>: cada troca gera uma nova pageview noPOSTseguinte.
Problemas comuns
- Só a primeira página é contada
- O
<AnalyticsTracker />ficou numa página e não no layout raiz, ou o efeito não depende depathname. Ele precisa estar emapp/layout.tsx, que não é desmontado entre navegações. siteKey is required- A variável de ambiente não chegou ao navegador. Confira o prefixo
NEXT_PUBLIC_e reinicie onext dev(ou refaça o build) depois de mudar o.env. - A requisição volta 403 (
origin_not_allowed) - O domínio não está em Allowed origins nas configurações do site. Cadastre a origem exata — com
https://, com e semwww, e endereços de teste comohttp://localhost:3000se quiser medir em desenvolvimento. - Nenhuma requisição aparece na aba Network
- O SDK respeita o Do Not Track por padrão: se o seu navegador envia DNT, nada é enviado. Teste em outro navegador ou perfil. Bloqueadores de anúncio também podem barrar o script.
- As pageviews aparecem em dobro
- O SDK foi inicializado duas vezes (por exemplo, o script colado no tema e também por um plugin). Mantenha uma única instância por página.