Analytics

Analytics

The site uses Analytics library to abstract our analytics events, so they are not specific to a single provider, allowing us swap providers in the future easily if need be.

This library is actively maintained and it’s designed to be easily plugged into most of the available analytics providers.

The setup files can be found in core/libs/analytics and can be reused across multiple apps.

Overview

A custom developed HOC was created to wrap the app and provide the analytics context.

By default this implementation is set up to track:

  • Original source of the user (original referral url and initial page they landed on)
  • Page views that fire on url changes
  • Click events that fire on components that have the data-track attribute defined
  • Idle time and wake up events that fire when the user is idle for a certain amount of time and wakes up (this is disabled by default but activated on passing the trackIdleTimeAndWakeUp property on the schema prop)

Setup

Import the HOC

import { AnalyticsProvider } from "core/libs/analytics"

Wrap your app with the HOC and pass the relevant data on the schema prop

layout.tsx
const App = () => (
  <AnalyticsProvider
    schema={{
      appName: "My App",
      appVersion: "1.0.0",
      trackerProviders: [
        {
          name: "segment",
          appIdentifier: process.env.NEXT_PUBLIC_SEGMENT_WRITE_KEY
        },
        {
          name: "gtm",
          appIdentifier: process.env.NEXT_PUBLIC_GTM_ID
        }
      ]
    }}
  >
    <MyApp />
  </AnalyticsProvider>
)

Types

type SupportedProviders = "segment" | "gtm" | "meta-pixel" | "google-analytics"
 
type TrackerProvider = {
  name: SupportedProviders
  appIdentifier: string
}
 
type AnalyticsProviderProps = {
  schema: {
    appName: string
    appVersion?: string
    trackerProviders?: TrackerProvider[]
    trackIdleTimeAndWakeUp?: {
      timeout: number
    }
  }
  children: ReactNode
}

Usage

Click Events

Pass an identifier to the component you want to track click events.

It’s important to use the data attribute data-track to pass the component identifier as that’s what the library will use to track the click event.

my-page.tsx
<Button data-track="my-page-example-button">Next</Button>
⚠️

The data-track='my-page-example-button' is the one that will tell the library to track the click event on this component, the value is what will be passed as the component identifier.

Test it!

You can test your implementation by running your server, clicking your target component and checking the payload being logged on your console.

Custom Events

Import the useAnalytics hook

import { useAnalytics } from "use-analytics"

Use the hook to track custom events

my-page.tsx
const MyPage = () => {
  const { track } = useAnalytics()
 
  const handleSubmit = () => {
    track({
      "my-form-submission-event-name",
      {
        myCustomProperty: "myCustomValue",
        url: document.URL
      }
    })
  }
 
  return (
    <Form onSubmit={handleSubmit}>
      ...
    </Form>
  )
}

Extending

The library is designed to be easily extendable, so if you need to add more plugins or change the way the library works, you can do so by following the documentation.

Add a custom plugin

To add a new custom plugin for a service that’s not supported by default, you need to create a new file in the plugins folder similar to our custom implementation for the meta pixel:

meta.ts
let fb
let fbLoaded = false
 
type Config = {
  pixelId: string
}
 
export default function facebookPixelPlugin(userConfig: Config) {
  return {
    name: "meta-pixel",
    config: {
      ...userConfig
    },
    initialize: async ({ config }) => {
      const { pixelId } = config
      await import("react-facebook-pixel")
        .then((module) => (fb = module.default))
        .then(() => {
          if (!fbLoaded) {
            fb.init(pixelId, {
              autoConfig: true,
              debug: true
            })
            fbLoaded = true
          }
        })
    },
    page: ({ payload }) => {
      fb.pageView()
    },
    track: ({ payload }) => {
      fb.track(payload.event, payload.properties)
    },
    identify: ({ payload }) => {
      fb.setUserID(payload.userId)
    },
    loaded: () => {
      return fbLoaded
    }
  }
}

Then you can import your plugin in the core/libs/analytics file and add it to the plugins array.

More info on custom plugins can be found here