昨年からGoogleアナリティクスの機能拡大が非常に盛んでして、「こんなのあったらいいな」と思っていた部分が次々と標準機能で対応されていっており、やはりGoogleさんはすごいなと感動しきりでございます。
そんな感動の傍らで、「こんなのあったらいいな」という機能を独自に開発してみたものの標準機能で対応されてしまったという寂寞の念を抱いている方も多いのではないのでしょうか。
そうです。私もそのうちの一人です。
今回はそんな寂寞のJavaScriptモジュールを公開してみたいと思います。
ga.link_tracking.js – Googleアナリティクス用自動リンク計測ツール – Download
※[2013/11/07 10:56追記]要素の取得部分に不具合があったので修正しました。
詳しい解説は以下の通りです。
主な機能
- JSファイルを読み込むだけですべてのリンク(aタグ)のクリックを計測
- セッション内で何回目にクリックしたリンクかを取得(経路分析もどき)
なお、(1)はGTMの自動リンク計測機能で、(2)はアドバンスセグメントのシーケンスで代替可能です。とほほ。
依存するライブラリ/プラグイン
- jQuery(ver.1.7 or later)
- jQuery.cookie
詳細な機能説明
(1)リンククリックの監視&イベントトラッキング
aタグのクリックイベントを監視しています。formタグなどaタグ以外のクリックには対応していません。
aタグがクリックされると、Googleアナリティクスのイベントトラッキングを使ってクリック情報を取得します。
(2)GAイベントの引数
category:
デフォルトは、リンクがクリックされたページのURL(http://から)です。
この値は変更可能です。
action:
デフォルトは、「Tracklink」という固定文字列です。
この値は変更可能です。
label:
クリック情報のメイン部分です。下記のような内容になっています。
【クリック回数】_【リンク元ページ】_【リンク先ページ】_【クリックされた要素】
それぞれを解説していきます。
【クリック回数】
クリック回数は、セッション内での何回目のクリックかという情報が入ります。
クリック回数はCookieに記録されており、このCookieはブラウザを閉じるまで有効です。
Googleアナリティクスのセッションとは一致しないので注意してください。
書式 | 説明 |
---|---|
Pnum:n | nはクリック回数です。 |
【リンク元ページ】
リンク元ページは、リンクがクリックされたページのURL(http://から)です。
categoryと同じ値が入ります。
書式 | 説明 |
---|---|
From:fURL | fURLにはリンクがクリックされたページのURLが入ります。 |
【リンク先ページ】
リンク先ページは、クリックされたリンクのリンク先URL(http://から)です。
aタグのhrefが相対パスで記載されていてもhttp://からのURLに変換します。
書式 | 説明 |
---|---|
To:tURL | tURLにはリンク先のURLが入ります。 |
【クリックされた要素】
クリックされた要素は、クリックされたaタグを特定するための情報です。
クリックされたaタグとその親要素を3階層上まで辿って、要素のID・class・要素名(タグ名)を取得します。
ID・classが両方とも設定されている場合は、ID -> class -> タグ名の順で優先されます。
書式 | 説明 |
---|---|
obj1<obj2<obj3 | obj1はクリックされたaタグの要素、obj2、obj3はその上の親要素です。 |
なお、辿る要素の数は設定で変更可能です。
すべてまとめると、labelの値は下記のような形になります。
Pnum:10_From:http://meaningfree.net/_To:http://meaningfree.net/?123_Area:#id1<.class2<DIV
(3)コールバック関数の利用
Googleが提供しているコールバックの関するを利用するかどうかを選択できます。
リンクをクリックした際に発行されるイベントは、リクエストが送信される前にページ遷移をしてしまい、GAのサーバにリクエストが送信されない(=クリックが計測されない)ことがあるという問題があります。
その問題を回避するために、リクエストが送信されてからページ遷移をさせるための機能がコールバックです。ざっくり言いますと。
ただコールバックを利用するとaタグのデフォルトの動きを止めて、JavaScriptの処理でページ遷移をさせるので、リンククリック時にGA以外の処理を入れていた場合のコンフリクトなどの問題もあり、
一概にコールバックを使うのが必ず良いと言えるわけではない、ということになっています。
ですので、コールバックを利用するかどうかはサイトの状況に合わせて変更できるようにするため、コールバック利用のON/OFFが設定できるようになっています。
これはコードの冒頭にある環境設定のエリアで UseCallBack という変数の値をtrue/falseにすることで変更ができます。
(4)ユニバーサルアナリティクスと標準のアナリティクスの利用
ユニバーサルアナリティクスを利用しているか、標準のアナリティクスを利用しているかに合わせて、イベント関数の書式を選択できるようにしています。
ユニバーサルアナリティクスと標準のアナリティクスのトグル選択ではなく、それぞれの計測方法でON/OFFが可能です。つまり、どちらかだけ送信することもできますし、両方とも送信することも可能です。
コードの冒頭にある環境設定のエリアで、ユニバーサルアナリティクスは UnivTrack という変数の値を、標準のアナリティクスは TradTrack という変数の値をtrue/falseにすることで変更ができます。
(5)計測対象外リンクの設定
基本的にはすべてのaタグを計測しますが、計測したくないリンクについては、エスケープ用classを設定することで計測対象から外すことができます。
エスケープ用class名は任意に設定可能ですが、デフォルトは「esc_ga」です。
ページ遷移を伴わないaタグなどに利用してください。
例) <a href=”#” class=”esc_ga”>計測対象外リンク</a>
それでは最後にソースコードです。
/* ----------------------------------------------------------------- */ // // Googleアナリティクス 自動リンク計測 // /* ----------------------------------------------------------------- */ function galink_tracking() { /* ----------------------------------------------------------------- */ // 環境設定ここから /* ----------------------------------------------------------------- */ // イベントトラッキングの第1引数 var param1 = location.href; // イベントトラッキングの第2引数 var param2 = "Tracklink"; // リンク要素識別のためにたどる要素の数 var target_prtLv = 3; // コールバックの使用 true/false var UseCallBack = true; // ユニバーサルトラッキング用イベント送信 true/false var UnivTrack = true; // 従来のコード(_gaq.push)用イベント送信 true/false var TradTrack = true; // 計測対象外タグ用のエスケープclass名 var escClass = "esc_ga"; /* ----------------------------------------------------------------- */ // 環境設定ここまで /* ----------------------------------------------------------------- */ var data_cookie, cookie, cookie_count; $("a").on('click', function(evt){ var thisHref = $(this).attr('href'); var thisTarget = $(this).attr('target'); var prtNode = $(this).parent(); /* ----------------------------------------------------------------- */ // クリックされた要素と親要素のID・Classを取得 /* ----------------------------------------------------------------- */ var thisLinkArea = ""; var LinkArea_sep = ""; for(var i=0; i<target_prtLv; i++){ var myLvNum = i+1; if(myLvNum==1){ eval("prtLv" + myLvNum + "= $(this)"); LinkArea_sep = ""; }else{ eval("prtLv" + myLvNum + "= prtLv" + i + ".parent()"); LinkArea_sep = "<"; } eval("var myid = prtLv" + myLvNum + ".attr('id')"); eval("var myclass = prtLv" + myLvNum + ".attr('class')"); if(myid){ thisLinkArea += LinkArea_sep + "#" + myid; }else if(myclass){ thisLinkArea += LinkArea_sep + "." + myclass; }else{ eval("thisLinkArea += LinkArea_sep + prtLv" + myLvNum + "[0].tagName"); } } /* ----------------------------------------------------------------- */ // エスケープクラスの定義 /* ----------------------------------------------------------------- */ // エスケープクラス判定 var cls = $(this).attr('class'); if (typeof cls === "undefined") { set_link_tracking(thisHref, thisTarget, thisLinkArea); } else { if (cls.indexOf(escClass) < 0) { set_link_tracking(thisHref, thisTarget, thisLinkArea); } } function set_link_tracking(href, target, LinkArea){ /* ----------------------------------------------------------------- */ // リンク先URLの取得 /* ----------------------------------------------------------------- */ var nowUrl = location.href; var nowDomain = nowUrl.match(/^https?://[^/]+/); // URLからドメイン名を抽出 var nowFile = nowUrl.match(".+/(.+?)$")[1]; // URLからhtmlファイル名を抽出 var nowDirectory = nowUrl.replace(nowFile, ''); var toUrl; if (href.indexOf('http') == 0) { // 絶対パス toUrl = href; } else { var subs_href = href.substr(0, 1); // hrefの1文字目 var href_size = href.length ; // hrefの文字列の長さ var splt_href = href.split('/'); // hrefをスラッシュ(/)で分割 var splt_href_size = splt_href.length; var now_splt = nowUrl.split('/'); // 現在のurlをスラッシュ(/)で分割 var now_splt_size = now_splt.length; if (splt_href[0] == '') { // ルート相対 toUrl = nowDomain + href; } else if(splt_href[0] == '.') { // 相対() var tmp_url = href.substring(2, href_size); toUrl = nowDirectory + tmp_url; } else if(splt_href[0] == '..'){ // 相対(上位ディレクトリ) for (i=0; i<splt_href_size; i++) { //console.log(splt_href[i]); if (splt_href[i] != '..') { var level_count = i; break; } } var level_up_url = '/'; for (i=3; i<now_splt_size-level_count-1; i++) { level_up_url += now_splt[i] + '/'; } var level_down_url = href.replace('../', ''); toUrl = nowDomain + level_up_url + level_down_url; } else { // ファイル名・ディレクトリ名 toUrl = nowDirectory + href; } } /* ----------------------------------------------------------------- */ // クリック回数の取得 /* ----------------------------------------------------------------- */ data_cookie = 'ga_click_count'; cookie = $.cookie(data_cookie); if (typeof cookie === "undefined") { //cookie 作成 cookie_count = 1; } else { //cookie インクリメント cookie_count = parseInt(cookie, 10) + 1; } // cookie カウント登録 $.cookie('ga_click_count', cookie_count, {path: '/'}); /* ----------------------------------------------------------------- */ // GAリクエスト送信処理 /* ----------------------------------------------------------------- */ var param3 = 'Pnum:' + cookie_count + '_From:' + nowUrl + '_To:' + toUrl + "_Area:" + LinkArea; if(target == '_blank') { ga_trackEvent(param1,param2,param3); }else if(UseCallBack){ ga_trackEvent_callback(param1,param2,param3,evt,href); }else{ ga_trackEvent(param1,param2,param3); } } // set_lick_tracking() end }); function ga_trackEvent(p1,p2,p3){ if(UnivTrack){ ga('send', 'event', p1, p2, p3); } if(TradTrack){ _gaq.push(['_trackEvent', p1, p2, p3]); } } function ga_trackEvent_callback(p1,p2,p3,evt,href){ if(UnivTrack){ ga('send', 'event', p1, p2, p3, { hitCallback: function () { document.location.href = href; } }); evt.preventDefault(); } if(TradTrack){ _gaq.push( ['_set', { hitCallback : function(){ document.location.href = href; } }], ['_trackEvent', p1, p2, p3] ); // コールバック取り消し _gaq.push(['_set', { hitCallback : function(){} }]); evt.preventDefault(); } } } $(function(){ galink_tracking(); });