【React】PartytownでGoogle Analytics(Tag Manager)のスクリプトをWeb Worker上で実行する
やりたいこと
以前、Next.js製のサイトにGoogle Analytics(GA4)を導入した。
【Next.js】SPAにGoogle Analytics(GA4)を導入する
しかしnext/script
を用いて読み込みを最適化しているものの、90kb近いサイズのスクリプトをメインスレッドで実行しているためページのロード時間に多少影響がある。
PageSpeed Insightsでも上記のように「使用していないJavaScriptの削減」の項目で怒られてしまう。
そこでパフォーマンス改善のためにも、Partytownを用いてそのサードパーティのスクリプトをWeb Worker上で実行してみる。
※ちなみにnext/script自体がPartytownをサポートしているもののそれはApp Directoryのみで使用可能なため、今回はフレームワークの機能に頼らない素の<script>
タグを用いる方法で導入する。
解決法
基本的には公式ドキュメントに沿えば問題ない。
1. Partytownのインストール
npm i @builder.io/partytown
2. コンポーネント作成
const ScriptGa = () => { return ( <> <script src={`https://www.googletagmanager.com/gtag/js?id=<GTAG_ID>`} /> <script dangerouslySetInnerHTML={{ __html: ` window.dataLayer = window.dataLayer || []; function gtag() { dataLayer.push(arguments); } gtag("js", new Date()); gtag("config", '<GTAG_ID>'); `, }} /> </> );};
export default ScriptGa;
まずGoogle Tag Managerで発行されるスクリプトをほぼそのままコンポーネント化する。<GTAG_ID>
には発行されるIDを指定。
import { Partytown } from "@builder.io/partytown/react";
const ScriptGa = () => { return ( <> <Partytown forward={["dataLayer.push"]} /> <script type="text/partytown" defer src={`https://www.googletagmanager.com/gtag/js?id=<GTAG_ID>`} /> <script type="text/partytown" defer dangerouslySetInnerHTML={{ __html: ` window.dataLayer = window.dataLayer || []; function gtag() { dataLayer.push(arguments); } gtag("js", new Date()); gtag("config", '<GTAG_ID>'); `, }} /> </> );};
export default ScriptGa;
Partytown用に少し手を加える。
- 対象のスクリプトに
type="text/partytown"
を追加 Partytown
コンポーネントを追加- Google Tag Managerで発行されるスクリプト内のイベントを転送するために
forward={["dataLayer.push"]}
を指定
- Google Tag Managerで発行されるスクリプト内のイベントを転送するために
- 非同期に実行するために
defer
を指定(任意)
3. ライブラリファイルのコピー
ライプラリファイルを同オリジンから提供する必要があるので、public
下に配置していく。
{ "scripts": { "build": "next build", "build": "npm run partytown && next build", "partytown": "partytown copylib public/~partytown" }}
ライブラリ側でCLIが用意されているので、package.json
にてタスクを登録し実行すれば必要なファイルが勝手に配置される。ちなみに当サイトでは上記のようにbuild
タスク実行前にコピーするようにした。
これで導入は完了。Google Analytics Debuggerでテストしたところ正常にトラッキングされていた。