Originally posted at my blog
There are lots of tutorials online that give you instructions on how to set up Google Analytics with Next.js project.
But most of them require you to use react-ga
, a library that basically wraps Google Analytics logic inside a React component.
This is good, but I personally prefer a solution that:
- Does not require an external dependency (
react-ga
in this case) - Easy to implement (you don't need to make a thousand lines of custom code)
- Is recommended officially
My solution is based on an official example of Next.js team here: Example app with analytics
You can also check this Github issue for some of the other workarounds that people used: Adding GA script tag? #160
Let's get started!
Table of contents
- Create GA Helper
- Update _document.js
- Update _app.js
- Conclusion
1. Create GA Helper
This helper file stores your Google Analytics tracking ID and provides some methods that you need to track your page views.
Add this to lib/gtag.js
:
export const GA_TRACKING_ID = 'UA-XXXXXXXXX-X' // This is your GA Tracking ID
// https://developers.google.com/analytics/devguides/collection/gtagjs/pages
export const pageview = (url) => {
window.gtag('config', GA_TRACKING_ID, {
page_path: url,
})
}
// https://developers.google.com/analytics/devguides/collection/gtagjs/events
export const event = ({ action, category, label, value }) => {
window.gtag('event', action, {
event_category: category,
event_label: label,
value: value,
})
}
2. Update _document.js
Create a custom _document.js
that will load our Google Analytics script for us. We will only load this script in production so that we don't track items locally. In the pages directory create a new file, _document.js
and add the following code:
File: pages/_document.js
import { Fragment } from 'react'
import Document, { Head, Main, NextScript } from 'next/document'
import FavIcon from '../assets/image/favicon.png'
import { GA_TRACKING_ID } from '../lib/gtag'
export default class CustomDocument extends Document {
static async getInitialProps(ctx) {
const sheet = new ServerStyleSheet()
const originalRenderPage = ctx.renderPage
const initialProps = await Document.getInitialProps(ctx)
// Check if in production
const isProduction = process.env.NODE_ENV === 'production'
return {
...initialProps,
isProduction,
}
}
render() {
const { isProduction } = this.props
return (
<html lang="en">
<Head>
<link rel="shortcut icon" type="image/x-icon" href={FavIcon} />
{/* We only want to add the scripts if in production */}
{isProduction && (
<Fragment>
{/* Global Site Tag (gtag.js) - Google Analytics */}
<script
async
src={`https://www.googletagmanager.com/gtag/js?id=${GA_TRACKING_ID}`}
/>
<script
dangerouslySetInnerHTML={{
__html: `
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${GA_TRACKING_ID}', {
page_path: window.location.pathname,
});
`,
}}
/>
</Fragment>
)}
</Head>
<body>
<Main />
<NextScript />
</body>
</html>
)
}
}
3. Update _app.js
You will trigger pageview event here when the router detects route is changed.
File: pages/_app.js
import React, { Fragment } from 'react'
import Router from 'next/router'
import * as gtag from 'common/src/lib/gtag'
// Notice how we track pageview when route is changed
Router.events.on('routeChangeComplete', (url) => gtag.pageview(url))
export default ({ Component, pageProps }) => {
return (
<Fragment>
<Component {...pageProps} />
</Fragment>
)
}
4. Conclusion
Now you can see how easy it is to make Google Analytics works with Next.js without any external dependency.
Happy coding!
Top comments (1)
Great!
Do you know how to catch scroll event per page on GTM?
It only catches once though activate pageview function because we are on SPA ... :(
In other words, the page scroll status does not reset on route change(pageview)...
I'm very struggling with this.. plz help!