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
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
Or if you're using npm
:
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 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,
}
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
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])
}
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>
)
}
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>
)
}
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)
Nice implementation. I like how you used a new Routes component.
Thanks, man! It was a rough solution but the simpler one π