はじめに
前置きが不要な方は、解決方法の節まで飛ばしてください。
以前からGoogle Analyticsでブログのアクセス数やreferrerなどを見ていました。HexoやHugoといった静的ブログなら、headタグにJavaScriptを追加するだけで簡単に導入できます。先日ブログをAstroに移したのですが、従来どおりheadでJavaScriptを実行してイベントを送信すると、性能が落ちます。ご存じのとおり、Astroはフロントエンドの性能を追求し、JavaScriptの実行をできるだけゼロに抑える方針です。イベント送信のためにJavaScriptを動かすと、その分だけ性能を損なってしまいます。

調べてみると、多くの解説がpartytownでスクリプトをメインスレッドの外に移し、読み込みをブロックせず性能を保つ方法を紹介していました。サンプルコードもあったので、それをもとにブログへ組み込んだ結果がこちらです。

計測数が見事にゼロになりました。
さすがに笑えません。長い調査が始まりましたが、原因はどうしても見つかりませんでした。ネット上の関連サンプルはどれも私と同じやり方です。解説を書いた人たちは自分で試していないのでしょうか。まったく動かないんですが。
仕方なく2か月ほど放置し、その間は一時的にumamiで計測していました。
ここ数日でまた思い出し、気になって仕方がなくなったので、再び延々と検索しました。ようやくGitHubの片隅で解決策を見つけました。
解決方法
パッケージマネージャーで@astrojs/partytownをインストールします。
<head>タグに次のコードを追加します。
<script is:inline src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXX" type="text/partytown"></script>
<script is:inline type="text/partytown">
window.dataLayer = window.dataLayer || [];
window.gtag = function () {
dataLayer.push(arguments);
};
window.gtag('js', new Date());
window.gtag('config', 'G-XXXXXXXXX');
</script>
注意点は次のとおりです。
is:inlineはスクリプトをクライアント側で実行する指定です。type="text/partytown"は、メインスレッドではなくpartytownで実行する指定です。gtagは関数宣言ではなく、windowオブジェクトの変数に関数を代入する形で定義する必要があります。妙な話ですが。
Astroの設定ファイル(通常はastro.config.tsやastro.config.mjs)に次の設定を追加します。
import partytown from '@astrojs/partytown'
export default defineConfig({
// ...
integrations: [partytown({ config: { forward: ['dataLayer.push', 'gtag'] } })],
});
ほとんどの解説には、forward配列にgtagも追加する必要があることが書かれていません。
これで完了です! コミットしてデプロイすると、Google Analyticsに正常にデータが送られるようになります。
