Google Analytics Events with Gatsby and TypeScript
Context
I'm going to show you how I use TypeScript to improve Google
Analytics events tracking. The beauty of using TypeScript is we can use the
enum
type to create discrete options to choose from. This should help us make
our analytics more consistent.
The examples we'll look at involve the Gatsby framework.
npm install gatsby-plugin-google-analytics
Learning how to use Google Analytics or Gatsby is beyond the scope of this article. For a general tutorial on setting up Google Analytics with Gatsby, check out this video by Guiding Digital.
Event Tracking with TypeScript
There are three main properties we want to set when tracking an event.
These are how I think of each event property.
- Category. What type of thing was interacted with?
- Action. How was the thing interacted with?
- Label. Which specific thing was interacted with?
In my project, I create an analytics.ts
to store information about event
tracking.
I like to use the TypeScript enum
for each event property. This lets me have
discrete properties that I can use throughout my site. I find this approach more
maintainable than using ad-hoc strings.
// ❌ Bad
// Ad-hoc strings could lead to inconsistencies in analytics bucketing
trackCustomEvent({
category: 'Newsletter',
action: 'Subscribe',
});
// ✅ Good
// Discrete options to choose makes bucketing analytics more maintainable
trackCustomEvent({
category: AnalyticsCategory.Newsletter,
action: AnalyticsAction.Subscribe,
});
I define the following enum
types to give me a discrete set of options that I
can use throughout my site. With these types, I can create my own custom
AnalyticsEvent
interface to model an event.
export enum AnalyticsCategory {
Themes = 'Themes',
Newsletter = 'Newsletter',
Blogs = 'Blogs',
Feedback = 'Feedback',
Contact = 'Contact',
}
export enum AnalyticsAction {
Click = 'Click',
Subscribe = 'Subscribe',
Switch = 'Switch',
SendEmail = 'Send Email',
Like = 'Liked',
Dislike = 'Dislike',
Dismiss = 'Dismiss',
}
export enum AnalyticsLabel {
Light = 'Light',
Dark = 'Dark',
Green = 'Green',
Blue = 'Blue',
Red = 'Red',
}
export interface AnalyticsEvent {
category: AnalyticsCategory;
action: AnalyticsAction;
label?: AnalyticsLabel | string;
}
I let the label
property also accept a string
because sometimes I need to
label something dynamically.
For example, here I let the label be the page the user was on when they
interacted with some Button
component.
import {useLocation} from '@reach/router';
import {trackCustomEvent} from 'gatsby-plugin-google-analytics';
import {
AnalyticsAction,
AnalyticsCategory,
AnalyticsEvent,
} from '@utils/analytics';
function Button() {
const {pathname} = useLocation();
return (
<button
type="button"
onClick={() => {
trackCustomEvent({
category: AnalayticsCategory.Feedback,
action: AnalyticsAction.SentEmail,
label: pathname,
});
}}
>
Click
</button>
);
}
I also create a thin wrapper over the trackCustomEvent
function exported by
gatsby-plugin-google-analytics
.
The plugin supports TypeScript, but it doesn't support the custom
AnalyticsEvent
interface that I defined.
Making this wrapper lets me use my AnalyticsEvent
type instead of the
CustomEventArgs
interface that is exported by
gatsby-plugin-google-analytics
.
import {trackCustomEvent} from 'gatsby-plugin-google-analytics';
// Thin wrapper to get TypeScript support
export function track(event: AnalyticsEvent) {
trackCustomEvent(event);
}
With that change, we can refactor our Button
component ever so slightly.
import {useLocation} from '@reach/router';
import {
AnalyticsAction,
AnalyticsCategory,
AnalyticsEvent,
track,
} from '@utils/analytics';
function Button() {
const {pathname} = useLocation();
return (
<button
type="button"
onClick={() => {
const event: AnalyticsEvent = {
category: AnalayticsCategory.Feedback,
action: AnalyticsAction.SentEmail,
label: pathname,
};
track(event);
}}
>
Click
</button>
);
}
That's all there is to it. TypeScript makes it easy to choose from a selection of discrete event types. I like this approach because it makes your analytics more consistent and helps you collect better data on how users are interacting with your site.