Fathom Analytics Gatsby Configuration

3 minutes to read

Fathom Analytics, a great tool to use for your site analytics without the compromise of giving your visitors data to Google.

I’ve written about How to Track Custom Events with Fathom in the past but since then Fathom have changed their tracking/embed code, which means the config is slightly different.


With the new embed code there’s a guide on how to use the code with Gatsby on Fathom’s blog. It involves modifying the Gatsby html.js file which I’m not too keen on doing, although it works fine, it’s not recommended.

I’ve gone with using React Helmet to add the embed code to the head of my Gatsby projects.

Add it as high up in the React component tree as possible. In my case the way I do it is with the Gatsby wrapPageelEment API which I use in a module that’s shared between gatsby-browser.js and gatsby-ssr.js.

There’s a Plugin for That

There’s also a plugin available, you can configure gatsby-plugin-fathom which will take the same details, a site id and a custom domain but as far as I can tell it’s still using the previous version of the embed code.

The new embed code is less verbose and offers some handy options like enableTrackingForMe and blockTrackingForMe.

Here’s that same Fathom tracking from the Fathom blog guide, but I’m adding it to the head of the site with React Helmet instead of using the html.js file.

export const wrapPageElement = ({ element }) => (
<MDXProvider components={components}>

Track Events

Because the new tracking code is a tiny bit less verbose I’ve had to slightly modify the React Context Provider to accommodate.

import React, { createContext, useContext } from 'react'
const AnalyticsContext = createContext({})
export const AnalyticsProvider = ({ children }) => {
const logClicks = goalId => {
window.fathom.trackGoal(goalId, 0)
return (
<AnalyticsContext.Provider value={logClicks}>
export const useAnalytics = () => {
return useContext(AnalyticsContext)

To consume the event tracking lower in the tree either use it with a hardcoded goalId or pass it in as a variable, here’s how I do it for nav items.

export const NavItems = () => {
const fa = useAnalytics()
return (
<nav aria-label={`page navigation`}>
onClick={() => fa('GH6DDCV6')}
onClick={() => fa('HJAW5F8H')}

A click event passing in the goalId there’s also the option to pass a variable.

export const A = props => {
const fa = useAnalytics()
const containsGoalId = props.href?.includes(`goalId`)
const [goalId, setGoalId] = useState(``)
const [newHref, setNewHref] = useState(``)
useEffect(() => {
if (containsGoalId) {
const url = new URL(props.href)
}, [containsGoalId, props.href])
const onClick = () => {
if (goalId) {
fa(goalId, 0)
return (
href={containsGoalId ? newHref : props.href}

I’ve written before on how to Add Analytics Tracking Links to your Markdown this still stands apart from there’s no need to include quotes ("") around the goalId.

a cheeky butt

Sign up for the newsletter

Want to keep up to date with what I'm working on?

Important dev related content, directly to your inbox (for free).

I care about the protection of your data. Read my Privacy Policy.