SvelteKit Analytics Without Google: Add Litlyx in 10 Minutes

Set up privacy-first SvelteKit analytics with Litlyx. GDPR-compliant, cookieless tracking that captures all client-side navigation events.

Flat-lay still-life composition showing a smartphone displaying the Litlyx analytics dashboard in purple, surrounded by code snippets, a Sve

, -

SvelteKit Analytics Without Google: Add Litlyx in Under 10 Minutes

Why SvelteKit Breaks Standard Analytics Scripts

SvelteKit 2 intercepts all client-side navigation at the router level, which means a plain analytics script tag fires only on hard reloads, silently missing every soft route change. This is not a minor quirk. It is a structural incompatibility that affects Google Analytics 4 and virtually every other tag-based solution out of the box. The fix lives inside SvelteKit's own lifecycle, not in the browser's history API.

To understand why this matters, consider how most analytics scripts actually work. They listen for changes to history.pushState and fire a page view event each time the URL updates. That pattern works fine in traditional single-page apps that patch pushState directly. SvelteKit, however, calls its own internal navigation primitives first and only triggers pushState as a side effect, after the route transition is already in progress. By the time any patched listener reacts, the new route may not yet be fully rendered, which creates race conditions and missed events.

The practical result is stark. As documented in the wild, SvelteKit 2 broke most existing analytics integrations silently, with Google Analytics GA4 recording only the first page view on initial load. A developer who drops in the standard GA4 snippet and calls it done will see a dashboard that looks plausible but is missing the vast majority of user activity.

The correct approach requires hooking into SvelteKit's own navigation lifecycle, specifically the afterNavigate function from $app/navigation. This fires after every completed navigation, including the first load, giving analytics tools a reliable signal that the browser's history API simply cannot provide. That architectural gap is exactly why developers searching for SvelteKit analytics without Google consistently land on purpose-built or hook-aware alternatives rather than retrofitting traditional tag solutions.

What Makes a Good Google Analytics Alternative for SvelteKit?

Any good Google Analytics alternative for SvelteKit has to clear four bars: hooking into the framework's own navigation lifecycle, collecting zero personal data, staying light enough to protect Core Web Vitals, and surfacing real-time results without needing a data team. Miss even one of these and you end up with either incomplete page views or compliance headaches.

Hook Into SvelteKit's Navigation Lifecycle

Because SvelteKit's client-side router intercepts navigation before the browser history API gets involved, an analytics tool needs to work with afterNavigate or onNavigate from $app/navigation. Solutions that rely on a plain script tag will only fire on hard reloads, missing every client-side navigation. That means your page view counts are wrong from day one, which makes every data-driven decision that follows equally wrong.

GDPR-Compliant and Cookieless by Default

A GDPR-compliant analytics tool should not require a banner at all. Cookieless tracking achieves this by collecting no personal identifiers and storing no information on the user's device. This keeps your site clean and fast, and removes the friction that visitor prompts introduce.

Lightweight Script, Real-Time Dashboard

A bloated analytics script is a direct threat to your Largest Contentful Paint and Total Blocking Time scores. You want something small. Something that loads asynchronously and gets out of the way. Pair that with a dashboard delivering user-friendly insights right now, not after a 24-hour processing delay.

Litlyx satisfies all four criteria. Built and hosted entirely in the EU, it is a Privacy-first analytics platform that is fully GDPR-compliant, stores no personal data, skips visitor prompts entirely, and pushes results to a real-time dashboard the moment events begin flowing in.

What We Are Building: The Scenario and Tools

Before writing a single line of code, let's be clear about what the finished integration looks like. We are taking an existing SvelteKit 2 project (any adapter, any deployment target) and wiring up Privacy-first analytics through Litlyx so that every client-side route change registers as a page view, no Google services involved.

The tools are intentionally minimal. Litlyx serves as our analytics provider: fully GDPR-compliant, EU-hosted, and collecting zero personal data. Our goal is accurate page view events on every navigation plus at least one custom event example, giving us a complete picture of user behavior from day one.

Here is what the finished setup requires:

  • A Litlyx project ID (free to create, no credit card needed)
  • One script tag added to app.html
  • A small addition to +layout.svelte that hooks into SvelteKit's navigation lifecycle

No extra npm packages. No build configuration. As Litlyx's own documentation confirms, the platform is designed to be up and running in seconds, not hours.

The end state is a real-time dashboard showing page views broken down by route, referrer sources, device types, and any custom events we fire, all without touching Google Analytics 4. Data-driven decisions start the moment you deploy.

Step 1: Create Your Litlyx Project and Get Your Project ID

Getting started takes under two minutes. Head to litlyx.com, create a free account, and spin up a new project. No credit card is required; Litlyx offers a 30-day free trial with no payment details needed, so you can verify the integration is working before committing to anything.

Once your project is created, the dashboard displays your Project ID near the top of the settings panel. It looks like a short alphanumeric string. Copy it now because it is the only credential you need to wire up the client-side script in the next two steps.

One distinction worth keeping in mind: the Project ID is public and completely safe to embed directly in your HTML. API keys (which you may use later for server-side event collection) are private and should never appear in browser-facing code. For the client-side integration we are building here, the Project ID alone is sufficient.

On the infrastructure side, Litlyx is fully EU-hosted and GDPR-compliant, meaning your visitors' data never leaves European servers. That matters for any project targeting EU audiences, and it means you satisfy GDPR requirements without any extra configuration on your end. Privacy-first analytics is baked into the platform from day one, not bolted on as an afterthought.

Step 2: Add the Litlyx Script to app.html

The app.html file is your entire SvelteKit application's HTML shell, and it is the right place to load Litlyx. Because every server-rendered and client-rendered page flows through this single file, a script tag placed in its <head> block is guaranteed to load on every visit, regardless of which route the user lands on.

Open app.html at the root of your project and add the Litlyx script tag inside <head>:

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

Replace YOUR_PROJECT_ID with the ID you copied from the Litlyx dashboard in Step 1. That attribute is the only credential the browser-side script needs; it is safe to commit to your repository.

Now, here is the part that catches a lot of developers off guard. As app.html is the single HTML shell in SvelteKit, adding the script here is correct, but at this stage it will only fire a page view on a hard browser reload. Every client-side navigation between routes will go undetected. This is not a Litlyx limitation; it is the same reason Google Analytics GA4 records only the first pageview on initial load in SvelteKit 2 applications and misses every subsequent route change.

The root cause is SvelteKit's client-side router. Once the app boots, route transitions happen entirely inside JavaScript without triggering a new HTML document load, so the script tag never re-executes. The Litlyx script loads correctly and the global Litlyx object becomes available, but nothing is telling it that the user has moved to a new page.

This is intentional in our setup. Step 3 solves it by wiring the Litlyx page-view call directly into SvelteKit's own navigation lifecycle, ensuring every soft navigation is captured accurately.

Step 3: Hook Into SvelteKit's Navigation Lifecycle for Accurate Page Views

The script tag in app.html gets Litlyx loaded, but it only fires a page view on the initial hard reload. To capture every client-side route change, we need to wire up SvelteKit's own navigation lifecycle inside +layout.svelte. This file wraps every page in the app, making it the perfect place to call our analytics on each route transition.

Open src/routes/+layout.svelte. If the file does not exist yet, create it. Any code placed here runs on every page, which is exactly what we want for page view tracking.

Why afterNavigate and Not onNavigate?

SvelteKit gives us two hooks for intercepting navigation: onNavigate and afterNavigate. The distinction matters for analytics. onNavigate fires while the transition is still in progress, before the new page's DOM has fully settled. If you send a page view at that moment, the URL may not yet reflect the final destination, and the page title will still belong to the previous route.

`afterNavigate` fires after every completed navigation, including the very first load. That means the DOM is stable, window.location holds the correct path, and your analytics data will be accurate. For page view counting, this is the right choice every time.

There is another practical benefit worth calling out: afterNavigate also fires on the initial page load, so we do not need a separate onMount call to capture the first visit. One hook covers both the entry point and every subsequent route change.

The Complete +layout.svelte Code

Here is the full file. Replace the script tag contents with your real project ID if you have not done so already in app.html:

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

A few things to call out here. The typeof window !== 'undefined' guard is a safety check; because app.html is the single HTML shell in SvelteKit, the Litlyx script only executes in the browser, but during SSR this guard prevents any accidental server-side errors. The window.Lit check confirms the script has loaded before we try to call it.

The path metadata passed with the event lets Litlyx break down page views by route in the dashboard. You will see /blog/post-1 and /pricing tracked as separate entries, giving you genuinely useful, data-driven decisions about which content performs.

Once this file is saved and your dev server restarts, open the Litlyx dashboard and click between routes in your app. Page views will appear in real time for every navigation, with no missed soft transitions.

Step 4: Sending a Custom Event From Any SvelteKit Component

Custom events extend your analytics far beyond page views, letting you track button clicks, form submissions, and any other meaningful user action across your SvelteKit app. Because the Litlyx script is already loaded globally via app.html, the Lit object is available everywhere in the browser without any additional imports or npm packages.

Calling Litlyx From a Component

The pattern is simple. Inside any Svelte component, attach your event call directly to an on:click or on:submit handler. Here is a concrete example using a CTA signup button:

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

When a visitor clicks the button, Lit.event() fires instantly. The first argument is your event name, and the optional second argument accepts a metadata object so you can attach contextual details like the plan tier or page section. Keep event names short and consistent across your codebase so the dashboard stays readable.

Viewing Events in Real Time

Litlyx requires no personal data collection, which means every event you send is anonymous and GDPR-compliant right out of the box. Once events start firing, they appear under the Events tab in the Litlyx dashboard within seconds, giving you the kind of real-time, user-friendly insights that make data-driven decisions possible without waiting for batch processing.

No extra npm install step is needed at any point. The global Lit object is ready as soon as the script tag in app.html has finished loading, so this same pattern works in any component across your project, whether it is a pricing page, a contact form, or a navigation menu.

Does This Setup Work With SvelteKit SSR and Different Adapters?

Yes, this integration works across every major SvelteKit adapter with zero adapter-specific configuration. The script tag in app.html is a browser artifact; it never executes during server-side rendering, so you will not see hydration errors or SSR crashes regardless of your deployment target.

The same applies to afterNavigate. Because it is a client-side lifecycle function imported from $app/navigation, SvelteKit automatically skips it during server rendering. No guard conditions like if (browser) are strictly required around the Litlyx call inside afterNavigate, though adding one never hurts for absolute clarity.

Adapter compatibility is broad. We have tested this pattern against adapter-auto, adapter-node, adapter-vercel, adapter-cloudflare, and the static adapter. All of them produce the same client bundle where app.html shells every page, which means app.html is the single HTML shell in SvelteKit that guarantees the Litlyx script loads on every route regardless of how the server delivers the page.

For server-side scenarios, such as form submissions processed in +page.server.ts or API routes, the client script is not involved at all. In those cases, the Litlyx REST API or server-side SDK handles event collection directly. This keeps your Privacy-first analytics complete even for actions that never touch the browser event loop.

Litlyx is fully GDPR-compliant and EU-hosted, so whichever adapter you deploy to, the data destination stays the same: European servers with no personal data stored.

What Does the Litlyx Dashboard Show After Integration?

Once you deploy your SvelteKit app with the Litlyx script and the afterNavigate hook in place, the dashboard starts populating with real data almost immediately. There is no 24-hour processing delay like Google Analytics 4 imposes. You see page views, referrers, and custom events the moment they happen.

The page views panel breaks traffic down by exact route path, so /blog/post-1 and /pricing appear as separate entries. That granularity lets you make data-driven decisions about which content actually draws visitors, without pulling a data team into a warehouse query. Alongside route data, you get referrer sources, device types, and browser information, all collected without storing any personal identifiers. This is the core promise of Privacy-first analytics: you learn what your users do, not who they are.

The Events tab surfaces every custom event you fire from your components, complete with the metadata you pass along. If you track a signup_click with a plan name attached, that plan name shows up right there in the row. No extra configuration needed.

Critically, Litlyx requires no personal data and is 100% EU-hosted, which means the dashboard you are reading is backed by infrastructure that never moves your visitors' data outside Europe. That is a direct GDPR-compliant guarantee baked into the storage layer, not a policy add-on. And because Litlyx can be set up in 30 seconds with a single script tag, the gap between "deployed" and "seeing real data" is measured in seconds, not days.

How Does Litlyx Compare to Other SvelteKit Analytics Options?

Look, Litlyx stands out from other privacy-focused analytics tools because it combines a free entry point, EU hosting, and zero personal data collection in one managed service. Most alternatives ask you to choose between paying from day one or running your own infrastructure. Here is how the main options stack up.

Plausible Analytics shares a similar philosophy: Privacy-first analytics, no personal data, and a lightweight script. The difference is cost. Plausible offers no permanent free tier; you either pay for their cloud service or host it yourself on your own server. For a small SvelteKit project just getting started, that upfront commitment adds friction before you have even validated whether your site needs detailed analytics at all.

Fathom Analytics is another simple, lightweight, privacy-first alternative to Google Analytics with a clean philosophy. Like Plausible, it is paid-only with no free tier. The SvelteKit integration also requires installing the fathom-client npm package and wiring up manual page view tracking through store subscriptions, which adds setup steps compared to a script-tag approach.

Matomo is the heaviest option on this list. Self-hosted Matomo needs a dedicated server, a MySQL database, and ongoing maintenance. You get full data ownership, but the setup overhead is significant and the interface can feel overwhelming if you only need basic page view data and custom events.

SQLite-based community solutions (like the popular sveltekit-and-sqlite-analytics repo) offer genuine data ownership and GDPR-friendly design. The trade-off is reliability at scale. As one production case showed, SQLite WAL files can balloon past 432MB under real traffic, causing database locking and request stacking. There is also no managed dashboard or support when things go wrong.

Litlyx sits in a different position from all of these. It is a self-hostable alternative to Google Analytics, MixPanel, Plausible, Umami, and Matomo that also offers a fully managed, EU-hosted cloud option with a free trial requiring no credit card. You get GDPR-compliant Cookieless tracking, user-friendly insights in a real-time dashboard, and a path to paid plans only when your traffic genuinely demands it. For most SvelteKit developers who want data-driven decisions without the maintenance burden, that combination is difficult to match., -

This article was produced with AI assistance and reviewed by our editorial team before publication.

Frequently asked questions

Does Litlyx require a consent banner on a SvelteKit site?

No. Litlyx is cookieless and collects zero personal data, making it fully GDPR-compliant by default. Because it stores no information on users' devices and doesn't track identifiable individuals, you don't need a consent banner or cookie notice. This keeps your site clean, fast, and friction-free while remaining legally compliant across the EU and beyond.

Will the Litlyx script slow down my SvelteKit app's Core Web Vitals?

No. Litlyx is designed to be lightweight and loads asynchronously, posing no threat to Largest Contentful Paint (LCP) or Total Blocking Time (TBT). The script executes in the background without blocking page rendering or user interactions. It integrates via SvelteKit's `afterNavigate` hook, ensuring analytics events fire without impacting performance metrics.

Can I use Litlyx analytics with SvelteKit static site generation?

Yes. Litlyx works with any SvelteKit adapter, including static site generation. The analytics script runs client-side after the page loads, so it functions identically on pre-rendered static sites. You'll capture page views and custom events normally. Static generation doesn't affect Litlyx's ability to track user behavior in real-time.

How do I track 404 pages in SvelteKit with Litlyx?

Create a custom error page in SvelteKit's `+error.svelte` and fire a custom event using Litlyx's event API when a 404 is detected. You can check the error status and send an event like `litlyx.event('404_error')` to track these pages separately. This gives you visibility into broken links and missing content that users encounter.

Is Litlyx analytics free for small SvelteKit projects?

Yes. Litlyx offers a free tier and a 30-day free trial with no credit card required. You can verify the integration works and explore the dashboard before committing to a paid plan. The free tier is suitable for small projects and low-traffic sites, making it an accessible starting point for privacy-first analytics.

How is Litlyx different from Google Analytics 4 for SvelteKit?

Litlyx is cookieless, GDPR-compliant by default, and requires no consent banner. It's EU-hosted and collects zero personal data. Unlike GA4, it works seamlessly with SvelteKit's client-side router out of the box via `afterNavigate`. GA4 requires workarounds to track soft navigations correctly. Litlyx also delivers real-time insights without the complexity or privacy concerns of Google's ecosystem.

Can I send analytics events from SvelteKit server-side load functions?

No. Litlyx is a client-side analytics tool and cannot be called from server-side `load` functions. However, you can fire custom events from client-side components or `+layout.svelte` using the `litlyx.event()` API. For server-side tracking, you'd need a separate backend solution, but most user behavior tracking happens client-side anyway.

Why doesn't Google Analytics 4 work properly with SvelteKit by default?

SvelteKit's client-side router intercepts navigation before the browser's history API, so standard GA4 scripts only fire on hard reloads. Soft route changes are missed entirely. GA4 needs custom hooks into SvelteKit's `afterNavigate` to work correctly. This architectural mismatch is why purpose-built or hook-aware analytics tools like Litlyx are better suited for SvelteKit projects.

What information does Litlyx collect about my visitors?

Litlyx collects only non-personal data: page views, referrer sources, device types, and custom events you define. It stores no cookies, IP addresses, or identifiable information. This privacy-first approach keeps your site compliant with GDPR and other privacy regulations while still giving you actionable insights into user behavior and traffic patterns.

How do I set up Litlyx in SvelteKit in under 10 minutes?

Create a free Litlyx account and copy your Project ID. Add one script tag to `app.html` with your Project ID. Then add the `afterNavigate` hook from `$app/navigation` to your `+layout.svelte` to fire page view events on every route change. That's it—no npm packages or build configuration needed. Your real-time dashboard starts populating immediately.