Custom React hook to connect Google Analytics
Tags: webdev, react, javascript
Published: 2020-08-06 15:11:05

---
title: Custom React hook to connect Google Analytics
published: true
description: Create a custom hook to connect Google Analytics in React using react-router-dom and react-ga packages
tags: webdev,react,js
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/fv7spni3xvy5xfrpba7n.jpg
canonical_url: https://www.jimraptis.com/blog/custom-hook-to-connect-google-analytics-in-react/
---

Check the full article on my [personal blog](https://www.jimraptis.com/blog/custom-hook-to-connect-google-analytics-in-react/)

---

**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](analytics.google.com) 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`:

```bash
npx create-react-app demo-app
cd demo-app
```

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:

```bash
yarn add react-router-dom react-ga
```

Or if you're using `npm`:

```bash
npm install --save react-router-dom react-ga
```

## 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](https://github.com/react-ga/react-ga#reactgainitializegatrackingid-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.

```javascript
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,
}
```

## 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!

```jsx
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
```

## 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?!

```jsx
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])
}
```

## Let's call our hook

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

```jsx
function App() {
  useGoogleAnalytics()

  return (
    <BrowserRouter>
      <Switch>...</Switch>
    </BrowserRouter>
  )
}
```

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`.

```jsx
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>
  )
}
```

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](https://twitter.com/d__raptis) where I share daily tips about coding, design and bootstrapping micro-startups.**