Add Analytics Tracking Links to your Markdown
I'm talking Fathom Analytics again, this time about tracking link clicks in my Markdown.
I have written about how to track custom events with Fathom previously and this is really an extension to that post.
If you would like to try Fathom and get a £10 discount on your first invoice check my affiliate link.
This situation is specific to using MDX and the MDXProvider as it gives the ability to override rendering of links.
The problem 🤔
I'd like to add a Fathom goal to a link in my Markdown, to do this I'll need to get the goal ID I've created in Fathom to the link so that when it's clicked it's logged with Fathom.
So I can add an onClick
event to the a
tag using the MDXProvider
and pass that ID to the analytics provider.
The solution 💡
Ok, so I need a way to add a prop to a specific link that contains the goal ID for Fathom.
Using a made up attribute added to the markup for the goal ID I can
pick out the ID and pass it to the analytics provider from the A
component I'm using to override the links in the Markdown.
1export const A = props => {2 const fa = useAnalytics()3 return (4 <a5 {...props}6 id={props.id}7 onClick={() => fa(props.goal)}8 target="_blank"9 rel="noopener noreferrer"10 >11 {props.children}12 </a>13 )14}
So the Markdown will look something like this:
1# My awesome Markdown23Fathom Analytics recently added a feature for4<a href="https://usefathom.com/blog/bypass-adblockers" goal="IBQBRDPP">custom5domains</a> with their service.
So, job done right?
Wellllll....
No.
The other problem (for me anyway) 😧
I spend a lot of my time in Markdown files and I rarely use inline links. With an inline Markdown link the link from that last example it would look something like this:
1# My awesome Markdown23Fathom Analytics recently added a feature for4[custom domains](https://usefathom.com/blog/bypass-adblockers) with5their service.
Doesn't read great does it?
When there is a lot of prose (text) it can be difficult to read when there are a lot of links in there.
I prefer to use the link text and reference it at the bottom of my document, like this:
1# My awesome Markdown23Fathom Analytics recently added a feature for [custom domains] with4their service.56<!-- Links -->78[custom domains]: https://usefathom.com/blog/bypass-adblockers
The other solution 🤯
So, I'd prefer to have the goal ID in the link but not cluttering up
my beautifully crafted Markdown with a
tags everywhere. 😁
How do I do that then?
The way I worked out how to do it was to use a URL parameter and
intercept it in the A
component.
In the Markdown I add the goal ID to the URL, on line 9:
1# My awesome Markdown23Fathom Analytics recently added a feature for [custom domains] with4their service.56<!-- Links -->78[custom domains]:9 https://usefathom.com/blog/bypass-adblockers?goalId="IBQBRDPP"
This way the structure of the Markdown is unchanged making a much nicer writing experience.
How to use the goal ID from the URL parameter?
First up I used an onClick
handler to pull out the goalId
for the
analytics provider.
Using the URL(props.href).searchParams
means that I can pull out the
goalId
using the .get
function.
1export const A = props => {2 const fa = useAnalytics()3 const onClick = () => {4 if (props.href.includes(`goalId`)) {5 const params = new URL(props.href).searchParams6 fa(params.get(`goalId`))7 }8 }910 return (11 <a {...props} onClick={onClick}>12 {props.children}13 </a>14 )15}
The only thing with this was that the goalId
would still be in the
URL.
I didn't really like the way this looked, especially if someone was going to share that link after clicking it.
So reading into the URL API a bit more and reading up on some StackOverflow posts I found that I could delete the parameter after using it.
In the next block of code here, on line 3, I'm checking if the
props.href
contains a goalId
parameter.
I can then manipulate the props.href
in useEffect
and setting the
goalId
in state first on line 10.
Then I can delete the goalId
from the url
on line 11.
The props have been changed now so I'll need to provide the new href
to the a
tag in the props, on line 25.
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(``)67 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])1516 const onClick = () => {17 if (goalId) {18 fa(goalId)19 }20 }2122 return (23 <a24 {...props}25 href={containsGoalId ? newHref : props.href}26 onClick={onClick}27 >28 {props.children}29 </a>30 )31}
Now clicking the link will only call the analytics provider when
there's a goal ID in the href
passed to the component in the props.
Here's a video 📺
In this video detail what I've been writing about.
Resources 📑
These resources helped me along the way.