Fly higher! Sky is the limit!

webの現場で働く人のブログ

[GA]iPhone、iPad等(iOS:Safari)でGoogleアナリティクスでクリックイベント計測がうまくいかない時の対処方法。

※ こちらも合わせてご覧ください。2016/11/1更新 paradox-tm.hateblo.jp

iOSSafariのみブラウザの仕様上、Googleアナリティクス(以下、GA)を使用したイベント計測がうまくいかない事が多々あります。

特に計測がうまくいかない時のパターンが以下です。

  • a要素でリンクを指定していた場合のclickイベント計測
  • a要素でリンクとtarget="_blank"を指定していた場合のclickイベント計測

なぜ計測ができないのか?

iOSSafariのみ指定していたリンク先に飛ぶ処理の方が、埋め込んだイベント計測の発火よりも速く処理されてしまうのが原因のようです。

つまり通常のフローでは、

・click → イベント計測 → リンク先へ移動

ですが、iOSSafariの場合

・click → リンク先へ移動 (イベント計測はスルー)

と処理されてしまうということです。

解決策

二種類の方法でほぼ確実に計測ができるようになりました。

1つ目:eventCallback関数を使用する。

通常のdataLayer.pushの記述

dataLayer.push({
  'event': 'hoge',
  'category':'fuga',
  'action':'piyo',
  'label':'hogehoge'
});

eventCallback関数を使用したdataLayer.pushの記述

dataLayer.push({
  'event': 'hoge',
  'category':'fuga',
  'action':'piyo',
  'label':'hogehoge',
  'eventCallback' : function(){
    //event
  }
});

このeventCallback関数中に飛ぶリンク先を指定してあげることで、 確実にイベントを発火させます。

sampleソース(jQuery使用)

$('#target').each(function(){
  var link = $(this).attr('href');
  $(this).on( 'click' , function(){
    dataLayer.push({
      'event': 'hoge',
      'category':'fuga',
      'action':'piyo',
      'label':'hogehoge',
      'eventCallback' : function(){
        //event
        document.location = link;
      }
    });
    return false; 
  });
});

target="_blank"が使用されている場合は別窓表示に変更するなどの対応が必要。
※ document.locationの場合、同ページ内に表示されてしまいます。

公式ドキュメントにはないですが、Google Tag Manager for Web Trackingdのサンプルソースでも実装されている方法になります。

以下、引用ソース

/**
 * Call this function when a user clicks on a product link. This function uses the event
 * callback datalayer variable to handle navigation after the ecommerce data has been sent
 * to Google Analytics.
 * @param {Object} productObj An object representing a product.
 */
function(productObj) {
  dataLayer.push({
    'event': 'productClick',
    'ecommerce': {
      'click': {
        'actionField': {'list': 'Search Results'},      // Optional list property.
        'products': [{
          'name': productObj.name,                      // Name or ID is required.
          'id': productObj.id,
          'price': productObj.price,
          'brand': productObj.brand,
          'category': productObj.cat,
          'variant': productObj.variant,
          'position': productObj.position
         }]
       }
     },
     'eventCallback': function() {
       document.location = productObj.url
     }
  });
}

Enhanced Ecommerce (UA) Developer Guide  |  Google Tag Manager for Web Tracking  |  Google Developers

2つ目:iPhoneiPad等(iOSSafari)のみ処理を遅延させる。

手順1. ユーザーエージェントでiOSのデバイスかどうかを判定する。

var appleKit = false;
  if(navigator.userAgent.indexOf('iPad') > 0 || navigator.userAgent.indexOf('iPhone') > 0 || navigator.userAgent.indexOf('iPod') > 0){
  appleKit = true;
}

手順2. appleKit = trueの場合のみ遅延させる処理を追加。

if( appleKit === true ) {
/*event1*/ 
  $('#target').each(function(){
      var link = $(this).attr('href');
      $(this).on( 'click' , function(){
        dataLayer.push({
          'event': 'hoge',
          'category':'fuga',
          'action':'piyo',
          'label':'hogehoge'
        });
        var linkFunc = function(){
          document.location = link;
        };
        window.setTimeout( linkFunc, 500 );
      });
      return false;
  });
}else{
/*event1*/
//通常の記述
}

target="_blank"が使用されている場合は別窓表示に変更するなどの対応が必要。

ユーザーエージェントとの出し分けと通常の記述、iOS専用の記述と少し長めの記述になります。

考察

touchstartの座標 = touchendの座標のとき(疑似的なclick)を使用して計測した場合、二重にカウントされてしまうこともありうまくいかなかったり、onmousedownでの発火の場合、clickしていなくてもイベントが発火してしまうという欠点があったり...色々調査した結果、この2つのやり方がベストかと思いました。

[AngularJS]ノンコーダーやディレクター向け運用支援ツールの開発。

Webサイトの運用をするにあたって、ディレクターから案件が入稿され制作者が納品物をつくるわけですが 運用コスト削減につながるように運用支援ツール(仮)を考えてみました。

JSのフレームワークは、AngularJSを使用してみました。

運用ツールのゴール

  • ディレクターやノンコーダーでもソースを生成できる。
  • あとはコピーして貼り付けて終わり。

今回は、xmlの生成を例にサンプルをつくってみます。

DEMO

See the Pen Angularjs sample tool -- blog by @paradox_tm (@takumaro-web) on CodePen.

※ AngularJSを扱う場合は、バージョンに注意が必要。
※ 大したことはしていないので、技術的な説明は省きます。
※ ソースの整形には、http://hilite.me/ を使用してみました。

アイディア次第では、かなり運用負荷の軽減につながりそうな予感がしますね。

最後に

ツールの開発に時間がかかったとしても、その後の『運用負荷の軽減につながる』と考えれば十分つくる価値はあるかなーと思います! 特にディレクターさんに喜ばれるかもしれません!

それでは...

[JS]日付処理 × replace × 置換 × 後方置換

(例)2016/02/04 → 2016年2月4日 にしたい場合。

  /*日付置換*/
  var date = '2016/02/04';
  date = date.replace(/^(\d+)\/(\d+)\/(\d+)$/, function(){
        var month,day;
        month = arguments[2];
        day = arguments[3];
        month = month ? month.replace(/^0/,'') : '';
        day = day ? day.replace(/^0/,'') : '';
        return arguments[1] + "年"+ month + "月" + day + "日";
    });
  1. 文字列をスラッシュのところまでで三分割し、yyyy | mm | dd の形にする。
  2. 三分割したうちのmmとddのみ変数に代入
  3. 01日、02日などの0から始まる日付を三項演算子を使用し検索置換する。
  4. returnにて、変更した値を返す。

DEMO

See the Pen blog01 by @paradox_tm (@takumaro-web) on CodePen.

外部APIJSONから吐き出される日付を変更したい場合などに使えます。

日付処理の優秀なプラグインといえば、Moment.js | Homeがありますが、出力される形式(フォーマット)が決まっているのであれば、わざわざプラグインを使用しなくても対応できることもあるので少しでも参考になればと思います。