DEV Community

Cover image for How to Integrate Analytics into a React/NextJS Application
Radzion Chachura
Radzion Chachura

Posted on • Originally published at radzion.com

1

How to Integrate Analytics into a React/NextJS Application

🐙 GitHub

Integrating Analytics into a React Application

In this article, we'll explore a reusable method for integrating analytics into a React application. We'll use Amplitude analytics within a Next.js app as our example, but the same principles can be applied to any React app and analytics provider. All the reusable code for this article can be found in the RadzionKit repository.

In our app, we'll use two main functions to handle analytics:

  • setUser - This function sets the user ID for tracking purposes.
  • trackEvent - This function tracks events. It takes the event name and an optional data object, allowing us to pass any additional information about the event we want to track.
import { createContextHook } from "@lib/ui/state/createContextHook"
import { createContext } from "react"

export type AnalyticsContextState = {
  setUser: (id: string) => void
  trackEvent: (name: string, data?: Record<string, any>) => void
}

export const AnalyticsContext = createContext<
  AnalyticsContextState | undefined
>(undefined)

export const useAnalytics = createContextHook(
  AnalyticsContext,
  "AnalyticsContext"
)
Enter fullscreen mode Exit fullscreen mode

Using React Context API for Analytics Integration

We'll use React's context API to provide these functions to our components. The decision to use the context API instead of utility functions will become clearer when we examine the PageVisitTracker component. At Increaser, we use this component to track page visits on both the website and the app. The PageVisitTracker doesn't need to know which analytics tool we're using. It's the responsibility of the app and website projects to wrap the PageVisitTracker in the appropriate context provider.

import { useAnalytics } from "@lib/analytics-ui/AnalyticsContext"
import { useRouter } from "next/router"
import { useEffect } from "react"

export const PageVisitTracker = () => {
  const { pathname } = useRouter()
  const { trackEvent } = useAnalytics()

  useEffect(() => {
    trackEvent("Visit page", { pathname })
  }, [trackEvent, pathname])

  return null
}
Enter fullscreen mode Exit fullscreen mode

Local and Amplitude Analytics Providers

When running the app locally, we don't need to spam our analytics provider with events. For local development, we use the LocalAnalyticsProvider, which simply logs the events to the console.

import { ComponentWithChildrenProps } from "@lib/ui/props"
import { AnalyticsContext, AnalyticsContextState } from "./AnalyticsContext"

const localAnalytics: AnalyticsContextState = {
  setUser: (id) => {
    console.log("Set user for analytics: ", id)
  },
  trackEvent: (name, data) => {
    console.log("Track event: ", name, data)
  },
}

export const LocalAnalyticsProvider = ({
  children,
}: ComponentWithChildrenProps) => {
  return (
    <AnalyticsContext.Provider value={localAnalytics}>
      {children}
    </AnalyticsContext.Provider>
  )
}
Enter fullscreen mode Exit fullscreen mode

Our AmplitudeAnalyticsProvider offers the setUser and trackEvent functions using the Amplitude analytics library. We initialize the Amplitude library with the provided API key when the component mounts.

import { useEffect } from "react"
import * as amplitude from "@amplitude/analytics-browser"
import { AnalyticsContext, AnalyticsContextState } from "./AnalyticsContext"
import { ComponentWithChildrenProps } from "@lib/ui/props"

type AmplitudeAnalyticsProviderProps = ComponentWithChildrenProps & {
  apiKey: string
}

const amplitudeAnalytics: AnalyticsContextState = {
  setUser: (id) => {
    amplitude.setUserId(id)
  },
  trackEvent: (name, data) => {
    amplitude.track(name, data)
  },
}

export const AmplitudeAnalyticsProvider = ({
  apiKey,
  children,
}: AmplitudeAnalyticsProviderProps) => {
  useEffect(() => {
    amplitude.init(apiKey)
  }, [apiKey])

  return (
    <AnalyticsContext.Provider value={amplitudeAnalytics}>
      {children}
    </AnalyticsContext.Provider>
  )
}
Enter fullscreen mode Exit fullscreen mode

Integrating the Analytics Provider into a Next.js App

Now, let's see how we put it all together within our Next.js app. First, we create an AnalyticsProvider component that checks if the app is running in production. If it is, we use the AmplitudeAnalyticsProvider with the API key taken from environment variables. Otherwise, we use the LocalAnalyticsProvider.

import { shouldBeDefined } from "@lib/utils/assert/shouldBeDefined"
import { ComponentWithChildrenProps } from "@lib/ui/props"
import { AmplitudeAnalyticsProvider } from "@lib/analytics-ui/AmplitudeAnalyticsProvider"
import { LocalAnalyticsProvider } from "@lib/analytics-ui/LocalAnalyticsProvider"

export const AnalyticsProvider = ({ children }: ComponentWithChildrenProps) => {
  if (process.env.NODE_ENV === "production") {
    return (
      <AmplitudeAnalyticsProvider
        apiKey={shouldBeDefined(process.env.NEXT_PUBLIC_AMPLITUDE_API_KEY)}
      >
        {children}
      </AmplitudeAnalyticsProvider>
    )
  }

  return <LocalAnalyticsProvider>{children}</LocalAnalyticsProvider>
}
Enter fullscreen mode Exit fullscreen mode

Finally in the _app.tsx file, we wrap our app with the AnalyticsProvider component and place the PageVisitTracker component inside it. This way, we can track page visits across the entire app.

import { AnalyticsProvider } from "../analytics/AnalyticsProvider"
import { PageVisitTracker } from "@lib/next-ui/PageVisitTracker"

function MyApp() {
  return (
    <AnalyticsProvider>
      <PageVisitTracker />
      // ...
    </AnalyticsProvider>
  )
}

export default MyApp
Enter fullscreen mode Exit fullscreen mode

Imagine monitoring actually built for developers

Billboard image

Join Vercel, CrowdStrike, and thousands of other teams that trust Checkly to streamline monitor creation and configuration with Monitoring as Code.

Start Monitoring

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Discover a treasure trove of wisdom within this insightful piece, highly respected in the nurturing DEV Community enviroment. Developers, whether novice or expert, are encouraged to participate and add to our shared knowledge basin.

A simple "thank you" can illuminate someone's day. Express your appreciation in the comments section!

On DEV, sharing ideas smoothens our journey and strengthens our community ties. Learn something useful? Offering a quick thanks to the author is deeply appreciated.

Okay