Next 11 and adding Script tags not working. No scripts are rendered
Asked Answered
S

3

30

I added my google tag manager to _app.js file, and its not showing. None of the scripts I am loading via the new "Script" tag are working.

  <Head>
    <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no" />
    <Script
      src={`https://cdn.somelink.coom/${process.env.COOKIE_KEY}/block.js`}
      strategy="beforeInteractive"
    />
    <Script
      src="https://cdn.somelink.com/scripttemplates/stub.js"
      strategy="beforeInteractive"
    />
    <Script
      src={`https://www.googletagmanager.com/gtag/js?id=${process.env.GOOGLE_KEY}`}
      strategy="afterInteractive"
    />

These are not working. Nothing is downloaded in the network tab etc. Nothing shows up on the page. Any thoughts?

Reminder: this is in the _app.js file.

Note: My pages are static generated.

Spirt answered 20/6, 2021 at 18:17 Comment(1)
This might help https://mcmap.net/q/320373/-nextjs-public-folderLaclair
O
64

next/script should not be wrapped in next/head

Ref.: Script Component

Do something like this:

import Script from "next/script";

const App = ({ Component, pageProps }) => (
  <>
    <Script
      id="scriptAfterInteractive"
      src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js"
    />
    {/* eslint-disable-next-line react/jsx-props-no-​spreading */}
    <Component {...pageProps} />
  </>
);

export default App;
Omnipotence answered 20/6, 2021 at 19:54 Comment(7)
so, the only thing different here is you moved it out of the <Head tag?Spirt
Wow, the docs really should stress that more. Current version of the docs in April 2022 just says "It enables developers to set the loading priority of third-party scripts anywhere in their application, outside next/head, saving developer time..." Looks like it's a requirement though.Daryl
Looks like there's also some issues with wrapping it in the Html Next component too? If you're having difficulties with this, try burying the Script somewhere in a random component and see if it works, then work up from there.Daryl
I'm getting a "Failed to execute 'write' on 'Document': It isn't possible to write into a document from an asynchronously-loaded external script unless it is explicitly opened" when I do this. I have the strategy="beforeInteractive" and have tried all of the other kinds of strategy values as well. The web worker strategy is the only one that doesn't throw an error but still doesn't work.Adrianeadrianna
Regarding beforeInteractive strategy "only works inside _document.js and is designed to load scripts that are needed by the entire site" - nextjs.org/docs/basic-features/…Draughty
@AhmadM.Hawwash Yeah, it was updated in the last version. If you need to use that strategy in your pages, then you now need to do this: github.com/vercel/next.js/blob/… -- note that this is unstable right now and may change in future.Omnipotence
@Adrianeadrianna Adding defer={false} should fix the issue. See #72253319.Silverts
A
7

In addition to the requirement that Script (next/script) not be wrapped in Head (next/head), it should also not be placed within a custom _document.tsx unless you are not passing strategy="beforeInteractive" as mentioned in the docs.

I was unable to load a Cloudflare analytics script when placing it in _document.tsx, but it loaded successfully as a sibling to Component in _app.tsx.

Allisan answered 27/8, 2022 at 1:9 Comment(1)
Next.js v12.1 allowed adding to _document.js, but from v12.2 it does not. Only beforeInteractive supports in document.Lopez
S
1

This is a solution to add Google Tag Manager script in the head tag in NextJS 12

// pages/_document.js
import Document, { Html, Head, Main, NextScript } from 'next/document'

class MyDocument extends Document {
  render() {
    return (
      <Html>
        <Head>
          {/* Google Tag Manager */}
          <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');
              `,
            }}
          />
          {/* End Google Tag Manager */}
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    )
  }
}

export default MyDocument

and then:

// pages/_document.js
import Document, { Html, Head, Main, NextScript } from 'next/document'

class MyDocument extends Document {
  render() {
    return (
      <Html>
        <Head>
          {/* Google Tag Manager */}
          <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');
              `,
            }}
          />
          {/* End Google Tag Manager */}
        </Head>
        <body>
          {/* 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) */}
          <Main />
          <NextScript />
        </body>
      </Html>
    )
  }
}

export default MyDocument
Suffuse answered 12/6 at 7:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.