Adding Google Tag Manager to NextJS app

Using Google tag manager with NextJS can allow you to add 3rd party integrations and data to your application or website. GTM should be used in my opinion to not only be the connection between 3rd parties but be your only connection. Adding code directly to your application seem's like a great idea but it can give you a headache down the road if you need to remove it if you are replacing it or just don't need it any longer.
This article will go through the basic integration between NextJS.
I assume you will already have the following:
A current working NextJS application (I'm using NextJS version 13.2.1 for this tutorial )
Registered a Google tag manager account and setup a container for your application.
Creating a custom _document.js file in NextJS.
If you haven't already, in your pages folder within the app root add a custom _document.js file.
This document file although is optional for NextJS to run, allows you to control some of the main elements on the application such as <html> and <body>. It's important to note that the document.js file only runs on the server and so client side functions do not work in this file and may give you an error. Here is a sample of the basic document.js template you can use to get you going:
import { Html, Head, Main, NextScript } from 'next/document'
export default function Document() {
return (
<Html lang="en">
<Head>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
The Google tag manager code snippets
When you created your Google tag manager container you would have been presented with a popup which provides you with 2 code snippets. These snippets are used to integrate your container to your NextJS application.
Example of the 2 code snippets below:
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXXXX');</script>
<!-- End Google Tag Manager -->
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXXX"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
The first one should be added as high in the <head> element as possible, and the second should be the first block of code in the <body> element.
You will see within the snippets that my GTM-XXXXXX is generic but your's will contain your reference to the container you created. This is important so make sure that it is correct and you are using your reference.
Wait before you add these to app.
We can't just add these snippets of code to our NextJS app. They will cause your app to error. We will need to modify them so that they can be compiled with the rest of the application when it comes to been server rendered.
It is a simple change, we are going to be using the latest Next/Script which allows us to control how the scripts are included and used across our app.
Add
import Script from 'next/script';
Then include the Script component inside the Head component on your _document.js and adding the GTM script within the dangerouslySetInnerHTML attribute of the Script component. We are including both scripts making sure that the first one is the first item within the <Head> component and the second is the first component within the body element as requested by Google tag manager instructions.
import { Html, Head, Main, NextScript } from 'next/document'
import Script from 'next/script';
export default function Document() {
return (
<Html lang="en">
<Head>
<Script
id="google-tag-manager"
strategy="afterInteractive"
dangerouslySetInnerHTML={{ __html: `
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXXXX');
`}}></Script>
</Head>
<body>
<noscript
dangerouslySetInnerHTML={{
__html: `<iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXXX"
height="0" width="0" style="display:none;visibility:hidden"/>`,
}}
/>
<Main />
<NextScript />
</body>
</Html>
)
}
Now when you run your NextJS application if you review the Google tag manager dashboard at the same time it should be reporting your visits to the application.
I hope that was easy enough to follow, if i missed anything out or you have any questions please drop me a message here