ScottSpence.com

Scott's Digital Garden.

Fathom Analytics Gatsby Configuration

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.

Install

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.

1export const wrapPageElement = ({ element }) => (
2 <>
3 <Helmet>
4 <script
5 src={`${process.env.GATSBY_FATHOM_TRACKING_URL}/script.js`}
6 spa="auto"
7 site={process.env.GATSBY_FATHOM_TRACKING_ID}
8 defer
9 ></script>
10 </Helmet>
11 <MDXProvider components={components}>
12 <Layout>{element}</Layout>
13 </MDXProvider>
14 </>
15)

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.

1import React, { createContext, useContext } from 'react'
2
3const AnalyticsContext = createContext({})
4
5export const AnalyticsProvider = ({ children }) => {
6 const logClicks = goalId => {
7 window.fathom.trackGoal(goalId, 0)
8 }
9
10 return (
11 <AnalyticsContext.Provider value={logClicks}>
12 {children}
13 </AnalyticsContext.Provider>
14 )
15}
16
17export const useAnalytics = () => {
18 return useContext(AnalyticsContext)
19}

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.

1export const NavItems = () => {
2 const fa = useAnalytics()
3 return (
4 <nav aria-label={`page navigation`}>
5 <NavLink
6 gridArea={`about`}
7 href={`#hi-im-scott`}
8 onClick={() => fa('GH6DDCV6')}
9 >
10 About
11 </NavLink>
12 <NavLink
13 gridArea={`portfolio`}
14 href={`#portfolio`}
15 onClick={() => fa('HJAW5F8H')}
16 >
17 Portfolio
18 </NavLink>
19 ...

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

1export const A = props => {
2 const fa = useAnalytics()
3 const containsGoalId = props.href?.includes(`goalId`)
4 const [goalId, setGoalId] = useState(``)
5 const [newHref, setNewHref] = useState(``)
6
7 useEffect(() => {
8 if (containsGoalId) {
9 const url = new URL(props.href)
10 setGoalId(url.searchParams.get(`goalId`))
11 url.searchParams.delete(`goalId`)
12 setNewHref(url.href)
13 }
14 }, [containsGoalId, props.href])
15
16 const onClick = () => {
17 if (goalId) {
18 fa(goalId, 0)
19 }
20 }
21 return (
22 <StyledA
23 {...props}
24 href={containsGoalId ? newHref : props.href}
25 onClick={onClick}
26 >
27 {props.children}
28 </StyledA>
29 )
30}

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.

Back to Top