Next.js ha bisogno del tag in un posto solo e poi ti lascia in pace: le navigazioni lato client si contano da sole, quindi non c'è nessun evento del router a cui iscriversi e niente da chiamare al cambio di rotta.

Vai prima a prendere lo snippet dalla tua dashboard. Ha questo aspetto, con il tuo identificativo di sito nel percorso:

<script src="https://t.skomi.com/s/your-site-id.js" defer></script>

App Router

In app/layout.tsx, dentro il <body>:

import Script from "next/script";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        {children}
        <Script
          src="https://t.skomi.com/s/your-site-id.js"
          strategy="afterInteractive"
        />
      </body>
    </html>
  );
}

afterInteractive è il valore di serie ed è quello giusto qui: la pagina deve finire di caricare per prima, e non c'è niente sopra che aspetti l'analitica.

Pages Router

Lo stesso tag in pages/_app.tsx:

import Script from "next/script";
import type { AppProps } from "next/app";

export default function App({ Component, pageProps }: AppProps) {
  return (
    <>
      <Component {...pageProps} />
      <Script
        src="https://t.skomi.com/s/your-site-id.js"
        strategy="afterInteractive"
      />
    </>
  );
}

Nel _app e non nel _document, così sopravvive a una navigazione lato client come ci sopravvive il resto della tua applicazione.

La navigazione lato client è già contata

È la parte che le persone si aspettano di dover scrivere, e non c'è niente da scrivere.

Lo script di Skomi avvolge history.pushState e history.replaceState e ascolta popstate, quindi ogni cambio di rotta che Next fa è una pagina vista, che chi visita abbia cliccato un <Link>, sia tornato indietro, o che tu abbia chiamato router.push da solo.

Due dettagli che vale la pena conoscere, perché sono quelli che sembrano difetti:

  • Una navigazione che non cambia l'indirizzo non viene contata. Sostituire l'indirizzo con lo stesso indirizzo (cosa che un filtro o un aggiornamento della posizione di scorrimento a volte fanno) viene ignorato invece che contato come una seconda vista.
  • La pagina che si sta lasciando viene chiusa per prima. Il suo tempo sulla pagina e la sua profondità di scorrimento vengono svuotati prima che la vista nuova si apra, quindi un'applicazione a pagina singola riporta l'attenzione per rotta invece di un numero solo per tutta la sessione.

Non usare strategy="worker"

next/script offre una strategia worker che sposta uno script di terze parti dentro un web worker attraverso Partytown. È una buona idea per gli script che mandano soltanto eventi, e rompe questo del tutto: un worker non ha document, quindi non c'è nessuna pagina da leggere.

Tutto quello che Skomi fa ha bisogno della pagina vera: le mappe di calore e le registrazioni di sessione ne sono un'immagine, il widget di feedback ci deve comparire sopra, e persino l'analitica semplice ha bisogno dell'indirizzo che chi visita sta davvero guardando. Usa afterInteractive.

beforeInteractive non è sbagliato, solo inutile: esiste per gli script che devono girare prima dell'idratazione, e contare una visita non è uno di quelli.

Se hai una Content Security Policy

Next.js rende facile aggiungere una CSP stretta, e una CSP stretta blocca questo finché non le dici di no. Lo script e i dati che manda usano entrambi un solo host:

script-src  https://t.skomi.com
connect-src https://t.skomi.com

Se la tua policy usa un nonce, applicalo a questo tag come lo applichi ai tuoi.

In sviluppo non arriva niente

localhost non è il dominio che hai registrato, quindi i registri che arrivano da lì sono rifiutati dalla verifica dell'origine. È deliberato (il tuo lavoro non dovrebbe stare nei tuoi numeri) e vuol dire davvero che npm run dev non è dove confermi l'installazione. Pubblica sul dominio vero, o su un suo sottodominio, e guarda lì.

Controlla che funzioni

Carica una pagina sul dominio vero, clicca fino a un'altra rotta, e guarda la tua dashboard: dovresti vedere due pagine viste invece di una. Se non arriva niente, vedi che cosa controllare quando lo snippet non funziona.