Fathom Analytics with SvelteKit
In this guide I’ll go through the configuration needed to get set up with Fathom Analytics in a SvelteKit project.
I’ll cover getting set up, tracking goals and creating and using a custom Fathom Domain.
Fathom Analytics is a privacy focused product that I have loved using since 2019 now. I got tired of the confusing Google Analytics dashboard and wanted something simpler to use and to use a product that wasn’t going to sell off the browsing data of my sites visitors like Google does.
If you’re not already signed up you can get a $10 credit by signing up with my referral link. Yes I get a kick back from this, it’s an awesome product and if you’re interested in using it using the link would really help me out.
So, Fathom, digital privacy first. They’re GDPR, CCPA, ePrivacy, PECR compliant. Their business model is selling software, not data. Because of this, Fathom doesn’t require cookie banners.
Enough selling! Let’s get started!
Prerequisites
I’ll presume that you have a basic understanding of using a JavaScript framework like Svelte and are familiar with using the command line (CLI) to get certain tasks done.
So this means you already have a development environment with Node a terminal and a text editor like VS Code installed and ready to go. If you don’t then there are still services like Gitpod, StackBlitz and GitHub Codespaces you can use from a browser.
StackBlitz is bonkers fast and would be my go-to if I was to use one of the mentioned services there!
Create a Fathom site
Before I get into configuring the SvelteKit project I’ll need to
create a new site on Fathom. From my Fathom settings screen in the
sites section I can scroll down to the ‘Create New Site’ section and
enter a site name. I’m calling this one ideal-memory
.
That link is a public Fathom dashboard you can go and check out now if you like.
ℹ️ The site name doesn’t have to correspond with the actual project name but it could get confusing if it doesn’t and you have a lot of sites.
Here’s what the create new site section looks like:
After clicking the ‘Create New Site’ button the embed dialogue will show with the Site ID, take a note of the site ID or copy the embed code:
That’s it for now on the Fathom side of things, I’ll leave this dialogue open and go back to this once I’ve set up the project.
Create the SvelteKit skeleton project
You can integrate Fathom with your current SvelteKit project but I’m going to do this with the SvelteKit skeleton project so you can get an idea of what’s going on here.
I’m going to create the project with the following command, I use
pnpm
but if you’re following along you can use your package manager
of choice (like npm
or yarn
):
pnpm create svelte sveltekit-and-fathom
I’ll choose the following options from the CLI:
✔ Which Svelte app template? › Skeleton project
✔ Add type checking with TypeScript? › Yes, using TypeScript syntax
✔ Add ESLint for code linting? … Yes
✔ Add Prettier for code formatting? … Yes
✔ Add Playwright for browser testing? … Yes
✔ Add Vitest for unit testing? … Yes
I’ll change directory (cd
) into the project and install the
dependencies:
cd sveltekit-and-fathom
pnpm i
Now I can check out the project in VS Code, the file structure looks like this:
sveltekit-and-fathom/
├── src
│ ├── routes
│ │ └── +page.svelte
│ ├── app.d.ts
│ ├── app.html
│ └── index.test.ts
├── static
│ └── favicon.png
├── tests
│ └── test.ts
├── .eslintignore
├── .eslintrc.cjs
├── .gitignore
├── .npmrc
├── .prettierignore
├── .prettierrc
├── README.md
├── package.json
├── playwright.config.ts
├── svelte.config.js
├── tsconfig.json
└── vite.config.ts
Add Fathom details to .env
file
Create a .env
file in the root of the project and add in the Fathom
SiteID
and the Fathom tracking script variables for Svelte to use,
this bash command will do the trick:
touch .env
echo PUBLIC_FATHOM_ID= >> .env
echo PUBLIC_FATHOM_URL= >> .env
Then add the SiteID
and the tracking script to the variables to the
.env
file:
PUBLIC_FATHOM_ID=NYMDTPLM
PUBLIC_FATHOM_URL=https://cdn.usefathom.com/script.js
The reason for using a .env
file if because a lot of ad blockers
will scrape it from places like GitHub, GitLab and Bitbucket and add
it to their block lists.
Install and config Fathom client
To start tracking page views I’ll first need to install
fathom-client
via pnpm
as a dev dependency:
pnpm i -D fathom-client
To start tracking page views the Fathom client will need to be in a place that wraps all the pages in the project.
I’ll use the +layout.svelte
page for this, it will be applied to
every page in the project and can also be used to add styles and
components I want visible on each page.
Currently there’s only one page in the routes
directory for the
+page.svelte
file. I’ll add in an about
and a services
routes
for some additional pages as well for now.
I’ll do this with a couple of bash commands in the terminal:
mkdir -p src/routes/{about,services}
touch src/routes/{+layout.svelte,about/+page.svelte,services/+page.svelte}
After running that I have a couple of new files in my src/routes
directory:
sveltekit-and-fathom/
└── routes
├── about
│ └── +page.svelte
├── services
│ └── +page.svelte
└── +layout.svelte
The about
and services
files are so I can check the route change
in my Fathom dashboard once I’ve configured the client, which I’ll do
now.
In the +layout.svelte
file I’ll add this:
<script lang="ts">
import { browser } from '$app/environment'
import { page } from '$app/stores'
import {
PUBLIC_FATHOM_ID,
PUBLIC_FATHOM_URL,
} from '$env/static/public'
import * as Fathom from 'fathom-client'
import { onMount } from 'svelte'
onMount(async () => {
Fathom.load(PUBLIC_FATHOM_ID, {
url: PUBLIC_FATHOM_URL,
})
})
$: $page.url.pathname, browser && Fathom.trackPageview()
</script>
<ul>
<a href="/">Home</a>
<a href="/about">About</a>
<a href="/services">Services</a>
</ul>
<slot />
Let’s break down what’s going on here, importing the browser
indicates if the project is running in the browser or not, this will
return a Boolean (true
, false
) value. You can read more about
$app-environment
on the SvelteKit documentation.
Using page
for the $page.url.pathname
this is the route for the
current page that has been loaded. You can read more about
$app/stores
on the SvelteKit documentation. The $
is so that I
can subscribe to changes in that (page
) store.
onMount
is used to run after the +layout.svelte
page has loaded,
that’s when I’m running the Fathom client and passing in my Fathom
site ID.
If you’re not familiar with Svelte the the $:
might look a bit
funky, you can learn more about it on the Svelte
Reactivity/Declarations tutorial. The &&
is a short circuit
evaluation to if there’s no browser
then Fathom.trackPageview()
wont run.
ℹ️ As a side note here I will be using the Fathom SiteID
and script
URL in an .env
file so that it’s not visible when I commit the code
to GitHub.
If you’re using the environment variables you can replace the
hard-coded strings for the id
and url
with the variables, like
this:
onMount(async () => {
Fathom.load(PUBLIC_FATHOM_ID, {
url: PUBLIC_FATHOM_URL,
})
})
Ok, with that explanation out of the way time to see if the client is working.
Validate the project is working on Fathom
As I noted earlier, a lot of ad blockers will have the Fathom tracking script added to their block lists. If you’re using and ad blocker and you want to validate it’s working then you will probably want to use a private browser window without the ad blocker enabled.
Don’t worry you can bypass all ad blockers by setting up a custom domain with Fathom, more on that later though! For now just use a private browser window to validate it’s working.
pnpm run dev
Going over to my Fathom dashboard now I can check out that the
client is working as expected, here I’ve gone to the services
page
and the page view is being tracked.
That’s it! I’ve now added Fathom tracking to my project.
Tracking goals (clicks)
Ok, now I want to see when someone has clicked a certain CTA or link.
If I go to the Fathom dashboard for the site and scroll down to the bottom of the page I ca see the events section.
If I click on the Add event
button there I’ll get a dialogue to
create a new event! I already have a few configured, I’ll add in one
for a generic Button Click
. Then click the ‘Create event’ button.
From here all I’ll really need to concern myself with is the ‘Event code’ I’ll take a note of that and use it a button on the index page.
So the site has no content right now! I know, I’ll just go and stick
this button in the src/routes/+page.svelte
file for now.
<script lang="ts">
import { trackGoal } from 'fathom-client'
</script>
<h1>Welcome to SvelteKit</h1>
<p>
Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the
documentation
</p>
<button on:click={() => trackGoal(`H1CCQXUL`, 100)}>
Don't Click This Button!!
</button>
So, what I’m doing here is importing the trackGoal
function from
fathom-client
then using that in the on:click
event handler for
the button.
Now going over to the index page of my SvelteKit project I can see the button click it then go back to the Fathom dashboard and see that the event has been recorded.
If the event has a monetary value you can also pass in the value per click.
<button on:click={() => trackGoal(`H1CCQXUL`, 100)}>
Don't Click This Button!!
</button>
So in this case each click is worth $1.
I can also use it on links, here I’ve added the trackGoal
to the
home page link.
<script lang="ts">
import { browser } from '$app/environment'
import { page } from '$app/stores'
import {
PUBLIC_FATHOM_ID,
PUBLIC_FATHOM_URL,
} from '$env/static/public'
import * as Fathom from 'fathom-client'
import { onMount } from 'svelte'
onMount(async () => {
Fathom.load(PUBLIC_FATHOM_ID, {
url: PUBLIC_FATHOM_URL,
})
})
$: $page.url.pathname, browser && Fathom.trackPageview()
</script>
<ul>
<a href="/" on:click={() => Fathom.trackGoal(`KWOYX0PK`)}>Home</a>
<a href="/about">About</a>
<a href="/services">Services</a>
</ul>
<slot />
Using a custom domain
So last up I want to use a custom domain for my project!
Fathom use dynamic CNAME values which means that ad blockers can’t search for a specific domain to block.
To read more about this you can read the linked docs from Fathom on why they do this and a great run-down of how to set up a custom domain.
If I go back to the settings for the site (ideal-memory
) I’ve been
configuring on Fathom there’s an option to add a domain!
Domain providers (much like styling) can be a personal choice, I use Namecheap, you can use whichever you please. I’ve been with Namecheap for many years with no issues from me. You experience may vary.
For this site I have gone and bought the ideal-memory.com
domain.
I’ll be configuring this with Vercel. If you aren’t using vercel or
Namecheap some of the steps here may be different. The main concept
will be the same, which is add the provided CNAME value to your
domain.
I’ll add my domain and click the ‘Add domain’ button then in the dialogue which pops up after that I’ll need to take a note of the ‘CNAME’ and the value.
I’ll take a note of the values here for use later.
CNAME: van-protected
Value: ecstatic-thirtyone.b-cdn.net
So presuming my site is already deployed to Vercel (which it’s not right now), I push it to Vercel from the terminal with the Vercel CLI and a simple command from the root of my project:
vc
This guides me though deploying the project to Vercel. I’ve accepted the defaults (hit enter) for each prompt:
Vercel CLI 23.1.2
? Set up and deploy “~/repos/sveltekit-and-fathom”? [Y/n] y
? Which scope do you want to deploy to? Scott Spence
? Link to existing project? [y/N] n
? What’s your project’s name? sveltekit-and-fathom
? In which directory is your code located? ./
Auto-detected Project Settings (SvelteKit):
- Build Command: svelte-kit build
- Output Directory: public
- Development Command: svelte-kit dev --port $PORT
? Want to override the settings? [y/N] n
With that added to Vercel I can click on the Inspect
link in the
console to go to my Vercel dashboard! As this project is on GitHub I
can also connect it from Vercel so that any changes that are made to
the project will be deployed automatically to Vercel on a git push!
I’ll click on the ‘Connect Git Repository’ button and link it to my GitHub project.
Now that’s connected I can go to the ‘Domains’ section and add in my domain.
What I’ll need to do now is add the Vercel nameservers to the domain on Namecheap!
I’ll get a confirmation on Vercel once the’re validated then I can access the project on the domain.
I’ll need to add the CNAME record to Vercel now, I can do that with the CLI.
vc dns add ideal-memory.com van-protected CNAME ecstatic-thirtyone.b-cdn.net
Going back to the Fathom dashboard I can now click on the ‘I have created the DNS record’ button, then it’s just a case of waiting for the record to be validated. This can take a while, with Namecheap it’s always been super fast.
Once it’s been validated I’ll get my new embed code
With the new domain I can replace the PUBLIC_FATHOM_URL
in the
.env
file:
PUBLIC_FATHOM_ID=NYMDTPLM
-PUBLIC_FATHOM_URL=https://cdn.usefathom.com/script.js
+PUBLIC_FATHOM_URL=https://ecstatic-thirtyone.ideal-memory.com/script.js
One thing to note here is that I’ll need to add the .env
variables
to the ‘Environment variables’ section of the project settings on
Vercel.
Rather than do a Git push I’ll just run the vc
command again to push
up the latest changes with the new custom PUBLIC_FATHOM_URL
.
Now if I use a browser with an ad blocker enabled and go to
ideal-memory.com
and select some routes and click the button I added
I can see the values on the Fathom dashboard get updated!
Wrap up
That’s it! I’ve now added Fathom to my SvelteKit project to track page changes and events. Set up a custom domain for it and it tracks details with an ad blocker enabled!
If you want to check out an example of this setup check out the GitHub repo!
Year to date analytics for this post