Google Tag Manager with next.js

30 August 2023

Google Tag Manager with Next.js

Irelia Codeheart, Senior Developer

Understanding Google Tag Manager and Next.js

There's always new and more technologies to learn in web development. Today we're talking about the combination of a popular framework, Next.js, and Google Tag Manager (GTM). Let's start with an overview of these tools, understanding how client-side navigation works in Next.js and the benefits of integrating GTM in a Next.js web app.

Working with another framework?

Here are the guides for implementing GTM with Svelte and GTM with Nuxt.js.

Brief overview of GTM and Next.js

Google Tag Manager is a free tool from Google, as the name implies. GTM allows website owners to manage and deploy tags (snippets of code or tracking pixels) on a website (or mobile app) without having to modify the code. It delivers simplicity, flexibility, and reliability to manage and measure user interactions with the web content.

Still have questions? Read the full article on what Google Tag Manager is used for.

On the other hand, Next.js is a JavaScript framework based on React that enables developers to build server-side rendering and static web applications. This framework significantly improves the performance of React apps and provides SEO benefits. In addition to its benefits, it supports various advanced features, including pre-rendering, automatic code splitting, static exporting options, and comfortable development experience.

Understanding client-side navigation in Next.js

The concept of client-side navigation in Next.js is quite different from traditional webpage navigation. Here, a request for a new page does not require a full page reload from the server. The Next.js Link component enables client-side navigation between two pages in the same Next.js app. It pre-fetches the linked page's code in the background and swaps the old page with the new one on click. This leads to a seamless user experience mimicking a single-page application.

Why integrate GTM with Next.js

As modern web applications often involve complex user interactions, tracking these interactions becomes vital for understanding users. But GTM aims to make the tracking easy and efficient.

When integrated with Next.js, GTM offers significant benefits. It provides a centralized platform for managing tracking codes to track multiple user interactions without tampering with the website code. Additionally, GTM is relatively easy to implement and maintain within a Next.js app.

Moreover, Next.js's advantage relating to client-side navigation poses a particular challenge. Standard GTM setup does not track these internal page navigations. Therefore we need a custom setup involving the addition of a history change trigger in the GTM console. The next sections will dive deeper into this issue – and solutions.

In conclusion, integrating Google Tag Manager in a Next.js web application brings the convenience of managing tracking codes and collecting user interaction data while meeting the challenges posed by Next.js's client-side navigation mechanism. The next sections will guide you through setting up GTM in your Next.js application, illustrating several setups and offering code examples to make this process as simple as possible.

Win at SEO

Boost your SEO game effortlessly with your new favorite headless CMS: caisy. Time to unlock Headless SEO with a blend of speed, optimization and innovation.

Caisy graphic artwork SEO page speed

How to Integrate Google Tag Manager with Next.js

This section will provide you a comprehensive guide to integrating Google Tag Manager with Next.js applications, addressing challenges including tracking page views during client-side navigation. Let's dive in.

Preinstallation Setup and Prerequisites

Before we begin, ensure you have installed up-to-date versions of Node.js and npm. You will also need an active Google Tag Manager account. Make sure you have your GTM Container ID, as it will be used in the integration process.

Adding GTM Script to Your App

The GTM script should be placed in a file that won't be tree-shaken away. Add the Google Tag Manager code in both the <head> and <body> sections of the _document.js file:

<head>
    {(process.env.NODE_ENV === 'production') &&
        <script 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>
    {(process.env.NODE_ENV === 'production') &&
        <noscript dangerouslySetInnerHTML={{
            __html: `<iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXX" height="0" width="0" style="display:none;visibility:hidden"></iframe>`
        }}></noscript>
    }
</body>

Understanding and Handling Client-Side Navigation Issues

One common issue in Next.js applications integrated with GTM is that Google Analytics may not track internal page navigations. This is because these navigations do not trigger the browser's traditional 'load' event upon which Google Analytics relies.

As a solution, you can create a 'history change' trigger in your Google Tag Manager console.

In the GTM console, navigate to 'Triggers' > 'New' > 'Trigger Configuration' > 'History Change' and then save the trigger configuration. The trigger will ensure that every client-side navigation is tracked without reloading the entire page.

To summarize, in this section, we learned about the essentials of integrating Google Tag Manager with a Next.js web application and how to deal with issues related to client-side tracking. Stay tuned for the next section to further explore its manipulation and performance efficiency.

Advantages of Using Google Tag Manager in Next.js

There are several benefits to integrating Google Tag Manager (GTM) with your Next.js application. Here we look at three main advantages: centralized tracking code management, rich data for insights, and ease of implementation and maintenance.

Centralized Tracking Code Management

By integrating GTM with Next.js, you can manage all your tracking codes centrally. This comes in handy if you use multiple analytics platforms such as Google Analytics or LinkedIn Insights. In traditional setup, you'd need to add separate tracking codes to your Next.js pages. But with GTM, you simply add different tags within the GTM interface. This provides a neat and unified system for code management and less clutter in your codebase.

  <head>
    <script async src="https://www.googletagmanager.com/gtag/js?id=GA-MEASUREMENT-ID"></script>
  </head>

Rich Data for Insights

By tracking specific actions like clicks, form submissions, and engagement with different sections of your site, GTM provides a wealth of valuable data that goes beyond what traditional analytics can offer. This granular level of tracking empowers you to make data-driven decisions, better understand user behavior, and optimize the overall user experience on your website.

  useEffect(() => {
    window.dataLayer = window.dataLayer || [];
    function gtag() {
      dataLayer.push(arguments);
    }
    gtag("js", new Date());
  }, []);

Ease of Implementation and Maintenance

Adding GTM to your Next.js application is a simple process. First, you'll need to include the GTM script in the head section of each page. Once that's done, you can inject the script into your application. From there, any additional tracking tags can be managed directly through the GTM interface, there's no need to modify your application's codebase. GTM also provides tools for testing and debugging tags before they go live, making it easy to ensure everything is working as intended. This streamlined approach not only simplifies the initial setup but also reduces the ongoing maintenance required to keep your tracking up to date.

  export default function MyApp({ Component, pageProps }) {
     useEffect(() => {
         GTMPageView(url);
     }, [url]);
     return <Component {...pageProps} />;
  }

In conclusion, integrating Google Tag Manager with your Next.js application can significantly streamline your tracking code management, provide deeper user insight and simplify the overall implementation and maintenance process.

Common Challenges and Solutions when Integrating GTM with Next.js

Developers encounter a few common problems when integrating Google Tag Manager with Next.js. In this section, we'll cover three key challenges and their potential solutions: tracking page views during client-side navigation, adding GTM to a Next.js 14 app, and understanding and solving Google Analytics tag firing issues.

Tracking page views during client-side navigation

One common issue in integrating GTM with Next.js is the challenge of tracking page views during client-side navigation. This is because Next.js uses a client-side router, which doesn't result in a full page load, causing GTM not to track page views accurately.

To solve this issue, developers can use the next/router event paired with React's useEffect hook. This combination ensures that when the path of the page changes, the hook triggers the GTM to register the view event.

import { useEffect } from 'react'
import { useRouter } from 'next/router'
...
useEffect(()=>{
  const handleRouteChange = (url) => {
    window.dataLayer.push({
      event: 'page_view',
      page: url,
    })
  }

  router.events.on('routeChangeComplete', handleRouteChange)
  return () => {
    router.events.off('routeChangeComplete', handleRouteChange)
  }
}, [router.events])

Note: With the latest GA4 version all the client side navigation is already tracked and tracking page_view will result in the same. This event is not called page view however. If you open up the debugger in google tag manager this will show up as 'History Change'. So depending on your use case you can create triggers on a custom named page view event or you just use the history change event that is already there.

Adding GTM to a Next.js 14 with app router

To achive the same in the new Next.js App router, you want to create a client component and use that component in the app/layout.tsx to render it on every page and use the hook usePathname like this:

"use client";

import { usePathname } from "next/navigation";
import { useEffect } from "react";

export const GA4Provider = () => {
  const pathname = usePathname();

  useEffect(() => {
    window.dataLayer.push({
      event: "page_view",
      page: window.location.href,
    });
  }, [pathname]);

  return null;
};

Another challenge lies in integrating GTM into a Next.js 14 App Router website. The solution could be found in this react component, combined with the Suspense boundary in the layout.tsx root component. An example type of Analytics component, with page view tracking and the environmental check, could be as follows:

const Analytics = () => {
  if (process.env.NODE_ENV === 'production') {
    return (
      <Script
        src={`https://www.googletagmanager.com/gtag/js?id=${process.env.NEXT_PUBLIC_GOOGLE_ANALYTICS}`}
        strategy='afterInteractive'
      >
        {'window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag("js", new Date()); gtag("config", ""${process.env.NEXT_PUBLIC_GOOGLE_ANALYTICS}"");'}
      </Script>
    );
  }
  // development
  return null;
};

Understanding and solving Google Analytics tag firing issue

If a GTM tag dedicated to Google Analytics isn't firing properly, a possible issue might be with multiple tags. To avoid duplicate GTM tags, ensure the tag only implements once per page load. For example by placing the GTM script in either _app.js, layout.js, or _document.js file by using the <Script/> tag for Next.js v11 and <script> tag for v10 and below.

It also helps to add a "History Change" trigger in the GTM console. This can ensure that page views are tracked correctly even on subsequent page transitions. However, remember to remove any other tracking scripts to avoid overcounting.

<Script strategy="afterInteractive">
  (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-XXXX');
</Script>

This setup ensures effective page tracking without GTM tag duplication.

Examples of GTM Implementation in Next.js

In this section, we'll examine practical examples for integrating Google Tag Manager with Next.js. We'll cover the main aspects of GTM implementation, such as tracking page navigations, setting up GTM in a Next.js App, and adding a history change trigger in the GTM console.

Tracking Page Navigations in Next.js

Monitoring page navigations is an essential aspect of any web analytics effort. With GTM, you can track internal page navigations easily and efficiently. The method recommended for this involves leveraging the history change trigger feature in the GTM console.

// Basic example
window.dataLayer = window.dataLayer || [];
dataLayer.push({
  'event': 'pageView',
  'pagePath': window.location.pathname
});

This small code snippet pushes a new event to the window.dataLayer array each time a page change occurs, thus enabling page tracking.

Adding History Change Trigger in GTM Console

To effectively track internal page navigations in a Next.js App, utilizing the History Change trigger in GTM console is highly recommended. This feature allows capturing dynamic page views that occur within a single-page application (SPA) like Next.js.

In GTM console, navigate to the Triggers section. Create a new trigger, choose History Change type, and define its properties depending on your needs.

Remember, these examples are meant to guide you in the process of integration Google Tag Manager with your Next.js project. The real-life implementation may vary based on the specific needs and structure of your Next.js application.

Debugging and Optimizing Your GTM Implementation in Next.js

As you integrate GTM into your Next.js application, it's crucial to ensure that your implementation is functioning correctly. In this section, we'll explore various techniques for debugging and optimizing your GTM setup in Next.js.

Using GTM Preview Mode and GA Debugger

One of the most valuable tools for debugging your GTM implementation is the GTM Preview Mode. This feature allows you to test your tags, triggers, and variables in real-time without publishing your container. To enter Preview Mode, follow these steps:

  1. Open your GTM container and click on the "Preview" button in the top right corner.

  2. A new window will open, displaying your website with the GTM debug panel at the bottom.

  3. Navigate through your website and observe the data being collected and fired by GTM.

In addition to Preview Mode, you can also utilize the Google Analytics Debugger Chrome extension. This extension logs detailed information about your GA events and helps you identify any discrepancies or issues.

Leveraging Browser Developer Tools for Debugging

Browser developer tools, such as Chrome DevTools, provide a wealth of information for debugging your GTM implementation. Here are a few key areas to focus on:

  • Console: Check the console for any JavaScript errors or warnings related to GTM or your tracking code.

  • Network: Analyze the network requests to ensure that your tracking data is being sent correctly to Google Analytics or other endpoints.

  • Elements: Inspect the HTML structure of your pages to verify that the GTM container code is properly placed and executed.

Common Issues and Solutions in Next.js GTM Integration

When integrating GTM with Next.js, you may encounter some common issues. Here are a few scenarios and their corresponding solutions:

  1. Page view tracking inconsistencies: Due to Next.js's client-side navigation, page views may not be accurately tracked. To resolve this, you can utilize the next/router events and the useEffect hook to manually push page view events to the data layer.

  2. Duplicate tracking events: If you have multiple instances of the GTM script on your pages, it can lead to duplicate tracking. Ensure that you have a centralized approach to including the GTM script, such as using the next/script component or the _document.js file.

  3. Data layer availability: In server-side rendered pages, the dataLayer object may not be immediately available. To mitigate this, you can initialize the dataLayer on the server-side using a script in the _document.js file.

GTM vs Other Tag Management Implementations in Next.js

In this section, we'll delve into the comparison between Google Tag Manager and other prevalent tag management methods within Next.js. We'll compare them on several fronts and discuss why opting for GTM could be within your best interests.

Comparative Overview of GTM and Other Tag Management Methods

It's not uncommon to encounter other tag management methods in Next.js projects. Methods such as direct coding or using a different tag manager altogether like Segment or Matomo are pretty common.

However, note that directly coding tags onto your website can be a cumbersome task, especially if you are tracking multiple page events. It eliminates the flexibility of manipulating these tracking parameters on the fly without having to redeploy the app every time you make an adjustment.

On the other hand, while Segment and Matomo offer a comprehensive data analytics platform, they might not always provide the flexibility and ease of integration that GTM does with Next.js.

Advantages and issues with Various Implementations

Direct hand coding of tags allows for a custom-coded solution that fits your needs perfectly. However, it's quite time-consuming, unwieldy for large scale applications and depending on how your site is structured, could lead to slower load times.

Segment and Matomo offer strong analytics platforms with built-in tag management. While they are great tools in their own right, you might encounter a steeper learning curve as their interface is more complex to navigate than GTM. They also do not offer the same level of integration with an extensive range of third-party tools like GTM does.

Why Choose GTM Over Other Options

For a Next.js developer, Google Tag Manager is preferable due in part to its ease of use and the extensive range of third-party tool integrations it offers. This means you can feed data into almost any popular digital marketing tool with ease. GTM is also free to use, unlike some of its competition in the tag management space.

In addition, the centralization of all tracking code within the GTM interface makes it easy for anyone with appropriate access to manage and update your tracking setup. This eliminates the need to dig into code every time you want to add or modify your tracking parameters.

In conclusion, integrating Google Tag Manager with Next.js offers significant benefits. The detailed instructions, examples, and insights found throughout this guide will help you implement GTM into your Next.js applications with confidence.

Building Next.js applications with Google Tag Manager integration can lead to robust, data-driven applications. Having a headless CMS like caisy at the core of your projects can further enhance this experience (learn what a Headless CMS is). Caisy, with its powerful GraphQL API and remarkable speed, offers a user-friendly interface for developers to manage content.

A scalable multi-tenancy feature, comprehensive Digital Asset Management system and flexible self-service pricing tiers are some of caisy's key offerings. These features combined with GTM render a powerful toolkit for creating and managing your Next.js projects.

While GTM helps capture user interactions, caisy facilitates streamlined content creation and project management. Therefore, by combining the strengths of Google Tag Manager with the functionalities provided by the headless CMS caisy, developers can enjoy an efficient and flexible development experience.

So don't waste any more time. Check our Starter Templates and kickstart your journey with the perfect Headless CMS for developers right away!

Focus on Your Code
Let caisy Handle the Content.