複数ドメインのtracking

Google AnalyticsのAPIの説明をしながら解説してみたい。

まず、Google Analytisはfirst party cookieを使ってデータを取得・送信している。first-party cookieとは、個々のドメインに対して機能するものなので、違うドメインのcookieとは、連携する事はできない。(行動ターゲティングなどは、画像一つ一つがドメインとなれる事を利用して、複数ドメインでのユーザーの行動追跡を可能にしている、たぶん)

とにかく、データ収集範囲は、ドメインに限定される。

(2010/03/07 cookieの値に関する限りです。google analyticsは、web property IDが同じなら、サイトが違っても、同じレポート上のデータとして扱う)

が、ドメインを超えて、データを収集したい。そこで、Google Analyticsでは、URLにデータを乗せて(post送信もURLにくっつく形)、遷移した別のドメインで、そのデータをga.jsが読み書きするになっている。

これを行うAPIは、_link, _getLinkerUrl , _linkByPost 3つ。同時に、_setAllowLinker(true)が、この3つが機能させるフラグ、trueで機能する、デフォルトはfalse。

また、_ga.jsの中で、ドメインの相違をcheckしているので、それを外すのが_setDomainName()。この引数には、デフォルトで “auto”(そのページのドメインが使われる) “none”(ドメインハッシュを1にする), または、自分で任意の文字列をドメインとして設定することもできるよう。

また、_setAllowHashというものもあり、引数をfalseにすると、ドメインハッシュを行わず、checkも行わない。よって、cookieのドメインcheckをせず、複数ドメインに対応可能になる。又、domain-hashをしないので、実行効率もあがるらしい。

サブドメインの間でデータを取る場合に、_setDomainName(“.sub.hoge.com”)のように、頭に ” . “ を書く事が推奨されているけど、この理由はよくわからない。これは、sub-domain共通でデータを取得してますというのを、わかりやすくするのが理由だろうか?
(2010/03/07 cookieは、.hoge.com のように書くと、サブドメイインでの値の共有になるとの事)

cookieの値の受け渡しができれば、ドメインハッシュ値を同じにして、ga.jsでのdomainチェックを通し、データを送信でき、複数ドメインでのデータを同じプロファイルで扱えることになる。

Iframeでも同様。Iframenも平行してアクセスがあると考える(ページ遷移などでレポートされる遷移の順番は、utmbの番号などを見れば、いいだろうか?)

また、注意するべき点として、setDomainNameは、できるだけ早い順番にかくべき。pageTracker変数を作った後に。_setVarなど(もう廃止項目だけど)を使う場合に、setDomainNameでドメインをそろえてないと、変更前のドメインとなるので、trackePageviewに反映されない。(_setVarの変更でリクエストは飛ぶけど、これも_setCustomVarだと飛ばないよう)なので、

  1. var pageTracker = _gat._getTracker(“UA-XXXXXX-11”)
  2. pageTracker._setDomainName(“none”);
  3. pageTracker._setAllowLinker(true);
  4. pageTracker._setVar(“hogehoge);
  5. pageTracker._trackPageview();

この順番で試したら問題なく、utmvの値も引き継げた。また、htmlの中のリンクに直接 pageTracker変数を使う(<a>タグのonclickなどで)なら、bodyの頭に、上記のコード(1-5)を入れる必要がある。

しかし、外部リンクにいちいち、pageTrackr._linkerなどと書いていくのは、実用上無理がある気がする。めんどくさい。

ので、下の記事にも書いたけど、一括でEventListenerに登録する方が漏れが少ないと思う。google analytics 外部へのリンクを計測する

closureの利用を考える

closure_memo_001
javascriptの高度なtopicといえば、closureだと思う。
理解が難しいと思う。カウンターを作ってみた時は感動したけど、なかなか理解が汎化していかない。それで、まとめを書いて見ることにした。
他にも、いろんなサイトを見て回った。
下のコードの例は、上の記事のものと全然違うものもあります。信頼性を求める人は上のリンクを辿って下さい。

setTimeoutでの関数の参照で使う

setTimeoutには、関数オブジェクトの参照か無名関数の定義式を入れる事になっている。setTimeout(ref_func_obj, seconds)

ただ、関数オブジェクトではなく、実行式を書きたい時は多い。fun()といった後ろに () が付く形。

そこで、引数をくるんで、引数なしの関数オブジェクトを返すようにする。org_funcが与えられていた時、引数を定義式の中に組み込んでしまう形のnew_funcを作り(参照させ)、それをsetTimeoutに使う。

Function.prototype.curry = function(arg){
  var self = this;
  return function(){
    self.apply(this, [arg]);
  };
};
var org_func = function(a){
  console.log(a);
};
new_func = org_func.curry("konitiwa");
function a(arg){
  setTimeout(new_func, 2000);
}

こんな感じかな?これをカリー化と言うのはまずいのだろうか?

Functionクラス(Functionオブジェクトのprototype)をOpen Class?するのは汚い方法かもしれないけど、しょうがない。

リンク先の記事では、オブジェクト、メソッド、メソッドへの代入式の3つをclosureして?新しい関数を作っている。

動的に作成したDomのイベントに関数を定義

動的にDomを作るconstructor関数を作ってやる。その時に、イベントでtriggerされる関数をつけてやりたい。でも、その関数の定義は外に出しときたい?(ここら辺、よく分かってない、、、)

オブジェクトとメソッド名を与えると、そのオブジェクト[メソッド名]という関数名(メソッド名)で、イベントと新規に作ったDomオブジェクトを引数に取る関数を作るようにする。

function associateObjWithEvent(obj, methodName){
  return function(e){
    e = e || window.event;
    return obj[methodName](e);
  };
}

これを、Domを作るconstructor関数に組み込む。thisのメソッドという形になる。

function DhtmlObject(elementType, id){
  var el = document.createElement(elementType);
  this.ele = el;
  el.id = id;
  el.innerHTML = "New Div";
  document.body.appendChild(el);
  if(el){
    el.onmouseover = associateObjWithEvent(this, "doMouseOver");
  }
}

そして、インスタンスメソッドとして、doMouseOverを定義すれば、この例だと、mouseoverでtriggerされるeventになる。

DhtmlObject.prototype.doMouseOver = function(event){
  console.log(event, this.ele);
};
//それで、動的にDomを作る(タグ、IDを指定)
new DhtmlObject("div", "divId");

これで、Domを作成する定義式と、イベントが起きた時に実行される関数を分離できた。作ったdomをglobal変数に入れて、ごにょごにょする必要もなくなった。(ここら辺りは、理解が怪しい)

ローカル変数の作成の重複を避ける

関数を呼び出すたびに、その関数のローカル変数を作るのはさけたい。よく例題に出るカウンターの例と同じタイプ。

closureにすれば、そのローカル変数(closureされる変数)は共通化される。

divの中にimgタグをいれる形のdocument.elementを作る。この時に、文字列をinnerHTMLに突っ込む形にする。それで、共通部分をローカル変数に、変わる部分はパラメータとする。

closureを使うべきでない場合

内部関数を作る事による速度低下に気をつける。closureを作ったけど、利用時に、その環境を使わないのなら、closure を作らず、外側で関数を定義しておいて、それをassignしてもよい。

constructor関数内で、this.method1 = function(){….}と定義して、closureを作るのは、呼び出し回数が少ない場合に限定する。そのconstructorが何回も使われるものであれば、AConstructor.prototype.method1 = function(){….}と、constuctor関数の外で、定義していく。

Googleカスタム検索(Web Element)でGAを使う(運用・改善編)

*この記事は、いつもに増して誤りが多いので、注意して読んで下さい。(しかし、Google Analytics上の定義は理解できないものが多い。みんな苦労してないのかな??)

Googleカスタム検索(Web Element)でGAを使う

前回のGoogleカスタム検索(Web Element)でGAを使う(設定編)の次は、運用(Google Analyticsを使った)になる。

Google Analyticsのレポート画面を確認する

以下は、このデータを自分でサイト内検索を表示した画面。

サイト内で、

  • 何回検索されたのか?
  • それはどのページなのか?
  • 検索した表示された記事がclickされ閲覧されたか
  • 検索した後の、離脱するまでの滞在時間、pageview
  • 再検索した回数
などが記録されている。
項目別に見ていく。
1. 利用状況
サイト内検索をしたセッションと、そうでないセッションをわけてくれる。仮に、サイト内検索した人を追跡したい場合は、前回の記事のutmvの使いどころ、流入元を追加的に記入するみたいなやり方で、cookieのutmvにサイト内検索をしたという値を追記すればいいと思う。(この記事を書きながら、僕のサイトにもそういう設定をした)
2.次の検索キーワード、開始ページ、到達ページ、カテゴリは、同じ指標(メトリックス)を見せてくれる。
表示されるメトリックス
  • 検索結果の平均ページビュー -  検索結果をクリックした
  • 検索結果の離脱率 - 検索直後に直帰した
  • 再検索 - 続けて検索した。
  • その後のページビュー – 検索後の平均ページビュー
検索回数と検索後の行動を記録してくれるという事。
一応、赤丸で囲んだように、ヘルプで説明があるけど、こんな意味だと思う。
をみる。ここの例のところを見ると、
検診結果の平均ページビュー(検索結果をclickした数検索後のpageview数/検索回数)
その後の平均ページビューは、(???/検索したセッションの総数)
???の部分は、検索後のページビューではなく、平均ページビューと同じように検索結果をclickした数に読めるのだが、、、両者の違いは、分母にある、検索回数と検索したセッション数の違いにみえる。僕のレポートに出てる数字も、実感としてはそのように見える。
ただ、最初の定義の部分は、単なるページビューに読める。(これでいいみたい ???はページビューで良いのか??)
下の図は、ディメンジョンが検索キーワード

検索キーワードは、本物?のディメンジョンなので、他のディメンジョンと切り替えが効く。

他の項目(開始ページなどは)は、正式にディメンジョンになってないので、切り替え表示できないのだと思うGoogle AnalyticsのAPIページを見ても、サイト内検索用のAPIはない。検索用のパラメータが途中で入ったら、サイト内検索をしたという処理なんだと想像する。
カテゴリは今回設定してないけど、プロファイルの設定画面で、クエリーパラメータを追加すればいい。
傾向は、時系列でのサイト内検索のデータ(上で書いた項目)を出してくれる。
以上が運用

それで、どうやってデータを生かすか?

設定して、数値を見て、それをどう生かすのかだけど、
自然検索の流入の時と同じ感覚しか思いつかない。
  • キーワードの発掘
  • そのキーワードから見えるニーズに対応したページをみせられているかどうか?
  • コンバージョンに誘導できているかどうか?
  • その他(他にもあるんだろうけど、思いつかない)

サイト内検索してくれた人にお願いする。

たぶん、サイト内検索までしてくれる人には、アンケートみたいなのを頼んでもいいのではないかと思う。
検索直後に出すと迷惑がられそうなので、結果が出ない場合にオンラインフォームを出してみる。
とりあえず、簡単にgoogle spreadsheetで、online-formを作ってみた。普通の検索結果と同じように、”x”を押すと消える。
ウェブページの顔の部分に、検索やアンケート記入を持って行くのは問題かもしれないけど、ユーザの利便性は高まるかもしれない。