つい先日出ましたね。GoogleTagManager(=以下GTM)
最近仕事て使う機会が増えてきたので自分用メモがてらちょこちょことまとめて行こうと思いますよっと。
概要
ざっくりどんなものかを説明すると、
管理画面にアクセス出来る人がタグマネージャを使用したいドメインを設定し、コンテナと呼ばれるタグの集合体を管理する箱を作成。 発行されるタグを対象ドメインに貼り付け、独自のタグや独自のスクリプトを記述したタグを設定し、 公開ボタンをぽちっとするだけで3で作成したコンテナがサイトに埋め込まれる。
これだけでサイトがいじれてしまうという優れもの。 メリットデメリットは他の人も触れているみたいなので、 今回フォーカスしたいのはイベントについて。
タグ読み込みとイベントのタイミング
ご存知の通り、GTMはタグの読み込まれる順番を指定できない。これが非常に厄介。 けども、任意のタイミングで何かを行うscriptを記述したい場合、適切なタイミングで実行する方法が用意されている。
未知との遭遇にハマったのでリファレンス見たり、内部読んでみて自分なりに調べてみた。(間違っていたら指摘いただけると幸いです)
gtm.jsgtm.jsがscriptタグで
documentにappendされたタイミングでのタグの実行DOMの状態はページや環境によるのでここでDOMを使っての操作は行わないほうが無難
gtm.domDOMContentLoadedのタイミングでのタグの実行DOMが準備されているので要素を操作する際に最適
gtm.loadwindow.onloadのタイミングでのタグの実行ブラウザのレンダリングが完了している段階なので操作は出来るだけ少なめにしたいところ
と、3つのイベントのタイミングを用意しているみたい。 ただ、何も指定しなかった場合は具体的にどのタイミングで読み込まれるのだろう?という疑問点もあるので後々調べて追記予定。
4/16追記
どうやら上で書いたイベントのタイミングは大嘘だったようだ。。。 上で書いたのは今自分が触っているページにのみ起こる事象で、ページによってだいぶかわってくるみたい。
で、さっそくテストケースを用意して試してみた。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>gtm</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
</head>
<body>
<noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-XXXX"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<script>
window.addEventListener('DOMContentLoaded', function () {
console.log('window.DOMContentLoaded', new Date().getTime(), document.getElementById('elem'));
});
document.addEventListener('DOMContentLoaded', function () {
console.log('document.DOMContentLoaded', new Date().getTime(), document.getElementById('elem'));
});
$(function () {
console.log('$(document).ready()', new Date().getTime(), document.getElementById('elem'));
});
window.addEventListener('load', function () {
console.log('onload', new Date().getTime(), document.getElementById('elem'));
});
(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 = '//www.googletagmanager.com/gtm.js?id=' + i + dl;
console.log(w[l], new Date().getTime(), document.getElementById('elem'));
f.parentNode.insertBefore(j,f);
})(window, document, 'script', 'dataLayer', 'GTM-XXXX');
</script>
<a id="elem" href="#">test</a>
<div></div>
<div></div>
.
.
.
<!-- divの繰り返し -->
.
.
<div></div>
<div></div>
</body>
</html>
GTM上で前述の3つの各タイミング + 無指定(=ここではunknownと表示)でnew Date().getTime()でミリ秒を取得し、
console.logを実行してどういったタイミングでGTMのイベントが行われているのかを厳密に調べてみた。
環境によってかなりの差があることがわかる。
このあたりはブラウザのAsynchronous Loadingが密接に関係しているのだろう。
でも、結果を見て思うのはgtm.domでDOMは確実に用意されているので、DOMが必要な処理の際はgtm.domで実行するのがいいのかも。
参考 CSS/JavaScriptのAsynchronous Loadingをめぐる熱い論議
上記ソースコードの<!-- divの繰り返し -->の部分にリソースのロードを挟んでいたらまた挙動が変わってくるのだろう。
またそっちも後日テスト予定。
GoogleAnalyticsとの併用について
やっと本題です。
GTM使うとなると更に組み合わせたくなるのがGoogleAnalytics(=以下GA)。 これで現在推奨されている第三世代のコードを掛け合わせると、またまた厄介なことになる。
コードを見てみよう。
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-XXXXX-X']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
そう、async属性を指定している。
さっき紹介したGTMの3つのタイミング + ga.jsのロード時間も考慮しなくちゃならない。 何が怖いって、さっきの3つのタイミングでga.jsが確実にロードしている保証なんてどこにもないのである。
カスタム変数の値を見て、その値を元にページ内のとあるa要素を取得してそこにトラックイベントを飛ばすイベントハンドラをセットしたいなんて場合、
DOMContentLoadedのタイミングとga.jsのロードのタイミングが等価である保証は絶対にない。
まとめ
gtm.jsとga.jsを併用した場合、
windowまたはdocumentのロード状態とga.jsのロードのタイミングが等価である保証は絶対にないので、 GTMの設定は適切なタイミングを管理画面から設定して、ga.jsの読み込みを確認しながらscript書こうページの
nodeの数や閲覧ブラウザや通信状況などによってga.jsのロードタイミングもかわってくるよ解析士が開発しないなんて言う時代は終わったと声を大にして言いたい(自分は解析士じゃないので戯言)
おわり