javascriptnext.jsgoogle-tag-manager

How to load Google Tag Manager with next/script component (Next.js 11)?


Next.js v11 released a new Script component which has different strategies.

It is recommended to load Google TagManager with afterInteractive strategy.

I've tried

// _app.js

import Script from 'next/script';

class MyApp extends App {
  public render() {
    const { Component, pageProps } = this.props;

    return (
      <>
        <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-XXXXXXX');`}
        </Script>
        <Component {...pageProps} />
      </>
    );
  }
}

export default MyApp;

It works fine, it loads google tag manager, but the problem is that it injects the same script on every page nav, which makes duplicate tags.

How to utilize the new Script component?


Solution

  • You must set an id to your <Script> component because it has inline content (no src attribute).

    Next can check if it has been already rendered or not and you will not have these duplications.

    This is the eslint rule associated from Next :

    next/script components with inline content require an id attribute to be defined to track and optimize the script.

    See: https://nextjs.org/docs/messages/inline-script-id

    So your solution could be :

        <Script id="gtm-script" strategy="afterInteractive">{`...`}</Script>
    

    You should probably also install eslint for your next project :
    Either run next lint or install eslint next config :

    yarn add -D eslint eslint-config-next
    

    and define the file .eslintrc.json with this content at least :

    {
      "extends": ["next/core-web-vitals"]
    }
    

    Information about next.js eslint configuration.