Google Tag Manager with next.js

17 June 2024

Google Tag Manager with Next.js

Irelia Codeheart, Senior Developer

How to track and manage your next.js application's analytics without adding extra bulk to your code? In this blog post, I'll guide you through the advantages of using Google Tag Manager with Next.js, showing you not just the "how" but also the "why." We’ll cover setting it up step-by-step, optimizing your tracking strategies, and using these insights to enhance user experience and engagement. So let's make your Next.js app not just functional but also analytically powerful!

Google Tag Manager and Next.js

The integration of the popular framework, Next.js, and Google's Tag Manager (GTM) is something many developers come across.

So what is Google Tag Manager? GTM is a free tool from Google that website owners use to integrate and manage so-called tags (Google Tag Manager snippets of code or tracking pixels) on a website (or mobile app). This way, you can measure and track user interactions.

Want to know more? Read the full article on what Google Tag Manager is used for.

And what is next.js? It's a React-based JavaScript framework developers use to build server-side rendering and static web applications. Popular reasons for next.js are that it improves the performance of React apps and provides SEO benefits. Next.js also offers features like pre-rendering, automatic code splitting and static exporting options that developers appreciate.

When it comes to client-side navigation in Next.js is, 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 use GTM with Next.js

Integrating Google Tag Manager with Next.js helps you track what users do on your site. Knowing user behavior is key for any modern web app because it helps you understand your audience better and make data-driven decisions. GTM makes this task easier by letting you manage all your tracking codes centralized, without having to modify your project’s code directly.

Another big benefit is how well GTM works with Next.js, especially since Next.js handles page changes differently than traditional websites. Normally, GTM doesn't catch these user movements because they don’t involve reloading the page. But by setting up GTM with a history change trigger, you can make sure every single page visit gets tracked, even those that happen without a page reload.

In the following sections, we'll explore how to get GTM working perfectly with Next.js. We'll go over how to set everything up, give you code snippets to use, where to add google tag manager code and show you how to track user moves effectively.

Working with another framework?

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

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

Google Tag Manager Next.js Integration Guide

Here begins the work! A step-by-step guide will make sure you get everything right when implementing GTM in your Next.js project.

Make sure you have installed up-to-date versions of Node.js and npm. Also, don't forget to create your Google Tag Manager account and have your GTM Container ID ready.

How to Add GTM Script to Your App

Let's begin with an important question: Where to add google tag manager code? Place the GTM script in a file that won't be tree-shaken away. Add the Google Tag Manager code in both the <head> and <body> sections of your _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>

Client-Side Navigation Tracking in Next.js with GTM

A common challenge when using Google Tag Manager with Next.js is that Google Analytics might not track page views during internal navigations. This issue arises because Next.js's client-side routing doesn't trigger the browser's usual 'load' event that Google Analytics typically relies on for tracking.

To solve this, here's how to set up this 'history change' trigger in GTM I talked about earlier:

  1. Open your GTM dashboard.

  2. Go to 'Triggers', then click on 'New'.

  3. Select 'Trigger Configuration' and choose 'History Change'.

  4. Save your new trigger.

This trigger will catch every instance of client-side navigation by listening for changes in the browser's history.

Additionally, make sure your GTM is firing correctly with each page change. This might involve tweaking your Next.js _app.js file to manually push data to GTM upon route changes, using Next.js's router events. By adding a few lines of JavaScript, you can ensure that every navigation event, even those that don't reload the page, is captured and sent to Google Analytics.

Optimizing Google Tag Manager Integration in Next.js

After we covered the basics, in this section you'll learn the advanced use of the Next.js Script component and strategic approaches to script loading. With these techniques you can ensure optimal performance and user experience.

Utilizing the Next.js Script Component

Basic Setup: The Script component is a flexible tool in Next.js that facilitates better control over third-party script loading. To integrate GTM using the Script component:

import Script from 'next/script';

function MyApp() {
  return (
    <>
      <Script
        src="https://www.googletagmanager.com/gtm.js?id=GTM-XXXXXX"
        strategy="afterInteractive"
      />
      {/* Additional scripts and application components */}
    </>
  );
}

This example uses the afterInteractive strategy, which loads GTM after the page becomes interactive to avoid any impact on the critical rendering path.

Advanced Loading Strategies

  • beforeInteractive: Use this for critical scripts that need to load before the page becomes interactive, like early analytics or bot detection scripts.

  • lazyOnload: Ideal for scripts that are not critical on initial load, such as chatbots or social media feeds, improving load times by executing scripts when the browser is idle.

Performance Optimization Tips

Deferring Non-Essential Scripts: 

To prevent non-essential scripts from blocking the main thread, use the lazyOnloadstrategy. This approach delays loading until it's absolutely necessary, which is crucial for maintaining fast, responsive interactions.

Preconnect and DNS Prefetch:

Speed up the connection to third-party domains by adding preconnect or dns-prefetch links in your Next.js <Head> component:

<Head>
  <link rel="preconnect" href="https://www.googletagmanager.com" />
  <link rel="dns-prefetch" href="https://www.googletagmanager.com" />
</Head>

These hints help the browser to establish early connections, reducing the time to fetch the script when it’s needed.

Practical Implementation and Handling Script Events

Implementing GTM with Event Handling: 

The Script component also supports event handlers such as onLoad and onError, which can be used to handle the loading status of the script:

<Script
  src="https://www.googletagmanager.com/gtm.js?id=GTM-XXXXXX"
  strategy="afterInteractive"
  onLoad={() => console.log('GTM script loaded successfully')}
  onError={(e) => console.error('Error loading GTM script', e)}
/>

These handlers ensure you can track the load status and catch any errors, providing more robust error handling for your scripts.

By strategically using the Script component and optimizing the loading of Google Tag Manager in Next.js, you can ensure your next.js-applications are rich in functionality AND optimized for performance. These techniques align with best practices for modern web development, providing a balance between powerful analytics and user-centric performance.

For a more detailed exploration of the Next.js Script component and additional optimization tips, visit the Next.js Documentation on the Script Component.

Advanced Integration Techniques for GTM with Next.js

Integrating Google Tag Manager (GTM) with Next.js effectively also involves overcoming several common challenges. This section will dive deeper into thes key issues, offering solutions and best practices.

Accurate Page View Tracking on Client-Side Navigations

A challenge in Next.js applications is tracking page views during client-side navigation, as these do not trigger traditional page reloads. To capture these movements accurately:

  1. Utilize Next.js Router Events with GTM:

import { useEffect } from 'react';
import { useRouter } from 'next/router';

const usePageViewTracking = () => {
  const router = useRouter();
  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]);
};

export default usePageViewTracking;
  1. Utilize in App/Layout: Place the GA4Provider component within your app/layout.tsx to ensure it renders on every page, capturing all navigation events.

Resolving Google Analytics Tag Firing Issues

Misfires in Google Analytics tags can lead to inaccurate data collection. Here’s how to solve common firing issues:

  1. Ensure Single Implementation per Page: Make sure the GTM script is implemented once per page, typically in the _app.js for Next.js. Avoid duplications in _document.js or any layout components.

  2. Set Up a 'History Change' Trigger in GTM: Configure your GTM to include a 'History Change' trigger, which helps track client-side navigations effectively:

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

Integrating GTM and Next.js 14 with App Router

Integrating Google Tag Manager (GTM) into Next.js 14 applications, especially with the new App Router, requires a tailored approach to ensure every page navigation is tracked accurately. Here’s an updated method to integrate GTM effectively using client components and the latest Next.js features. Here's a detailed guide on the Next.js App Router.

Creating a Client Component for Universal Page Tracking

In Next.js 14, leveraging the App Router allows for a more seamless integration of client-side tools like GTM. To set this up, create a client-side component that utilizes the usePathname hook from next/navigation. This hook provides the current path, enabling the tracking of page views as users navigate through your application:

// components/GA4Provider.js
"use client";

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

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

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

  return null;
};

Implementation in the App Layout

Integrate the GA4Provider component within your app/layout.tsx to ensure it renders on every page load, effectively capturing every client-side navigation:

// pages/app/layout.tsx
import GA4Provider from '../components/GA4Provider';

const Layout = ({ children }) => {
  return (
    <>
      <GA4Provider />
      {children}
    </>
  );
};

export default Layout;

This setup ensures that the GA4Provider component tracks all navigation changes across the site without additional configuration for each page or component.

Advanced Analytics Component for Production Environments

To handle environments dynamically and ensure analytics scripts only load in production, you can create an Analyticscomponent. This component will conditionally load the GTM script based on the environment, preventing analytics tracking during development:

// components/Analytics.js
import Script from 'next/script';

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>
    );
  }
  return null;
};

export default Analytics;

This component uses Next.js’s Script component with the afterInteractive strategy. This way, the analytics script does not impact the initial load performance.

Using the @next/third-parties Library

The @next/third-parties library can be a valuable addition to your Next.js project for managing third-party scripts like GTM. It helps streamline the integration process and ensures better performance by handling script loading efficiently.

Integrating @next/third-parties for GTM

Here’s how you can utilize the @next/third-parties library to integrate GTM:

  1. Install the Library:

npm install @next/third-parties
  1. Use the Library to Load GTM:

import { ThirdParty } from '@next/third-parties';
import { useEffect } from 'react';
import { useRouter } from 'next/router';

const GTM = () => {
  const router = useRouter();

  useEffect(() => {
    const handleRouteChange = (url) => {
      window.dataLayer = window.dataLayer || [];
      window.dataLayer.push({
        event: 'page_view',
        page: url,
      });
    };

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

  return (
    <ThirdParty
      src={`https://www.googletagmanager.com/gtm.js?id=${process.env.NEXT_PUBLIC_GOOGLE_TAG_MANAGER}`}
      strategy="afterInteractive"
    />
  );
};

export default GTM;

The @next/third-parties library makes handling third-party scripts easy. It helps your scripts load at the perfect time without slowing down your site.

Debugging GTM Implementation in Next.js

Here’s how you can effectively debug and optimize your setup:

Using GTM Preview Mode and GA Debugger

GTM Preview Mode is an essential tool for debugging. It lets you test tags, triggers, and variables in real-time without affecting the live environment. To use it, simply activate Preview Mode in your GTM dashboard and navigate your site to see how tags are firing. This mode has been enhanced to work without third-party cookies, which means it now functions seamlessly across all modern browsers, including those that block such cookies by default​​.

Google Analytics Debugger, available as a Chrome extension, is another great tool that logs detailed information about GA events, helping you pinpoint discrepancies or configuration issues​​.

Leveraging Browser Developer Tools

Browser tools like Chrome DevTools are invaluable for debugging GTM:

  • Console: Check for JavaScript errors or warnings that might affect GTM.

  • Network: Ensure tracking data is sent correctly to Google Analytics or other endpoints.

  • Elements: Verify the correct placement and execution of GTM container code.

Advanced Debugging Tips

Additionally, understanding how to navigate and utilize the new GTM Preview Mode can significantly help your debugging process. The updated interface provides a more intuitive environment for testing and confirming that all tags are firing correctly, with detailed session summaries and API call logs​.

By following these updated methods and utilizing the latest tools, your GTM setup in Next.js will be most effective. For more detailed guidance, visiting the official Google Tag Manager documentation is recommended​.

Overall, the integration of these advanced tools and practices should provide a robust framework for deploying, testing, and optimizing GTM in your Next.js projects.

GTM vs Other Tag Management Implementations in Next.js

Are there alternatives to Google Tag Manager? Yes. We'll compare them on several fronts and discuss why tracking with GTM in Next.js applications could be your best choice.

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, directly coding tags onto your website can mean more work, 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.

Plus, 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.

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. Here's the guide for GTM with Nuxt.js.

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 improve this experience (learn what a Headless CMS is). Caisy, with its powerful GraphQL API, speedy and user-friendly interface helps developers to build and 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.