Last active
July 1, 2019 15:45
-
-
Save xdmorgan/b94de9123503b86de13d02a2f00c734a to your computer and use it in GitHub Desktop.
React Hook / Google gtag event tracking / TypeScript / SSR-Friendly (tested with Gatsby)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
"Static Tracking" for values that will not change | |
```js | |
const [onTrack] = useStaticTracking({ category: 'Home Page', label: "Register" }) | |
return <Button onClick={onTrack} /> | |
``` | |
"Dynamic Tracking" for values that will change between calls or vary in a loop | |
```js | |
const [onTrack] = useDynamicTracking({ | |
action: 'View Profile', | |
category: 'Team Members', | |
}) | |
// shared action and category with individual labels | |
people.map(person => <Button onClick={ () => onTrack({ label: person.name }) } /> ) | |
``` | |
Google gtag.js event tracking documentation: | |
https://developers.google.com/analytics/devguides/collection/gtagjs/events | |
*/ | |
type obj = { [key: string]: string } | |
interface EventTrackingConfig { | |
command?: string | |
action?: string | |
category?: string | |
label?: string | |
value?: string | |
custom_options?: obj | |
} | |
type StaticTracker = () => any | |
type StaticSettings = { | |
debug: boolean | |
args: [string, string, obj] | |
} | |
type DynamicTracker = (config: EventTrackingConfig) => any | |
type DynamicSettings = { debug: boolean; shared: any } | |
// empty function for ssr case | |
const noop = () => {} | |
// create event tracking signature and return with the onClick | |
// handler from data provided to the hook at creation time | |
export function useStaticTracking( | |
config = {}, | |
debug = false | |
): [StaticTracker, StaticSettings] { | |
const args = toArguments(config) | |
const settings = { debug, args } | |
// handle debug (console log), missing gtag global, and SSR case (no window) | |
const fn = debug ? console.info : canReportEvents() ? window.gtag : noop | |
return [() => fn(...args), settings] | |
} | |
// return event tracking function but handle config at call | |
// time for dynamic values that may change between calls | |
export function useDynamicTracking( | |
shared = {}, | |
debug = false | |
): [DynamicTracker, DynamicSettings] { | |
const settings = { debug, shared } | |
// handle debug (console log), missing gtag global, and SSR case (no window) | |
const fn = debug ? console.info : canReportEvents() ? window.gtag : noop | |
return [current => fn(...toArguments({ ...shared, ...current })), settings] | |
} | |
// bail if ssr (no window) or gtag unavailble (localhost or misconfigured) | |
function canReportEvents() { | |
return typeof window !== 'undefined' && typeof window.gtag !== 'undefined' | |
} | |
// convert from config object to function signature | |
function toArguments({ | |
command = 'event', | |
action = 'click', | |
category = undefined, | |
label = undefined, | |
value = undefined, | |
custom_options = undefined, | |
}: EventTrackingConfig): [string, string, obj] { | |
// should any options object be provided? | |
const empty = !(category || label || value || custom_options) | |
// create options object based on settings provided | |
const options = empty | |
? undefined | |
: { | |
...(category ? { event_category: category } : {}), | |
...(label ? { event_label: label } : {}), | |
...(value ? { value } : {}), | |
...custom_options, | |
} | |
return [command, action, options] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
custom_options
looks like a spread error 🤔