Asynchronous Trackingが導入された

2009/12/06 書き直した。2010/06/05 非同期読み込みの話について訂正した。

昨日発表されたGoogle Analyticsのtracking codeの読み込みを非同期にして、読み込み終了時に、指定した関数を実行させる方式。についてです。

経緯と背景(たぶん)

Google Analyticsはjavascriptを読み込んで、cookieをいじって、googleのサーバーにリクエストを飛ばす仕組みです。

このjavascript(GATC)は、今まで、</body>の直前の置く事が推奨されていました。理由は、javascritpはブラウザのレンダリング(もしくはparsing??同じタイミングで両者とも実行??)を停めるからです。停めるものは、最後におきましょうという事でした。javascriptは読み込み時間を遅くする要因になります。たくさんのjavascriptを実行する時に問題になる部分です。

ところで、HTML5では、scritpタグの属性としてasyncというものが出来ました。これはブラウザの読み込みを停めずに読み込みを行う方法が策定されています。また、ほとんどのブラウザで実装されてきました。そこで、この新しい機能のasyncを利用した形が今回のasynchronous trackingだと思います。

違った。 ここが詳しい。Google Analytics 非同期トラッキングコード再考

ブラウザの実行をblockしないテクニックの一つとして、Script要素をDOMで作って挿入する方法で読み込みを非同期にしていると。勉強になりました。

具体的には、上のリンク先かここにコードの例がいくつも載っているので、コピペするのが良いと思います。

実現方法は?

あらかじめ、htmlファイルの<head>内でメソッド名と引数をwindowプロパティの_gaqに入れておく。読み込んだコード(ga.js)が非同期で読み込みが終了すると、実行に移る。その時に、そのga.js内のオブジェクトのコンテキストで、_gaqに設定したメソッド、引数を実行する。メソッド名.apply(オブジェクト, [引数]) という形。

実際のコード(ga.js)部分を抜き出すと、(* これは、2009/12ごろのcode version4.5.9。2010/06/05では version4.7.2)

var $ = {
    ca: {},
    _createAsyncTracker: function (f, i) {
      i = i || "";
      f = new Z.aa(f);
      return $.ca[i] = f
    },
    _getAsyncTracker: function (f) {
      f = f || "";
      var i = $.ca[f];
      if (!i) {
        i = new Z.aa;
        $.ca[f] = i
      }
      return i
    },
    push: function () {
      for (var f = arguments, i = 0, b = 0; b < f[z]; b++) try {
        if (typeof f[b] === "function") f[b]();
        else {
          var j = "",
            c = f[b][0],
            p = c.lastIndexOf(".");
          if (p > 0) {
            j = P(c, 0, p);
            c = P(c, p + 1)
          }
          var m = $._getAsyncTracker(j);
          m.apply(m, f[b].slice(1))
        }
      } catch(q) {
        i++
      }
      return i
    }
  };
  window["_gat"] = Z;
  var la = window["_gaq"];

  function na() {
    var f = window["_gaq"],
      i = w;
    if (f && typeof f.push == "function") {
      i = f.constructor == Array;
      if (!i) return
    }
    window["_gaq"] = $;
    i && $.push.apply($, f)
  }
  na();

*番号は僕が勝手に付けたものです。

番号40より後ろのna()部分を見る。<head>の部分で設定した window[“_gaq”]の部分をfに退避させて、上で設定した$のメソッドpushを実行する。番号17からのpushでは関数オブジェクトならそのまま実行する。そうでないものは、pageTrackerオブジェクトのメソッド、引数として実行するようになっている。普通の関数も実行してくれるので、自分専用のgoogle analytics関数の定義が終了していたら、ここで実行してもOK.

ga.jsが非同期でloadされ実行されると、naが実行され、今、説明したような動きで、_gaqに設定したメソッド、引数を実行するという事です。_gaqの設定は、ドキュメントにあるように、

var _gaq = _gaq || [];

_gaq.push([])

の部分です。

なんらかの?状態で、先にコードが読まれた場合にも、pushはArrayのコンテキストではなく、$のコンテキストで実行されるようになっています。なので、順番が狂っても動くと思う。

思うこと

これで、ビーコン型の持つ弱点の一つが減ったと思います。サイトに手を入れていくと、javascriptが氾濫するようになるけど、こういう形は読み込みを邪魔しない。是非とも、他のアクセス解析ツールでも採用して欲しい。

おまけ。

このasynchronousは、コード自体は、versionが4.5.8の時に導入されていた(今は4.5.9)。

昨日、4.6.5というのも見かけたけど、いなくなった。10月以来の変更に伴うばたばた感?が続いてる感じもする。

登録メールアドレスに、google analyticsチームからメールが配信されて、10月以来導入された新機能の紹介が入っていた。移行に伴うタスクをいろいろとこなしてる最中なのかな?

他の機能では、CustomVariableが、アドバンスセグメントの所でしか登場しないけど、ユーザ定義が廃止されるので、代わりに通常のレポート画面に現れてくる事を期待。

外部リンクの計測も、近い内に実現するような気がしてきた。コード内での大まかな実装は済んでいる。