DEV Community

Cover image for Custom React hook to connect Google Analytics
Jim Raptis
Jim Raptis

Posted on • Updated on • Originally published at jimraptis.com

Custom React hook to connect Google Analytics

Check the full article on my personal blog


TL;DR

We'll create a custom React hook that setups Google Analytics to a CRA app. The React app uses the react-router-dom and react-ga modules.

A quick explanation of what we want to achieve.

Google Analytics is a web analytics service offered by Google that tracks and reports website traffic. They offer a great dashboard and the service is free.

Our goal is to connect the Google Analytics to our React app using some utility functions and a custom React hook that handles the initialization of the ga object.

Installation

We start with the creation of a new React app using create-react-app and npx:

npx create-react-app demo-app
cd demo-app
Enter fullscreen mode Exit fullscreen mode

Then, we install the two dependencies. The react-router-dom library which is the de-facto routing solution in React. and react-ga the official Google Analytics React package:

yarn add react-router-dom react-ga
Enter fullscreen mode Exit fullscreen mode

Or if you're using npm:

npm install --save react-router-dom react-ga
Enter fullscreen mode Exit fullscreen mode

Create the analytics.js file

Our first step is to create the file analytics.js where we're going to create the Google Analytics init function and define two helpers to fire custom events and the pageview one.

We utilize the react-ga's method initialize to set up the Google Analytics with our unique tracking id. You can pass more options to the initialize function but we'll only enable debug logging for the local development mode.

Then we create the two extra helper functions, sendEvent() and sendPageview(), that simply fire a custom event and the pageview one respectively.

import ReactGA from "react-ga"

const TRACKING_ID = "UA-XXXXXXXXX-X"

function init() {
  // Enable debug mode on the local development environment
  const isDev = !process.env.NODE_ENV || process.env.NODE_ENV === "development"
  ReactGA.initialize(TRACKING_ID, { debug: isDev })
}

function sendEvent(payload) {
  ReactGA.event(payload)
}

function sendPageview(path) {
  ReactGA.set({ page: path })
  ReactGA.pageview(path)
}

export default {
  init,
  sendEvent,
  sendPageview,
}
Enter fullscreen mode Exit fullscreen mode

Define the App component

Now we have to create the App component that renders the pages of our app. To keep it simple, I define 3 dummy routes, /, /features, and /signup.

I use BrowserRouter over the pure Router because it ignores the history prop and handles the history object automatically for you.

The Switch component selects the first route that fits the location and renders it. So it renders only one route!

import React from "react"
import { BrowserRouter, Switch, Route } from "react-router-dom"

import Home from "./pages/Home"
import Features from "./pages/Features"
import SignUp from "./pages/SignUp"

function App() {
  return (
    <BrowserRouter>
      <Switch>
        <Route exact path="/">
          <Home />
        </Route>
        <Route exact path="/features">
          <Features />
        </Route>
        <Route exact path="/signup">
          <SignUp />
        </Route>
      </Switch>
    </BrowserRouter>
  )
}

export default App
Enter fullscreen mode Exit fullscreen mode

Build the custom useGoogleAnalytics hook

Since we don't handle history manually (BrowserRouter does this for us), our only option to access the current location object is by using the useLocation hook by react-router-dom.

So, we define two useEffect hooks. The first useEffect simulates the known componentDidMount function and initializes the ga object. The second one listens on every location change and sends the valuable pageview event.

Pretty straightforward, huh?!

import React from "react"
import { useLocation } from "react-router-dom"

import analytics from "./analytics"

export default function useGoogleAnalytics() {
  const location = useLocation()

  React.useEffect(() => {
    analytics.init()
  }, [])

  React.useEffect(() => {
    const currentPath = location.pathname + location.search
    analytics.sendPageview(currentPath)
  }, [location])
}
Enter fullscreen mode Exit fullscreen mode

Let's call our hook

We go to our App component and we call our custom hook function.

function App() {
  useGoogleAnalytics()

  return (
    <BrowserRouter>
      <Switch>...</Switch>
    </BrowserRouter>
  )
}
Enter fullscreen mode Exit fullscreen mode

There is a problem though. Our hook depends on the current location object which is not available yet on the App components

A quick solution is to create a separate component called Routes that renders the Switch component and its children and calls the custom hook from there.

Doing that we can be sure that the BrowserRouter component exists and has defined the location object before rendering Routes.

function Routes() {
  useGoogleAnalytics()

  return (
    <Switch>
      <Route exact path="/">
        <Home />
      </Route>
      <Route exact path="/features">
        <Features />
      </Route>
      <Route exact path="/signup">
        <SignUp />
      </Route>
    </Switch>
  )
}

function App() {
  return (
    <BrowserRouter>
      <Routes />
    </BrowserRouter>
  )
}
Enter fullscreen mode Exit fullscreen mode

That's all folks! You have successfully added Google Analytics in your React app!

Now, you can fire custom events from any component you like by just importing and calling the sendEvent function from the analytics.js file.


If you liked this post, you can follow me on Twitter where I share daily tips about coding, design and bootstrapping micro-startups.

Top comments (2)

Collapse
 
keke_arif profile image
Keke Arif

Nice implementation. I like how you used a new Routes component.

Collapse
 
d__raptis profile image
Jim Raptis

Thanks, man! It was a rough solution but the simpler one 😅