🎧

Next.jsでは、HeadにScriptタグは使えません!

2022/09/07に公開

最初に結論

Next.jsには、Headタグ内にScriptタグが入った場合はScriptタグを無視するという仕様があります
No Script Tags In Head Component

v11からの仕様のようでした
https://nextjs.org/docs/basic-features/script > Version History

v11.0.0 next/script introduced.

どうしたらいい?

Headタグの外に、Scriptタグを書きましょう
Headタグに含めなければ、自動で<body>に入ります

import Head from 'next/head'
import Script from 'next/script'

export default function App({ Component, pageProps }: AppProps) {
  return (
    <>
      <Script src="..." />
      <Component {...pageProps} />
    </>
  )
}

経緯

そもそもは、next.jsのチュートリアルで作ったアプリに、GTM (Google Tag Manager) を設置しようと思ったことがきっかけです

最初の実装

最初はReact/GTMのワードで調べて、「Reactでも、普通のアプリと同じように<head>内に置けばいい」とわかり、下記のように書きました

  1. GTMタグを component として作成して
// components/gtm.tsx
import Script from "next/script";

export const GoogleTagManager: React.FC<{
  googleTagManagerId: string;
}> = ({ googleTagManagerId }) => (
  <Script
    id="gtm"
    strategy="afterInteractive"
    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','${googleTagManagerId}');
      `,
    }}
  />
);
  1. (全ページ共通のLayoutコンポーネントがあるので、)Head内で読み込み
// components/layout.tsx
import { GoogleTagManager } from "./gtm";
...
<Head>
  <GoogleTagManager googleTagManagerId={/*GTM_TAG*/} />
  ...
</Head>

が、どんなにローカルを更新しても、GTM用の<script>タグが出てこない…🤔

警告も出てなさそうだしなんで??と悲しみつつ、
React/Next/head/scriptのワードで調べ直したところ、
最初に紹介した、公式ドキュメントにたどり着き、仕様だということがわかりました!
No Script Tags In Head Component

最終的な実装

最初に紹介したコードとほぼ同じですが、下記のようになりました
https://github.com/hatsumihayashi/next-app/blob/main/pages/_app.tsx#L5-L24
開発者ツールにて、GTM用の<script>タグが読み込まれているのも確認できました😆

残念ながら<body>の下の方に表示になってしまって、 GTMの推奨位置(<head>の一番上)とは違う位置になってしまったのですが、表示されないよりいいでしょう😆

実はESLintにはちゃんとエラーがあった

今回、最初からGTM専用のコンポーネントを作ってしまったことも、私がしばらくエラーに気づけなかった原因の一つでした
Headの中にScriptタグそのものがある場合は、きちんとESLintのエラーが表示されました

公式の実装例

Next.jsはチュートリアルはもちろん、実装例も豊富です
GTM設置用の実装例もありました
https://github.com/vercel/next.js/tree/canary/examples/with-google-tag-manager
ここでは当然、Headの外にScriptタグが書かれています
https://github.com/vercel/next.js/blob/canary/examples/with-google-tag-manager/pages/_app.js#L15-L33
が、散々Headを追っていた自分の目には、Componentタグが全然入ってこず…😱
「なんで同じようなScriptタグ置いてるのにダメなんだろう…」と思って、気づくまでに時間がかかりました😭

これから、Next.js始めよう! & GAやGTMを設置しよう!と思っている方は、ぜひ最初にexamplesフォルダを見てみてください!😉
https://github.com/vercel/next.js/tree/canary/examples

Discussion