How to Implement Google Tag Manager and Consent Mode in NextJS 15

by Spencer, Co-Founder / CTO


Introduction

Google Tag Manager with Consent Mode in NextJS 15

Web analytics have become indispensable for modern businesses. Whether you’re tracking user interactions, evaluating campaign performance, or understanding your audience, tools like Google Tag Manager (GTM) and Google Analytics (GA) are essential. But as users demand greater control over their data, and as regulations like GDPR and CCPA enforce stricter compliance, integrating analytics without compromising privacy is more important than ever.

Why This Tutorial?

Despite its importance, implementing Google Tag Manager with Consent Mode in NextJS 15 can be challenging:

  • NextJS’s Limitations: Tools like @next/third-parties lack robust support for Consent Mode, especially when default consent states need to be set in sequence before cached consent values are loaded.
  • Documentation Gaps: While individual libraries provide usage guides, there’s no comprehensive tutorial on integrating GTM, Consent Mode, and a cookie banner in a NextJS 15 project.
  • A Proven Approach: Through hands-on experience, we developed a solution that builds on best practices and extends the functionality of existing tools. This tutorial shares our step-by-step approach, ensuring you achieve both analytics precision and privacy compliance.

Important NextJS Version Compatibility Note

The implementation this tutorial provides also works with NextJS 14 🚀

What You’ll Achieve

By following this guide, you’ll:

  1. Implement Google Tag Manager in your NextJS application.
  2. Add Consent Mode for privacy-first tracking.
  3. Build a cookie consent banner to capture and manage user preferences.
  4. Gain insights into how to configure GTM to respect consent states dynamically.

At the end of this tutorial, you’ll have a fully functional solution that respects user privacy while collecting valuable analytics data.


Prerequisites

Before diving into the technical steps, ensure your environment and knowledge are ready for the implementation.

Technical Knowledge

To follow this guide effectively, you should be familiar with:

  • JavaScript and React: Understanding of components, hooks, and JSX.
  • NextJS Framework: Familiarity with features like server-side rendering (SSR) and file-based routing.
  • Environment Variables: Experience setting up .env files for sensitive data.

While this tutorial includes detailed instructions, some familiarity with these concepts will ensure a smoother learning process.

Tools and Setup

Ensure your development environment includes:

  1. Node.js (v16 or newer): Install it from Node.js.
  2. Code Editor: Visual Studio Code is recommended for its robust ecosystem.
  3. Google Tag Manager Account: Create one at Google Tag Manager.
  4. GTM ID: Example: GTM-XXXXXX.

Already Have a GTM Account?

Ensure you have a valid Google Tag Manager ID (e.g., GTM-XXXXXX) to follow along. If not, create one at Google Tag Manager.


To streamline this tutorial, we’ve structured the accompanying repository into phases. Each branch corresponds to a step in the process, allowing you to follow along or compare your implementation at any time.

Repository Overview

Branch NameDescription
phase/0-initial-boilerplateThe starting point: a clean NextJS 15 app.
phase/1-add-libsAdds tracking utilities for GTM and Consent Mode.
phase/2-add-gtm-componentsImplements GTM scripts and a wrapper for cached consent handling.
phase/3-integrate-gtmFully integrates GTM, Consent Mode, and the cookie banner.
phase/complete-implementationFinalized project with all features implemented.

Steps to Use the Repository

  1. Clone the Repository:
    git clone https://github.com/spencermarx/aclarify-blog-example--gtm-with-consent-in-nextjs.git
    BASH
  2. Navigate to the Project Directory:
    cd aclarify-blog-example--gtm-with-consent-in-nextjs
    BASH
  3. Checkout the Initial Phase:
    git checkout phase/0-initial-boilerplate
    BASH
  4. Install Dependencies:
    npm install
    BASH
  5. Switch Between Phases:
    git checkout <branch-name>
    BASH

By following these steps, you can incrementally build the project while ensuring each phase works as expected.

Use Branches for Comparison

Each branch is designed to help you compare your work. If something isn’t working, check the corresponding branch for reference.

With the groundwork laid, we’re ready to begin building the project. In the next section, we’ll set up the initial NextJS application and configure it for analytics integration.


Run the Initial Boilerplate

To ensure you’re starting with a clean and functional project, checkout the phase/0-initial-boilerplate branch and run the development server. This will serve as the foundation for the Google Tag Manager (GTM) integration.


Step 1: Checkout and Run the Initial Boilerplate

Use the following commands to switch to the phase/0-initial-boilerplate branch and start the project:

 
# Checkout the Initial Boilerplate Branch
 
git checkout phase/0-initial-boilerplate
 
# Start the Development Server
 
npm run dev
BASH

Once the server is running, open your browser and navigate to http://localhost:3000 to view the boilerplate project.


Step 2: Confirm the Boilerplate Setup

At this phase, the project includes a minimal Next.js 15 application with placeholder content and no GTM or analytics functionality implemented yet. You should see a homepage resembling the image below:

Initial Boilerplate Project

This clean foundation ensures a smooth transition to the subsequent implementation steps.


Start Simple

The phase/0-initial-boilerplate branch provides a reliable starting point. By running and reviewing this base setup, you can identify any issues early and focus on the GTM and Consent Mode integration with confidence.

With the boilerplate confirmed, you’re ready to move on to Step 1: Adding TypeScript Types to establish a structured framework for GTM interactions.


Phase 1: Setting Up Tracking Utilities in NextJS

In this phase, we’ll establish the foundational tracking utilities for Google Tag Manager (GTM) in your NextJS 15 application. These utilities will ensure a scalable, maintainable way to manage tracking events and consent preferences.

What We’ll Cover

This section is divided into three main steps:

  1. Adding TypeScript Types: Define global types and interfaces to ensure consistency when interacting with GTM.
  2. Creating a Configuration Module: Centralize GTM-related settings for ease of use across your app.
  3. Implementing Tracking Utilities: Build reusable functions for managing GTM interactions, sending events, and handling consent.

By the end of this phase, you’ll have a robust framework for analytics integration, ready to be embedded into your application.


Step 1: Adding TypeScript Types

The first step is to define TypeScript types for GTM-related events and configurations. These types enforce structure and reduce errors when working with tracking data.

Add types.tracking.d.ts

Create a new file at src/libs/tracking/types.tracking.d.ts with the following content:

// src/libs/tracking/types.tracking.d.ts
 
// Extend the global namespace to recognize GTM-related properties
declare global {
  interface Window {
    gtag?: Gtag.Gtag
  }
}
 
declare namespace Gtag {
  interface Gtag {
    (...args: GtagFunctionArgs): void
  }
 
  type GtagFunctionArgs =
    | [GtagCommand, EventName | EventParams | CustomParams]
    | [GtagCommand, string, EventParams | CustomParams]
 
  type GtagCommand = 'config' | 'set' | 'js' | 'event' | 'consent'
 
  interface EventParams {
    [key: string]: unknown
  }
 
  interface CustomParams {
    [key: string]: unknown
  }
 
  type EventName = 'click' | 'submit' | 'purchase' | 'page_view' | 'screen_view'
 
  // Define a DTO for sending custom events
  type SendGAEventDto = {
    action: EventName
    category: string
    label: string
  }
}
TSX

Update tsconfig.json

To ensure TypeScript recognizes the new types, we need to include the types.tracking.d.ts file. Open your tsconfig.json file and add the following under "include":

{
  // ...other properties
  "include": [
    "next-env.d.ts",
    "**/*.ts",
    "**/*.tsx",
    ".next/types/**/*.ts",
    "src/libs/tracking/types.tracking.d.ts"
  ]
}
JSON

Explanation

  1. Global Namespace Extension:

    • Adds gtag to the Window interface, enabling TypeScript to recognize GTM-specific global properties.
  2. Standardized Event Types:

    • The EventName, EventParams, and CustomParams interfaces define the expected structure for GTM events.
    • The SendGAEventDto type is tailored for custom event tracking, ensuring consistency across your app.
  3. Benefits:

    • Centralized definitions make it easy to manage and extend event types.
    • Strong typing reduces runtime errors by catching issues during development.

Step 2: Creating a Configuration Module

Next, we’ll set up a configuration file to manage GTM-related settings, including enabling/disabling GTM and storing cookie preferences.

Add config.tracking.ts

Create a new file at src/libs/tracking/config.tracking.ts with the following content:

// src/libs/tracking/config.tracking.ts
'use client'
 
// Check if GTM is enabled via environment variable
export const IS_GTM_ENABLED =
  process.env.NEXT_PUBLIC_GTM_ID !== undefined &&
  process.env.NEXT_PUBLIC_GTM_ID !== ''
 
// Centralized tracking configuration
export const trackingConfig = {
  gtmId: process.env.NEXT_PUBLIC_GTM_ID || '',
  cookieBannerCookieName: 'cookieConsent',
}
TSX

Setting Up Environment Variables

To ensure the config.tracking.ts file works as intended, you need to set up your local environment variables by creating a .env.local file in the root of your project.

  1. Create .env.local: In the root of your project, create a new file named .env.local.

  2. Add the GTM ID: Add the following line to your .env.local file, replacing GTM-XXXXXX with your actual Google Tag Manager ID:

    NEXT_PUBLIC_GTM_ID=GTM-XXXXXX
    ENV
    • The NEXT_PUBLIC_ prefix makes this variable accessible on the client-side, which is required for GTM integration.
  3. Save the File: Save your .env.local file and restart your development server to ensure the environment variable is loaded.

Explanation

  1. Dynamic GTM Toggle:

    • The IS_GTM_ENABLED constant checks if NEXT_PUBLIC_GTM_ID is defined and not empty. This allows you to easily enable or disable GTM, especially in local or staging environments.
  2. Centralized Settings:

    • trackingConfig consolidates the GTM ID and cookie banner preferences into a single object for reusability.
  3. Best Practices:

    • Avoid hardcoding sensitive values like GTM IDs directly into your code. Use environment variables (NEXT_PUBLIC_GTM_ID) instead for security and flexibility.
    • Never commit your .env.local file to version control to keep your sensitive information secure.

Step 3: Implementing Tracking Utilities

With the types and configuration in place, we’ll create utility functions for interacting with GTM, including sending events, granting consent, and recording page views.

Add utils.tracking.ts

Create a new file at src/libs/tracking/utils.tracking.ts with the following content:

// src/libs/tracking/utils.tracking.ts
'use client'
 
import { IS_GTM_ENABLED, trackingConfig } from './config.tracking'
import { Gtag, GtagEvent } from './types.tracking'
 
const logGAWarning = (message: string) => {
  console.warn(`[Tracking] Warning: ${message}`)
}
 
const getGtag = () => {
  if (!IS_GTM_ENABLED) {
    logGAWarning('Google Analytics is not enabled')
    return null
  }
  if (!window.gtag) {
    logGAWarning('GTag does not exist')
    throw new Error('GTag does not exist')
  }
  return window.gtag
}
 
const withGtag = (callback: (gtag: Gtag.Gtag) => void) => {
  const gtag = getGtag()
  if (!gtag) return
  callback(gtag)
}
 
export const sendGAEvent = (event: GtagEvent) =>
  withGtag((gtag) => {
    gtag('event', event.action, {
      event_category: event.category,
      event_label: event.label,
      value: event.value,
    })
  })
 
export const grantConsentForEverything = () =>
  withGtag((gtag) => {
    gtag('consent', 'update', {
      ad_user_data: 'granted',
      ad_personalization: 'granted',
      ad_storage: 'granted',
      analytics_storage: 'granted',
    })
  })
 
export const markFeatureUsage = (feature: string) =>
  performance.mark('mark_feature_usage', {
    detail: { feature },
  })
 
export const pageview = (url: string) =>
  withGtag((gtag) => {
    gtag('config', trackingConfig.gtmId, {
      page_path: url,
    })
  })
TSX

Explanation

  1. Error Handling:

    • The logGAWarning and getGtag functions ensure clear error messages when GTM is not enabled or gtag is unavailable.
  2. Reusable Logic:

    • withGtag abstracts error handling, simplifying the implementation of tracking functions like sendGAEvent and pageview.
  3. Key Functions:

    • sendGAEvent: Tracks custom events (e.g., button clicks, form submissions) using the structured GtagEvent type.
    • grantConsentForEverything: Updates consent settings, granting all tracking permissions.
    • pageview: Records page views for navigation analytics.
  4. Scalability:

    • These utilities can be reused throughout your app, ensuring consistent tracking behavior.

Summary

In this phase, we achieved the following:

  1. Added TypeScript Types:
    • Defined global GTM properties and event structures for type safety.
  2. Created a Configuration Module:
    • Centralized GTM settings with dynamic enable/disable functionality.
  3. Implemented Tracking Utilities:
    • Built reusable functions for sending events, managing consent, and tracking page views.

With these utilities in place, you’re ready to integrate GTM into your NextJS application. In the next phase, we’ll add GTM components to your app and connect them to the utilities created here.

Need Help Implementing GTM in Your NextJS App?

Partner with Aclarify to accelerate your analytics integration. Our team of experts specializes in NextJS development, Google Tag Manager, and compliance solutions tailored to your business needs.


Phase 2: Adding Google Tag Manager Components

In this phase, we’ll integrate Google Tag Manager (GTM) into your NextJS 15 application by creating components to load GTM scripts dynamically and handle cached consent states. This integration ensures compliance with privacy regulations while maintaining robust analytics capabilities.

What We’ll Cover

  1. Adding GTM Script Component: Embed GTM into the application with GoogleTagManagerScripts, ensuring that GTM scripts are loaded correctly and efficiently.
  2. Creating Consent-Aware GTM Wrapper: Build a GoogleTagManager component to manage cached consent preferences and initialize GTM accordingly.

At the end of this phase, your app will have a reusable GTM integration that respects user consent.


Step 1: Adding GTM Script Component

We’ll start by creating the GoogleTagManagerScripts component. This component is responsible for embedding GTM scripts into the app and tracking page views dynamically.

Create GoogleTagManagerScripts.tsx

Create a new file at src/components/tracking/GoogleTagManagerScripts.tsx and add the following:

'use client'
 
import { markFeatureUsage, pageview } from '@/libs/tracking/utils.tracking'
import { usePathname, useSearchParams } from 'next/navigation'
import Script from 'next/script'
import { FC, useEffect } from 'react'
 
type Props = {
  gaId: string
  onLoadCallback?: () => void
}
 
export const GoogleTagManagerScripts: FC<Props> = ({
  gaId,
  onLoadCallback,
}) => {
  const pathname = usePathname()
  const searchParams = useSearchParams()
 
  // Track pageview on route change
  useEffect(() => {
    const url = pathname + searchParams.toString()
    pageview(url)
  }, [pathname, searchParams])
 
  useEffect(() => {
    markFeatureUsage('google_analytics_tag')
  }, [])
 
  return (
    <>
      {/* Inline script to set up dataLayer and define window.gtag */}
      <Script
        id="gtm-init"
        strategy="afterInteractive"
        dangerouslySetInnerHTML={{
          __html: `
            window.dataLayer = window.dataLayer || [];
            window.dataLayer.push({
              'gtm.start': new Date().getTime(),
              event: 'gtm.js'
            });
            window.gtag = function(){ window.dataLayer.push(arguments); };
            window.gtag('js', new Date());
            window.gtag('consent', 'default', {
              ad_storage: 'denied',
              ad_user_data: 'denied',
              ad_personalization: 'denied',
              analytics_storage: 'denied',
            });
            window.gtag('config', '${gaId}', {
              page_path: window.location.pathname,
            });
          `,
        }}
      />
      {/* Load the GTM script via src to enable onLoad callback */}
      <Script
        id="gtm-script"
        src={`https://www.googletagmanager.com/gtm.js?id=${gaId}`}
        strategy="afterInteractive"
        onLoad={onLoadCallback}
      />
    </>
  )
}
TSX

Explanation

  1. Dynamic Script Loading:

    • The Script component from NextJS dynamically loads the GTM scripts using the src attribute. The onLoadCallback ensures the app is notified when GTM finishes loading.
  2. Default Consent States:

    • The inline script (dangerouslySetInnerHTML) initializes dataLayer and sets default consent states (denied) for all categories (ad storage, personalization, etc.).
  3. Pageview Tracking:

    • The useEffect hook listens for route changes and triggers the pageview utility to track navigation events.
  4. Feature Usage Marking:

    • The markFeatureUsage function records the usage of GTM analytics for debugging or performance monitoring.

Be Careful with GTM Script Integration

Embedding scripts dynamically requires careful handling to avoid negatively impacting performance or violating compliance regulations.

  • Performance Impact: Ensure scripts are loaded asynchronously to avoid blocking the rendering of critical page elements.
  • Compliance Risks: Double-check that default consent states (e.g., denied for ad personalization and analytics) are correctly configured to comply with GDPR and CCPA.

If unsure, consider testing script loading behavior in a staging environment before deploying to production.


Fortunately, our implementation addresses these concerns by loading all gtm-related scripts asynchronously and also setting default consent states immediately.


To handle cached consent preferences and integrate GTM scripts into your app, we’ll create a higher-level wrapper component, GoogleTagManager.

Install Dependencies

First, add the required dependencies for managing cookies and animations:

npm install react-cookie-consent framer-motion
BASH

Add GoogleTagManager.tsx

Create a new file at src/components/tracking/GoogleTagManager.tsx and add the following:

'use client'
 
import { Suspense, useEffect, useState } from 'react'
import { getCookieConsentValue } from 'react-cookie-consent'
import { GoogleTagManagerScripts } from './GoogleTagManagerScripts'
import { trackingConfig } from '@/libs/tracking/config.tracking'
import { grantConsentForEverything } from '@/libs/tracking/utils.tracking'
 
export const GoogleTagManager = () => {
  const [isGtagLoaded, setIsGtagLoaded] = useState(false)
  const [hasSetConsent, setHasSetConsent] = useState(false)
 
  // Handle Consent
  useEffect(() => {
    if (isGtagLoaded && !hasSetConsent) {
      // Get historic consent value
      const consent = getCookieConsentValue(
        trackingConfig.cookieBannerCookieName
      )
 
      if (consent === 'true') {
        grantConsentForEverything()
      }
 
      setHasSetConsent(true)
    }
  }, [isGtagLoaded, hasSetConsent])
 
  return (
    <>
      <noscript>
        <iframe
          src={`https://www.googletagmanager.com/ns.html?id=${trackingConfig.gtmId}`}
          height="0"
          width="0"
          style={{
            display: 'none',
            visibility: 'hidden',
          }}
        ></iframe>
      </noscript>
      {/* We need to use Suspense in order to access useSearchParams (see https://nextjs.org/docs/messages/missing-suspense-with-csr-bailout) */}
      <Suspense>
        <GoogleTagManagerScripts
          gaId={trackingConfig.gtmId}
          onLoadCallback={() => setIsGtagLoaded(true)}
        />
      </Suspense>
    </>
  )
}
TSX

Explanation

  1. Consent Management:

    • The useEffect hook retrieves the stored consent value (getCookieConsentValue) and grants full consent (grantConsentForEverything) if the user has previously opted in.
  2. Suspense for Navigation:

    • To track route changes, the GoogleTagManagerScripts component uses useSearchParams, requiring a Suspense boundary due to NextJS's data fetching requirements.
  3. Fallback for NoScript Environments:

    • A <noscript> block ensures GTM functionality in browsers with JavaScript disabled by embedding an invisible iframe.

Summary

In this phase, we implemented GTM components to embed analytics scripts and manage user consent:

  1. GoogleTagManagerScripts:
    • Dynamically loads GTM scripts, initializes dataLayer, and tracks page views.
  2. GoogleTagManager:
    • Handles consent preferences, ensures scripts load correctly, and integrates smoothly with NextJS features.

With these components, your app is now ready to manage user consent and track events dynamically. In the next phase, we’ll integrate a cookie consent banner to enhance compliance and improve the user experience.


Phase 3: Integrating Google Tag Manager into the Global Layout

In this final phase, we’ll integrate the Google Tag Manager (GTM) and cookie consent banner directly into the global layout of the application. This ensures that tracking and consent management are accessible throughout the app, providing a seamless user experience.

What We’ll Cover

  1. Adding the Client-Side Inner Layout: Create a reusable RootInnerLayout component to manage the cookie consent banner.
  2. Embedding GTM in the Global Layout: Modify the global layout.tsx to include GTM and the inner layout for cookie consent.

By the end of this phase, your application will have a robust and privacy-compliant analytics integration that is active across all pages.


Step 1: Adding the Client-Side Inner Layout

The RootInnerLayout component handles the cookie consent banner using the react-cookie-consent library. It provides a clean structure for managing global UI elements like modals or banners.

Create RootInnerLayout.tsx

Add a new file at src/components/layouts/RootInnerLayout.tsx with the following code:

'use client'
 
import { trackingConfig } from '@/libs/tracking/config.tracking'
import { grantConsentForEverything } from '@/libs/tracking/utils.tracking'
import { ReactNode } from 'react'
import CookieConsent from 'react-cookie-consent'
import { motion } from 'framer-motion'
 
export const RootInnerLayout = ({ children }: { children: ReactNode }) => (
  <>
    <main className="w-full h-full relative">{children}</main>
    <motion.div
      initial={{ y: '100vh', opacity: 0 }}
      animate={{ y: 0, opacity: 1 }}
      transition={{ duration: 1, ease: 'easeInOut' }}
      className="fixed inset-x-0 bottom-0 z-50"
    >
      <CookieConsent
        disableStyles={true}
        cookieName={trackingConfig.cookieBannerCookieName}
        buttonText="Acknowledge"
        onAccept={grantConsentForEverything}
        location="bottom"
        containerClasses="w-full px-6 py-4 bg-black text-white text-center flex justify-center items-center flex-wrap shadow gap-3 md:gap-8 rounded-t-4xl shadow"
        buttonClasses="px-8 py-1.5 text-lg inline-flex rounded-full px-4 py-1.5 text-sm font-semibold transition bg-white text-black hover:bg-white/90 transition-colors ease-in-out duration-100"
      >
        <p>This website uses cookies to enhance the user experience.</p>
      </CookieConsent>
    </motion.div>
  </>
)
TSX

Explanation

  1. Cookie Consent Management:

    • The react-cookie-consent library is used to display a consent banner at the bottom of the page. When the user clicks "Acknowledge," it calls the grantConsentForEverything utility to grant full consent for tracking.
  2. Animations:

    • The framer-motion library animates the appearance of the cookie banner for a smooth user experience.

Step 2: Embedding GTM in the Global Layout

To enable GTM and the RootInnerLayout, we’ll update the global layout file (layout.tsx) to include these components.

Modify layout.tsx

Update the existing src/app/layout.tsx file with the following code:

import type { Metadata } from 'next'
import localFont from 'next/font/local'
import './globals.css'
import { GoogleTagManager } from '@/components/tracking/GoogleTagManager'
import { IS_GTM_ENABLED } from '@/libs/tracking/config.tracking'
import { RootInnerLayout } from '@/components/layouts/RootInnerLayout'
 
const geistSans = localFont({
  src: './fonts/GeistVF.woff',
  variable: '--font-geist-sans',
  display: 'swap',
})
 
const geistMono = localFont({
  src: './fonts/GeistMonoVF.woff',
  variable: '--font-geist-mono',
  display: 'swap',
})
 
export const metadata: Metadata = {
  title: 'NextJS with GTM & Consent Mode',
  description:
    'Integrate Google Tag Manager and Consent Mode into a NextJS 15 application with user privacy in mind.',
}
 
export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en" className={`${geistSans.variable} ${geistMono.variable}`}>
      <body
        className={`${geistSans.variable} ${geistMono.variable} antialiased`}
      >
        {IS_GTM_ENABLED && <GoogleTagManager />}
        <RootInnerLayout>{children}</RootInnerLayout>
      </body>
    </html>
  )
}
TSX

Explanation

  1. GTM Integration:

    • The GoogleTagManager component is conditionally rendered based on the IS_GTM_ENABLED configuration flag, ensuring GTM scripts only load when a valid GTM ID is provided.
  2. Cookie Consent Banner:

    • The RootInnerLayout wraps the entire application and includes the consent banner, ensuring it is displayed consistently across all pages.

Summary

In this phase, we integrated GTM and the cookie consent banner into the global layout:

  1. RootInnerLayout:
    • A reusable component for managing cookie consent and global UI elements.
  2. GTM in Global Layout:
    • GTM scripts are conditionally embedded across the app, ensuring analytics functionality while respecting user preferences.

With this integration complete, your application is now fully equipped with analytics, user consent management, and a scalable global layout structure. Congratulations on completing the tutorial! 🎉


Testing the Full Integration

After completing the implementation, it’s essential to test the integration to ensure everything functions as expected. Google Tag Manager (GTM) events, such as consent initialization and updates, must be verified to confirm proper tracking and consent mechanisms.

In this section, we’ll guide you through visual testing, verifying consent mechanisms, and inspecting event tracking using Google Tag Assistant. Additionally, we recommend referring to Google’s official guide for detailed instructions on setting up and using Tag Assistant effectively.


Step 1: Perform a Visual Test

Start by visually inspecting your implementation in the browser to confirm the behavior of the cookie banner and consent mechanism:

  1. Open the Site:

    • Navigate to your application in the browser (e.g., http://localhost:3000).
  2. Confirm the Cookie Banner:

    • On the first load, the cookie banner should appear at the bottom of the page.
    • The banner will display the consent message and the acknowledgment button.
    Implementation Complete - Initial Cookie Banner
  3. Acknowledge the Banner:

    • Click the acknowledgment button. This action will:
      • Write consent information to the cookie specified in your configuration.
      • Trigger the grantConsentForEverything function to update the consent state.
  4. Refresh the Page:

    • Reload the page. The cookie banner should no longer appear, as the consent state is now stored in the cookie.
  5. Repeat for Testing:

    • Clear your cookies and reload the site to ensure the cookie banner reappears, confirming the consent state depends on cookie storage.

Verify Cookie Behavior

Make sure the consent cookie is written correctly and persists between page reloads. Use your browser’s developer tools to inspect the cookieConsent cookie value under the "Application" tab.


Step 2: Setting Up Google Tag Assistant

After confirming the visual behavior, use Google Tag Assistant to verify GTM event tracking and consent initialization. Follow these steps to configure and connect the debugger:

  1. Access Tag Assistant:

  2. Enable Tag Assistant Debug Mode:

    • Click the Enable Debug Mode button.
    • Enter the URL of your development environment (e.g., http://localhost:3000).
    • Click Start to launch a new browser tab with debugging enabled.
  3. Verify the Debug Connection:

    • Return to the Tag Assistant interface and confirm the debugger is connected to your development environment.

For more details on configuring Tag Assistant, refer to Google's official setup guide.


Step 3: Examining Key Events

Once Tag Assistant is running, you’ll use the debug interface to inspect the GTM events triggered by your application. Below are two key events to verify:

The Consent Default event initializes when the application loads. By default, all consent options (e.g., analytics and ad personalization) are set to Denied, ensuring compliance with privacy regulations such as GDPR and CCPA.

  • Expected Behavior:
    • The "On-page Default" column should display Denied for all options (e.g., ad_storage, analytics_storage).
    • The corresponding gtag function call should indicate "consent": "default".

Here’s a visual example of the Consent Default event:

Consent Default Event in Google Tag Assistant

The Consent Update event occurs when a user interacts with the cookie banner and provides consent. When this happens, the consent status transitions to Granted, enabling analytics tracking and other services.

  • Expected Behavior:
    • The "On-page Update" column should display Granted for all options (e.g., ad_storage, analytics_storage).
    • The corresponding gtag function call should indicate "consent": "update" with granted permissions.

Here’s a visual example of the Consent Update event:

Consent Update Event in Google Tag Assistant

Step 4: Validating the Integration

After verifying the events, ensure that GTM is functioning as intended across your site:

  1. Navigate the Site:

    • Use your site as a typical user would, navigating between pages and interacting with elements.
    • Confirm that the pageview event is triggered on route changes.
  2. Check the Data Layer:

    • In the Tag Assistant debugger, inspect the Data Layer tab to verify that all expected variables (e.g., gtm.start, page_path) are populated.
  3. Verify Consent Persistence:

    • Reload the site and ensure that the consent state (e.g., Granted or Denied) persists based on the user’s prior input.
  4. Debug Any Issues:


Next Steps

With the testing phase complete, your GTM and Consent Mode integration should now be ready for production. By using tools like Tag Assistant, you ensure compliance with privacy regulations while maintaining robust analytics tracking.

If you encounter any issues or need to scale this implementation further, consider adding additional GTM triggers, refining your cookie banner design, or consulting the Google Tag Manager Help Center.


Conclusion: Achieving Analytics and Compliance Harmony in NextJS

That's it! You've successfully integrated Google Tag Manager (GTM) with Consent Mode in your NextJS 15 application, creating a privacy-compliant analytics solution that respects user consent 🥳

Successful nextjs and google tag manager integration

Here's a quick recap of what we accomplished:

  • Setting Up Tracking Utilities:
    • Configured GTM for environment-based flexibility.
    • Implemented reusable utilities for sending events, granting consent, and tracking user behavior.
  • Adding GTM Components:
    • Built a script loader and wrapper for cached consent management.
    • Enabled dynamic route-based page tracking and event initialization.
  • Integrating GTM into the Application:
    • Added a global cookie consent banner with react-cookie-consent.
    • Seamlessly incorporated GTM tracking into the app layout.
  • Testing the Integration:
    • Verified consent states and event triggers using Google Tag Assistant.
    • Ensured compliance with GDPR/CCPA while maintaining robust analytics.

By implementing these steps, you've created a scalable solution that respects user consent while enabling powerful data collection for actionable insights.

Next Steps

Now that you've laid the foundation, here are some suggestions for further enhancement:

  • Advanced Analytics Configuration: Add triggers for custom events like button clicks, video plays, or form submissions.
  • Dynamic Consent Preferences: Allow users to modify their consent settings via a dedicated preferences center.
  • Multi-Language Support: Localize your cookie banner to provide a consistent experience for global audiences.
  • A/B Testing Integration: Incorporate tools like Google Optimize to conduct data-driven experiments.
  • Performance Optimization: Monitor and optimize your implementation to minimize impact on page load speeds.

Expanding your integration with these features ensures you stay ahead in delivering value to users while maintaining compliance.


Partner with Aclarify for Your NextJS Success

Implementing GTM and Consent Mode is just the beginning. Scaling analytics while adhering to privacy regulations can be challenging, but that's where Aclarify can help. Our expert team specializes in building custom NextJS solutions tailored to your business needs.

Why Choose Aclarify?

  • Proven Expertise: We bring years of experience in integrating analytics and compliance solutions with NextJS, ensuring a seamless implementation.
  • Tailored Solutions: Every business is unique, and we deliver personalized solutions designed to meet your specific requirements.
  • Ongoing Support: From deployment to optimization, we provide continuous support to ensure your system performs at its best.

Let's Build Something Exceptional Together

Imagine having an analytics system that not only respects user consent but also empowers your team with actionable insights. Picture a future where your website becomes a data-driven powerhouse while remaining fully compliant with global privacy standards.

At Aclarify, we make this vision a reality.

Partner with Aclarify for Your NextJS Integration Needs

Our team at Aclarify specializes in NextJS integrations with Google Tag Manager, Consent Mode, and more. Let us help you create a compliant, data-driven, and high-performing web experience tailored to your goals.

More articles

5 Benefits of IT Support and Maintenance Services for HVAC, Plumbing, and Electrical Businesses

Discover how Aclarify’s specialized IT support and maintenance services boost efficiency, cut costs, and enhance customer satisfaction in HVAC, plumbing, and electrical industries.

Read more

5 Common Pitfalls to Avoid When Building ServiceTitan Integrations

Discover how to sidestep the five most common mistakes in ServiceTitan integrations and optimize your operations with insights from Aclarify.

Read more

Tell us about your project

Our offices

  • New Hampshire
    195 Carley Rd
    Peterborough, New Hampshire
    03458 USA
  • California
    1155 5th St, 406
    Oakland, California
    94607 USA