Google アナリティクスのトラッキングコードを外部ファイルで共通化する

はじめに

実務にて、ライブラリやプラグインを利用しないで、Google アナリティクスのトラッキングコードを外部ファイルで共通化してほしいという小仕事の依頼があり、それを解決した情報になります。HTML5 で非推奨の document.write() は利用しません。

ソースコード

GA_MEASUREMENT_ID には、ご自身の Google アナリティクスプロパティ ID を記述してください。

const GA_MEASUREMENT_ID = 'xx-xxxxxxxxx-x'
var newScript = document.createElement('script')
newScript.async = true
newScript.src = `https://www.googletagmanager.com/gtag/js?id=${GA_MEASUREMENT_ID}`
var firstScript = document.getElementsByTagName('script')[0]
firstScript.parentNode.insertBefore(newScript, firstScript)
window.dataLayer = window.dataLayer || []
function gtag() {dataLayer.push(arguments)}
gtag('js', new Date())
gtag('config', GA_MEASUREMENT_ID)

検証環境

解説

JavaScript で解決する

JavaScript で解決する場合、ソースコードをコピペ(コピー&ペースト)した外部ファイル(JavaScript ファイル)を作成して、head タグの直後に script タグで読み込む。

ソースコードが少々複雑に見えると思いますが、document.write() メソッドを利用しない、且つ追加した script タグを実行させるには工夫が必要でした。

下記のソースコードは document.write() を利用している例です。

document.write('<script async src="https://www.googletagmanager.com/gtag/js?id=xx-xxxxxxxxx-x"></script>')

document.write() を利用しない理由は下記になります。

  • HTML5 で非推奨 になっている。
  • deferred または asynchronous のスクリプト内では無視される。
  • Chrome 55 からは、キャッシュされていない HTTP の場合、document.write() を通じて挿入された script 要素は実行されなくなる。
  • 後続の DOM 要素のレンダリングを妨げるので、ページ表示速度が遅くなり SEO に影響がでる。

これは document.write() の邪悪な力の片鱗です…

回避策として Node.insertBefore() メソッドを利用して代替します。

firstScript.parentNode.insertBefore(newScript, firstScript)

因みに、下記のように insertAdjacentHTML() メソッドを利用した場合は、挿入した script タグが実行されないので代替となりませんでした。

document.head.insertAdjacentHTML('afterbegin', `<script async src="https://www.googletagmanager.com/gtag/js?id=${GA_MEASUREMENT_ID}"></script>`)

script タグを挿入する親要素について、Safari などのブラウザによっては head 要素がない場合があるので、汎用性を持たせる為に head 要素を回避しています。

var firstScript = document.getElementsByTagName('script')[0]

このような DOM の沼に足を取られる余裕がない方は、PHP で解決することをおすすめします。

PHP で解決する

PHP で解決する場合、Google アナリティクスのトラッキングコードをコピペ(コピー&ペースト)した外部ファイル(PHP ファイル)を作成して、head タグの直後でインクルードします。

おわりに

本課題を解決するにあたって、stevesouders.com にある appendChild vs insertBefore の情報はかなり貴重でした。

参考