はじめに
実務にて、ライブラリやプラグインを利用しないで、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 / マニュアル
- Google Chrome 83.0.4103.116
- Safari 13.1.1
解説
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 の情報はかなり貴重でした。