【React】PartytownでGoogle Analytics(Tag Manager)のスクリプトをWeb Worker上で実行する

やりたいこと

以前、Next.js製のサイトにGoogle Analytics(GA4)を導入した。

しかしnext/scriptを用いて読み込みを最適化しているものの、90kb近いサイズのスクリプトをメインスレッドで実行しているためページのロード時間に多少影響がある。

PageSpeed Insightsでも「使用していないJavaScriptの削減」の項目で怒られてしまう

PageSpeed Insightsでも上記のように「使用していないJavaScriptの削減」の項目で怒られてしまう。

そこでパフォーマンス改善のためにも、Partytownを用いてそのサードパーティのスクリプトをWeb Worker上で実行してみる。

※ちなみにnext/script自体がPartytownをサポートしているもののそれはApp Directoryのみで使用可能なため、今回はフレームワークの機能に頼らない素の<script>タグを用いる方法で導入する。

解決法

基本的には公式ドキュメントに沿えば問題ない。

1. Partytownのインストール

Terminal window
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"]}を指定
  • 非同期に実行するために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でテストしたところ正常にトラッキングされていた。