Integration GuidesSvelte

SvelteKit

Add Rybbit analytics to your SvelteKit app

SvelteKit renders every page through a single HTML shell at src/app.html, so adding the snippet there loads Rybbit on every route.

Get your tracking snippet

In your Rybbit dashboard, open Site Settings → Tracking Script and copy your snippet. It looks like this:

<script src="https://app.rybbit.io/api/script.js?siteId=YOUR_SITE_ID" defer></script>

YOUR_SITE_ID is the numeric ID of your site. If you self-host Rybbit, app.rybbit.io is the domain of your own instance.

Add the snippet to SvelteKit

Open src/app.html and paste the snippet inside <head>, next to %sveltekit.head%:

src/app.html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%sveltekit.assets%/favicon.png" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <script src="https://app.rybbit.io/api/script.js?siteId=YOUR_SITE_ID" defer></script>
    %sveltekit.head%
  </head>
  <body data-sveltekit-preload-data="hover">
    <div style="display: contents">%sveltekit.body%</div>
  </body>
</html>

Rybbit tracks SvelteKit's client-side navigations as pageviews automatically; no router hook is needed.

Verify installation

Open your live site in a new tab and click through a few pages. Within a few seconds the pageviews appear in the Rybbit dashboard.

If nothing shows up:

  • View the page source and search for script.js?siteId= to confirm the snippet is on the page.
  • Open the browser Network tab and check that script.js returns 200 and that POST requests go to /api/track.
  • Disable ad blockers, or set up a proxy so the script loads from your own domain.
  • See the script troubleshooting guide for other common causes.

Track custom events

Call window.rybbit.event() from any Svelte component. Guard the call with typeof window !== "undefined", since SvelteKit components also run on the server:

src/lib/components/ActionButton.svelte
<script>
  function handleAction() {
    if (typeof window !== "undefined" && window.rybbit) {
      window.rybbit.event("user_action", { component: "ActionButton" });
    }
  }
</script>

<button on:click={handleAction}>Perform action</button>

Troubleshooting

  • Pageviews missing after navigation: automatic route tracking covers SvelteKit's router, so test the default first. If a navigation is still not recorded, trigger it from afterNavigate in your root layout:

    src/routes/+layout.svelte
    <script>
      import { afterNavigate } from "$app/navigation";
    
      afterNavigate(() => {
        if (typeof window !== "undefined" && window.rybbit) {
          window.rybbit.pageview();
        }
      });
    </script>

Next steps

On this page