2013-12-20

[ GAS ]シェアレポートをスクリプトで取得してメール送信させてみる

毎月初めに(勝手に)公開している仕事先のサイトの訪問数による色んなシェア(※参照※)、カスタムレポート作ってそこから数値をペタペタコピペしてたけど、暇つぶしがてらGoogle Analyticsにアクセスして集計してブログに投稿するためのhtmlにしたテキストをメール送信するGoogle Apps Scriptを書いて、毎月3日の適当な時間帯のトリガーで設定することにしてみた。

ソースコードをさらしてみる
コンストラクタは”レポートのタイトル”、”レポートの開始日”、”レポートの終了日”を引数にとる、GAからデータを取得させる関数、メール送信用に文字列を作らせる関数を持ったMonthlyShareというクラス(らしきもの)を準備。Main.gsのmain関数で必要なレポート分だけインスタンスを作って本文を作成させてメールする。
って感じ。
Google Analyticsからデータを取得するAnalytics.Data.Ga.get(ids, start-date, end-date, metrics, optionalArgs)の”ids”にあたるtable idだかprofile IDだかとメール送信先のメールアドレスは「プロジェクトのプロパティ」のユーザープロパティに入れておいた。

UserProperties.getProperty( 'プロパティ名' )
※Google Apps Scriptの準備の仕方とかは調べたほうが詳しく書かれているのがいっぱいあるので、特に記述しない…。

/*****
 * MonthlyShare Class
 * @settings { 'month_first', 'month_last', 'report_title', 'report_max' }
*****/
var MonthlyShare = function( settings ) {
  var a;

  // month_first( 1st of last month )
  a = new Date( this.today.getYear(), this.today.getMonth() - 1, 1 )
  , this.month_first = settings.month_first || Utilities.formatDate( a, 'JST', 'yyyy-MM-dd' )
  ;
  
  // month_last( last day of last manths )
  a = new Date( this.today.getYear(), this.today.getMonth(), 0 )
  , this.month_last = settings.month_last || Utilities.formatDate( a, 'JST', 'yyyy-MM-dd' )
  ;

  // report_title
  this.report_title = settings.report_title || this.report_title;

  // report_max
  this.report_max = settings.report_max || this.report_max;
};

MonthlyShare.prototype = {
  ga_profile_ids: UserProperties.getProperty( 'ga_profile_ids' )
  , today: new Date()
  , month_first: ''
  , month_last: ''
  , report_title: 'Monthly Share Report'
  , report_max: 5
  , report_gadata: {}
  , report_mailtext: ''
  , ga_metrix: ''
  , ga_options: {}

  , gaData: function( met, opt ) {
    this.ga_metrix = met
    , this.ga_options = opt;

    /**
    Analytics.Data.Ga.get(ids, start-date, end-date, metrics, optionalArgs)
    **/
    return this.report_gadata = Analytics.Data.Ga.get( this.ga_profile_ids, this.month_first, this.month_last, met, opt );
  }

  , dimensionMix: function( d ) {
    var a = new Array();

    for( var i = 0, m = d.length, b = 0, s = ''; i < m; i++, s = '' ){
      c = d[ i ].length - 1;

      for( var j = 0; j < c; j++ ){
        if( !!s )
          s += '+';
        s += d[ i ][ j ];
      }
      a.push( [ s, d[ i ][ c ] ] );
    }

    return a;
  }

  , analysisShare: function( d ) {
    var a = new Array()
    , ttl_val = this.report_gadata.getTotalsForAllResults()[ 'ga:visits' ]
    ;

    for( var i = 0, m = d.length, b = 0; i < m; i++ ){
      b = Utilities.formatString( '%.2f', Math.round( d[ i ][ 1 ] / ttl_val * 10000 ) / 100 ) + '%';
      a.push( [ d[ i ][ 0 ], b ] );
    }
    return a;
  }

  , createMailText: function() {
    var a = '', rows, b;

    rows = this.report_gadata.getRows();
    if( rows.lenght <= 0 )
      return '';

    b = rows.slice( 0, this.report_max - 1 );
    if( rows[ 0 ].length > 2 ){
      b = this.dimensionMix( rows )
    }else{
      b = rows;
    }

    b = this.analysisShare( b );

    a += '
' + this.report_title + '
'; for( var i = 0; i < this.report_max; i++ ){ a += '
' + b[ i ][ 0 ] + '
' + b[ i ][ 1 ] + '
'; } a += '
'; return this.mailText( a ); } , mailText: function( s ) { if( !!s ) this.report_mailtext = s return this.report_mailtext; } };
function main() {
  
  var mail_text = ''
  , options = {}
  , month_first
  , month_last
  ;

/*
  // for Test
  var today = new Date();
  month_first = Utilities.formatDate( new Date( today.getYear(), today.getMonth() - 1, 1 ), 'JST', 'yyyy-MM-dd' );
  month_last = Utilities.formatDate( new Date( today.getYear(), today.getMonth(), 0 ), 'JST', 'yyyy-MM-dd' );
  ;
*/
  
  // ----------------
  var ms0 = new MonthlyShare( {
    'month_first': month_first
    , 'month_last': month_last
    , 'report_title': '全デバイス・OSシェア'
  } );
  options = {
    'dimensions': 'ga:operatingSystem'
    , 'sort': '-ga:visits'
  };
  ms0.gaData( 'ga:visits', options );
  mail_text += ms0.createMailText();


  // ----------------
  var ms1 = new MonthlyShare( {
    'month_first': month_first
    , 'month_last': month_last
    , 'report_title': '全デバイス・ブラウザシェア'
  } );
  options = {
    'dimensions': 'ga:browser'
    , 'sort': '-ga:visits'
  };
  ms1.gaData( 'ga:visits', options );
  mail_text += ms1.createMailText();


  // ----------------
  var ms2 = new MonthlyShare( {
    'month_first': month_first
    , 'month_last': month_last
    , 'report_title': '全デバイス・ブラウザ+バージョンシェア'
  } );
  options = {
    'dimensions': 'ga:browser,ga:browserVersion'
    , 'sort': '-ga:visits'
  };
  ms2.gaData( 'ga:visits', options );
  mail_text += ms2.createMailText();
  

  // ----------------
  var ms3 = new MonthlyShare( {
    'month_first': month_first
    , 'month_last': month_last
    , 'report_title': '全デバイス・OS+ブラウザシェア'
  } );
  options = {
    'dimensions': 'ga:operatingSystem,ga:browser'
    , 'sort': '-ga:visits'
  };
  ms3.gaData( 'ga:visits', options );
  mail_text += ms3.createMailText();

  
  // ----------------
  var ms4 = new MonthlyShare( {
    'month_first': month_first
    , 'month_last': month_last
    , 'report_title': 'PC系縛り・ブラウザ+バージョンシェア'
  } );
  options = {
    'dimensions': 'ga:browser,ga:browserVersion'
    , 'sort': '-ga:visits'
    , 'filters': 'ga:deviceCategory==desktop'
  };
  ms4.gaData( 'ga:visits', options );
  mail_text += ms4.createMailText();

  
  // ----------------
  var ms5 = new MonthlyShare( {
    'month_first': month_first
    , 'month_last': month_last
    , 'report_title': 'スマホ系縛り・OS+バージョンシェア'
  } );
  options = {
    'dimensions': 'ga:operatingSystem,ga:operatingSystemVersion'
    , 'sort': '-ga:visits'
    , 'filters': 'ga:deviceCategory==mobile,ga:deviceCategory==tablet'
  };
  ms5.gaData( 'ga:visits', options );
  mail_text += ms5.createMailText();


  // ----------------
  var report_month = Utilities.formatDate( new Date( ms5.month_first.replace( /\-/g, '/' ) ), 'JST', 'yyyy/MMM' );
  MailApp.sendEmail( {
    'to': UserProperties.getProperty( 'mail_to' )
    , 'subject': '[ ' + report_month + ' ]Automatically Monthly Report'
    , 'body': mail_text
  } )
//  Logger.log( mail_text );

};

一番よく見た公式サイトのリファレンスとか
Analytics Service
Dimensions & Metrics Reference
Properties Services
Utilities Service
Mail Service

何か間違えていたら指摘していただけると…


そして、誰かの何かの参考になれば…

2013-12-05

[ js ]css3のアニメーションでアイコン的動きにするjQueryプラグインを作ってみた

コピペで使えるCSS3アニメーション http://jsdo.it/gryng02/css3animation を拝見していて、「New!」が一つずつ大きくなるのが面白いけど、文字が多くなったらcss書くの大変だな。と思ったので指定された場所にcssを適用させるjqueryプラグインを書いてみた。

ま、活用できるかは置いておくとして…。

New!
Conguratulations!
Update!
Topics!

ソース

css(外部ファイルとかでicon_tip.css)

/*

 文字一つ一つにかかるスタイル指定。
  似たような感じでバリエーションを増やしてクラス名を引数で渡す

*/
.icnBgGreen {
	background-color: rgba( 0, 250, 0, 1 );
	color: rgba( 255, 255, 255, 1 );
	font-weight: bold;
	font-size: 110%;
	padding: 4px;
}
.icnBgRed {
	background-color: rgba( 250, 0, 0, 1 );
	color: rgba( 255, 255, 255, 1 );
	font-weight: bold;
	font-size: 110%;
	padding: 4px;
}




/*

 アニメーションさせたりするのスタイル指定。
  数字を変更するくらいで基本は変更しなくてよいはず

*/
span#iconTip {
	display: inline;
}
span#iconTip span.icnLetter {
	display: inline-block;
	-webkit-transform-origin: middle center;
	-moz-transform-origin: middle center;
	-ms-transform-origin: middle center;
	-o-transform-origin: middle center;
	transform-origin: middle center;
	-webkit-transform: scale( 1 );
	-moz-transform: scale( 1 );
	-ms-transform: scale( 1 );
	-o-transform: scale( 1 );
	transform: scale( 1 );
	-webkit-animation: 1.3s ease-in-out icnLetterX infinite;
	-moz-animation: 1.3s ease-in-out icnLetterX infinite;
	-o-animation: 1.3s ease-in-out icnLetterX infinite;
	animation: 1.3s ease-in-out icnLetterX infinite;
}
@-webkit-keyframes icnLetterX {
	0% {
		-webkit-transform: scale( 1 );
	}
	70% {
		-webkit-transform: scale( 1 );
	}
	85% {
		-webkit-transform: scale( 1.5 );
	}
	100% {
		-webkit-transform: scale( 1 );
	}
}
@-moz-keyframes icnLetterX {
	0% {
		-moz-transform: scale( 1 );
	}
	70% {
		-moz-transform: scale( 1 );
	}
	85% {
		-moz-transform: scale( 1.5 );
	}
	100% {
		-moz-transform: scale( 1 );
	}
}
@-o-keyframes icnLetterX {
	0% {
		-o-transform: scale( 1 );
	}
	70% {
		-o-transform: scale( 1 );
	}
	85% {
		-o-transform: scale( 1.5 );
	}
	100% {
		-o-transform: scale( 1 );
	}
}
@keyframes icnLetterX {
	0% {
		transform: scale( 1 );
	}
	70% {
		transform: scale( 1 );
	}
	85% {
		transform: scale( 1.5 );
	}
	100% {
		transform: scale( 1 );
	}
}

JavaScript(外部ファイルとかでjquery.icon_tip.js)

;

( function( $ ) {

    $.fn.iconTip = function( config ) {
        var defaults = {
            elem: 'span'
            , iconTipId: 'iconTip'
            , class: 'icnBgGreen'
            , letterClass: 'icnLetter'
        };

        var options = $.extend( defaults, config );

        return this.each( function() {
            var $one = $( this )
            , one_txt = $one.text()
            , $icon_tip = $( document.createElement( options.elem ) ).attr( 'id', options.iconTipId );

            $.each( one_txt.split(''), function( i, s ) {
                var delay = 0 + ( i / 10 ) + 's';
                var cssprop = {
                    'webkitAnimationDelay': delay
                    , 'mozAnimationDelay': delay
                    , 'oAnimationDelay': delay
                    , 'animationDelay': delay
                };
                $icon_tip.append( $( document.createElement( options.elem ) ).text( s ).addClass( options.class ).addClass( options.letterClass ).addClass( options.letterClass + ( i + 1 ) ).css( cssprop ) );
            } );

            $one.contents().remove();
            $one.append( $icon_tip );
        } );
    };

} )( jQuery );

HTMLと実行部分

New!
Conguratulations!
Update!
Topics!
<script> $( '#new' ).iconTip(); $( '#cong' ).iconTip( {class:'icnBgRed'} ); $( '#upd' ).iconTip(); $( '#topics' ).iconTip( {class:'icnBgRed'} ); </script>

classをキー、クラス名を値にした連想配列を引数で渡すと一文字ずつspanのclassにくっつきます。デフォルトは、上記cssの

.icnBgGreen {
	background-color: rgba( 0, 250, 0, 1 );
	color: rgba( 255, 255, 255, 1 );
	font-weight: bold;
	font-size: 110%;
	padding: 4px;
}
2種類、3種類バリエーションを増やしたい時は似たようなスタイルシートのクラスを作って引数で渡す。

あとは、適宜数字をいじれば…。

2013-12-03

[ シェアレポート ]2013/11 GAで調べた訪問数に見る

2013年11月 仕事先のサイト(国内)の訪問数による色んなシェア 上位5つ(GA調べ)
(注意)特殊な媒体なので時期によってPC、スマホの割合が非常に上下します

全デバイス・OSシェア
Windows
41.22%
Android
31.20%
iOS
24.25%
Macintosh
2.59%
Linux
0.34%
全デバイス・ブラウザシェア
Internet Explorer
31.10%
Android Browser
28.59%
Safari
22.77%
Chrome
9.42%
Firefox
3.14%
全デバイス・ブラウザ+バージョンシェア
Android Browser+4.0
28.53%
Internet Explorer+10.0
17.29%
Safari+7.0
12.89%
Internet Explorer+8.0
6.92%
Safari+6.0
5.98%
全デバイス・OS+ブラウザシェア
Windows+Internet Explorer
31.09%
Android+Android Browser
28.59%
iOS+Safari
20.98%
Windows+Chrome
6.04%
iOS+Safari (in-app)
3.02%
PC系縛り・ブラウザ+バージョンシェア
Internet Explorer+10.0
39.10%
Internet Explorer+8.0
15.47%
Internet Explorer+9.0
11.15%
Chrome+30.0.1599.101
6.90%
Chrome+31.0.1650.57
6.49%
スマホ系縛り・OS+バージョンシェア
Android+4.0.4
15.95%
iOS+7.0.3
14.26%
Android+4.1.2
12.66%
Android+4.2.2
8.74%
iOS+7.0.4
7.48%

計測方法
全てGAのカスタムレポート

全デバイス・OSシェア
指標グループ:訪問数
ディメンションの詳細:オペレーティングシステム
全デバイス・ブラウザシェア
指標グループ:訪問数
ディメンションの詳細:ブラウザ
全デバイス・ブラウザ+バージョンシェア
指標グループ:訪問数
ディメンションの詳細:ブラウザ → セカンダリ ディメンション:ブラウザのバージョン
全デバイス・OS+ブラウザシェア
指標グループ:訪問数
ディメンションの詳細:オペレーティングシステム → セカンダリ ディメンション:ブラウザ
PC系縛り・ブラウザ+バージョンシェア
指標グループ:訪問数
ディメンションの詳細:モバイル(タブレットを含む)※"No"を選択>ブラウザ → セカンダリ ディメンション:ブラウザのバージョン
スマホ系縛り・OS+バージョンシェア
指標グループ:訪問数
ディメンションの詳細:モバイル(タブレットを含む)※"Yes"を選択>オペレーティング システム → セカンダリ ディメンション:OSのバージョン

何か間違えていたら指摘していただけると…


そして、誰かの何かの参考になれば…

archive