[Astro] Google Tag Manager(GTM)を静的サイトに入れる
TechWordPress 時代に使っていた Google Tag Manager(GTM) を、Astro でも入れ直しました。GTM のスニペットは「<head> 用」と「<body> 直後の noscript 用」の2つがあるので、その両方を Astro で素直に配置します。
コンポーネントにまとめる
GTM の head 用スニペットをコンポーネント化します。ID はサイト定数から渡す形に。Astro にバンドルさせたくないので is:inline を付けます。
---
// src/components/GoogleTagManager.astro
import { SITE } from '@/data/site';
---
<!-- Google Tag Manager -->
<script is:inline define:vars={{ gtmId: SITE.gtmId }}>
(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',gtmId);
</script>
<!-- End Google Tag Manager -->
define:vars で frontmatter の値(gtmId)をインライン script に渡せるのが便利です。ID は src/data/site.ts あたりに置いておきます。
export const SITE = {
// ...
gtmId: 'GTM-XXXXXXX',
} as const;
レイアウトに配置する
<head> のできるだけ上にコンポーネントを置き、<body> 直後に noscript 版を置きます。
---
// src/layouts/BaseLayout.astro
import GoogleTagManager from '@/components/GoogleTagManager.astro';
import { SITE } from '@/data/site';
---
<html lang="ja">
<head>
<GoogleTagManager />
<meta charset="utf-8" />
<!-- ... -->
</head>
<body>
<!-- Google Tag Manager (noscript) -->
<noscript>
<iframe src={`https://www.googletagmanager.com/ns.html?id=${SITE.gtmId}`}
height="0" width="0" style="display:none;visibility:hidden"></iframe>
</noscript>
<slot />
</body>
</html>
noscript の iframe には is:inline は不要(script ではないので Astro がそのまま出力します)。
確認
ビルド後の HTML に GTM が入っているか見ます。
npm run build
grep -o "googletagmanager.com/gtm.js" dist/index.html
grep -o "GTM-XXXXXXX" dist/index.html
本番では GTM プレビュー(Tag Assistant)で発火を確認するのが確実です。
メモ
is:inlineを忘れると Astro が script をバンドルしようとして GTM の意図どおりに動かないことがある。インラインのまま出すのがポイント。- ID をコンポーネントに直書きせず
SITE.gtmIdに集約しておくと、head とも noscript とも共有できて管理が楽。 - 静的サイトでも GTM はクライアント側で動くので、WordPress 時代の設定(タグ・トリガー)はそのまま使い回せました。
Astro, GTM, アクセス解析