Next.jsPagesRouterでGoogleTagManagerをheadタグに挿入する
Next.jsのPagesRouterを採用している案件で、 <head> タグにGoogleタグマネージャーを挿入する依頼があり、少々手こずったのでメモ。
まず、全てのページの <head> に含めたかったので  _document.tsx に以下のように記載してみる。
// _document.tsx
import { Html, Head, Main, NextScript } from 'next/document'
 
export default function Document() {
  return (
    <Html lang="ja">
      <Head>
	      <GoogleTagManager />
      </Head>
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  )
}
// GoogleTagManager.tsx
import { Script } from 'next/script'
export const GoogleTagManager = () => (
	<Script
		// ...省略
	/>
)
しかしこれでは head に表示されなかった。(ブラウザレンダリング後のDOMとHTMLレスポンスどちらも)
なので、以下のように Script を直接 _document.tsx に記載してみる。
export default function Document() {
  return (
    <Html lang="ja">
      <Head>
				<Script
					// ...省略
				/>
      </Head>
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  )
}
するとブラウザレンダリング後のDOMの head タグにGTMが表示された。
(ただ、HTMLレスポンスには含まれていないのでクライアント側で生成されたっぽい)
公式ドキュメントを見てみる👀
どうやら strategy プロパティを使用すると Script の実行タイミングを操作できるみたい🧐
- beforeInteractive: サーバー側で初期 HTML に挿入される
- afterInteractive: クライアント側でハイドレーション発生後に挿入される
- lazyOnload: クライアント側で全てのリソースを取得した後に挿入される
他にも worker や onLoad …などあるがタイミングを操作できるのは👆の3つっぽい。
なので、👆の中の beforeInteractive を使用したらサーバー側で head に挿入してくれる。
// _document.tsx
import { Html, Head, Main, NextScript } from 'next/document'
 
export default function Document() {
  return (
    <Html lang="ja">
      <Head>
				<Script
					strategy={beforeInteractive} 👈ここに記述
					// ...省略
				/>
      </Head>
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  )
}
これで初期 HTMLの head にも含まれていてブラウザのDOMにも表示されたので一件落着🙌
最近はNext.jsのAppRouterを使うことが多いので本件はだいぶ手こずった💦
だいぶAppRouter色に染まってしまっている。。。