Updated 20 October 2026

SvelteKit analytics

Privacy-first, cookieless analytics for SvelteKit: one tag in app.html, or events sent through a route on your own domain.

In short

  • Paste the tag in src/app.html, or call init from src/hooks.client.ts.
  • Client-side navigation is counted by itself, and the same URL is never counted twice in a row.
  • No cookie banner needed in cookieless mode, no IP address stored, and nothing loaded from another company.

Install on SvelteKit#

Use your own site id and server address in the code below. On trckable Cloud the address is https://cloud.trckable.com.

The shortest install is the tag, in the <head> of src/app.html:

<head>
  %sveltekit.head%
  <script
    defer
    data-site="tkb_a1b2c3d4"
    data-domain="example.com"
    src="https://stats.example.com/js/tkb_a1b2c3d4.js">
  </script>
</head>

To send events through your own domain instead, install the package, call it in src/hooks.client.ts, and add a route that forwards them:

// src/hooks.client.ts
import { init } from 'trckable'

init({ site: 'tkb_a1b2c3d4' })

The route uses trckable/server, which takes a standard Request and returns a Response:

// src/routes/api/e/+server.ts
import { proxy } from 'trckable/server'
import { env } from '$env/dynamic/private'

const trckable = proxy({ host: env.TRCKABLE_HOST, proxyKey: env.TRCKABLE_PROXY_KEY })

export const POST = ({ request }) => trckable(request)

Set the two variables where the app runs, then check it:

# .env (on your server, never in the browser)
TRCKABLE_HOST=https://stats.example.com
TRCKABLE_PROXY_KEY=your-proxy-key

Open your site once, then run npx trckable doctor --host https://stats.example.com --site tkb_a1b2c3d4 --url https://example.com. It only reads, and tells you whether the tag is on the page and the server answers.

What to know about SvelteKit#

  • Both install styles count client-side navigation. SvelteKit changes the URL with the history API, and trckable counts the route change.
  • Without host, events go to /api/e on your own domain, which is why the route above has that path. Leave the route out and keep the tag if you do not want a proxy.
  • The proxy key stays on the server. Read it from $env/dynamic/private, never from a PUBLIC_ variable.
  • Prerendered and static sites work with the tag. The route needs a server adapter, because it runs on each request.

Goals and revenue#

A goal needs no code: put an attribute on the element and each click is counted.

<button data-trckable-goal="signup" data-trckable-goal-plan="pro">Start trial</button>

Connect Stripe, Paddle, Lemon Squeezy, Polar or Dodo Payments with one key, and each payment is credited to the visit that earned it, so revenue shows next to traffic. See revenue attribution.

Questions#

Which install should I pick for SvelteKit?
The tag in app.html if you want the quickest start, on any adapter. The package with a route on your own domain if you want the accurate setup: no separate analytics file for a blocklist to match, and a visitor cookie that Safari keeps for 400 days instead of seven.
Do I need a cookie banner on my SvelteKit site?
Not for the counting itself. In cookieless mode (add data-cookieless to the tag) nothing is stored on the visitor's device and no IP address is kept. Whether your site needs a banner for other reasons is a question for your own situation; the cookie banner guide explains the rules in plain words.
Can ad blockers stop it?
A blocker can block any script, and trckable does not claim otherwise. Sending events through your own domain removes the separate analytics file a blocklist would match by name, which is the accurate setup. The same-origin proxy guide shows how.
Is it free for a SvelteKit site?
The server is open source and free to self-host, and the tracker is MIT licensed. If you would rather not run a server, trckable Cloud runs it for you; the plans are on the pricing page.

Keep reading#

Other stacks#

Start free