Skip to main content
For Next.js with the App Router. Tested by the example examples/nextjs (Next.js 16.4.6, React 19.3.1, next build and next start), which runs in the browser test matrix.

Where the tag goes

Render the tag as a plain <script> element in the <head> of the root layout, app/layout.js (or app/layout.tsx):
The example reads the three values on the server from its environment and the tracker’s release manifest, so tests can use their own site id:
In your app, write the values from the console’s tag directly into the element: src, integrity and data-website-id of
Write crossOrigin in JSX; React renders it as crossorigin. The example is plain JavaScript only because Next.js type-checks TypeScript projects through the typescript package’s compiler API, which the TypeScript 7 pinned in this repository does not offer; in a TypeScript app the layout is the same.

Route changes

The first load is server rendered and is one pageview. <Link> navigations happen on the client with history.pushState, which the tracker watches, so each is one pageview; back and forward too. Known limitation. Right after a back or forward navigation, the App Router rewrites the current history entry with history.replaceState, before the tracker’s 300 ms delay for that pageview has passed. The pageview is counted for the right page, but its referrer becomes the page itself instead of the page the visitor came from. Referrers inside your own site are not stored anyway (they are sent as paths and dropped by the gateway), so the dashboards are not affected; only a data-before-send hook that reads the referrer would see it. The browser test checks the referrer only for forward navigations on this example for that reason.

Custom events

data-umami-event attributes work in server and client components alike. A click handler needs a client component:

What the browser tests check

One pageview per server-rendered load and per client-side navigation, back and forward, the previous route as referrer on forward navigations, an external referrer on the first pageview, both kinds of custom event, Global Privacy Control and a tampered tracker refused (tests/e2e/specs, examples/nextjs/test).