Skip to main content
For SvelteKit apps. Tested by the example examples/sveltekit (SvelteKit 3.1.1, Svelte 5.57.3, @sveltejs/adapter-node 6.0.2, Vite 8), which runs in the browser test matrix.

Where the tag goes

Put the tag in src/app.html, before %sveltekit.head%:
The example replaces the comment with the tag in a handle hook so that tests can set their own site id at run time. In your app the tag from the console stands there:
app.html is the page template of every route, and SvelteKit copies markup outside its %sveltekit.*% placeholders into each page as it is (the example relies on that: its hook finds the comment unchanged in every rendered page). Keep the tag there rather than in <svelte:head>, so it is part of every page exactly once and no component manages it.

Route changes

The first load is rendered on the server and is one pageview. After that SvelteKit navigates on the client with history.pushState, which the tracker watches, so every route change, back and forward included, is one pageview.

Custom events

data-umami-event attributes work in any component. For a call from code, use window.umami?.track():
and declare the global in src/app.d.ts for TypeScript:

Content security policy

If you use SvelteKit’s kit.csp option, add the gateway to script-src and connect-src as content-security-policy.md describes. The example does not set kit.csp.

What the browser tests check

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