Support home / Integrations

SvelteKit

Fathom Analytics works great with SvelteKit. Since SvelteKit is a single-page application framework, you’ll want to track page views as users navigate between routes. A huge thank you to Rick Cogley of eSolia for contributing the Svelte 5 update to this guide.

Setting up Fathom in SvelteKit

  1. Add the Fathom script to your app.html file (located in the src folder). Add it just before the closing </head> tag:
<script src="https://cdn.usefathom.com/script.js" data-site="YOUR-SITE-ID" data-spa="auto" defer></script>

Note: Replace `YOUR-SITE-ID` with your actual Fathom site ID. You can find this in your Fathom site settings.

The data-spa="auto" attribute ensures Fathom properly tracks page views as users navigate between routes in your SvelteKit app.

Alternative: Using fathom-client

If you prefer more control over when and how Fathom loads, you can use the fathom-client package:

  1. Install fathom-client:
npm install fathom-client
  1. Create a layout component that initializes Fathom. In your src/routes/+layout.svelte:

Note: Using Svelte 4? See the Svelte 4 example below.

<script>
  import { onMount } from 'svelte';
  import { page } from '$app/stores';
  import { browser } from '$app/environment';
  import * as Fathom from 'fathom-client';

  let { children } = $props();

  onMount(() => {
    Fathom.load('YOUR-SITE-ID', {
      auto: false
    });
  });

  $effect(() => {
    if (browser) {
      const _pathname = $page.url.pathname;
      Fathom.trackPageview();
    }
  });
</script>

{@render children()}

Tracking events

To track custom events, import and use the trackEvent function:

<script>
  import { trackEvent } from 'fathom-client';

  function handleClick() {
    trackEvent('Button Clicked');
  }
</script>

<button onclick={handleClick}>Click me</button>

For events with monetary values (in cents):

trackEvent('Purchase Completed', { _value: 9900 }); // $99.00

Using Svelte 4?

If your project still uses Svelte 4, use the following layout setup and event syntax instead. The key differences are $: for reactivity (instead of $effect()), <slot /> for child content (instead of {@render children()}), and on:click for events (instead of onclick).

Layout setup (src/routes/+layout.svelte):

<script>
  import { onMount } from 'svelte';
  import { page } from '$app/stores';
  import * as Fathom from 'fathom-client';

  onMount(() => {
    Fathom.load('YOUR-SITE-ID', {
      auto: false
    });
  });

  $: $page.url.pathname, Fathom.trackPageview();
</script>

<slot />

Event tracking:

<script>
  import { trackEvent } from 'fathom-client';

  function handleClick() {
    trackEvent('Button Clicked');
  }
</script>

<button on:click={handleClick}>Click me</button>

Further customization

To learn about all the options we offer, read our advanced documentation here.