google apps scriptと chart apiを使ったレポート自動化

今回は、アクセス解析の話ではないのですが、データとして GAを使ったので、ここに書きます。

前回、スクロール率をgoogle analyticsで計測した話を書きました。 レポート部分は、エクセルでの表示だったんですが、今回、自動化のひとつの方法として、タイトルの方法をやったので、報告します。

Google Apps Script(GAS)は、かなりの便利ツール

データを外部から引っ張ってきて、加工して、メール配信というのが、割合簡単にできます。

今回は、google analyticsのデータを引っ張って、加工して、HTMLメールで配信という形の紹介です。

GASの記述は、javascriptです。 google analyticsの集計の設定も javascriptですので、 javascriptは習得しがいのある技術かもしれません。

手順としては、URLFetchで google analytics Data Export  Api からデータを取得して、それを google chart apiを使って、 HTMLメールで送る作業です。

Google Chart APIも、自動化ツールとして価値大。

URLを指定すれば、チャート画像を返してくれます。

ですので、変化する数字を自動的にグラフ化してレポーティングしたい場合に価値が高いです。

パラメータがたくさんあって、マニュアル(解説)が英語なのでとっつきにくいですが、データ、チャートタイプ、ラベル、軸、などの概念とapiでのパラメータが一致すれば、それなりに使えるのではと思ってます。

別サイトにメモみたいなのを書きましたが、、、あまり参考にならないかも。

GMailの問題?

いろいろいじって、なんとか自動化にこぎつけたのですが、GmailのHTML表示の時に、imageタグの部分が上手く表示されなくて、いろいろ探したのですが、結局あきらめました。 たぶん、文字数の問題のような気がしてるのですが、、、どうなんでしょう。 Yahoo Japanの Web mailなら問題なかったです。

出力画像と スクリプトを貼りつけます。

スクロール計測とそのレポート配信を試してみたい方は連絡下さい(コメントでスクロール計測希望と書いてくだい)。 設定して、週次 or 日次で、特定のディメンジョンで切ったスクロール率のよる閲覧割合をメールレポーティングします。無料です。 以下の画像のような形でのHTMLメールが送られます。

画像レポートの後に、参考に、GASのスクリプトを貼りつけておきます。 貼り付けた以外にも追加の定義(関数、代入式)などがあるので、全部ではないです。

2010-06-03から2010-06-15のセッション数上位3ページの精読率調査です。数字はセッション数です。

以下、レポート配信に使ったscriptの一部。

   1:  function CRReport(id,name,title,address){
   2:    //id = "ga:21600568", name="shirai", title="wordpress", address="kimiyuki[at?]gmail.com";
   3:    var startdate; var enddate; var dimensions = []; var metrics = []; var filters = ""; var segments = "";
   4:    var entries; var sort;var data;
   5:    var tmp;
   6:    var siteurl;
   7:    startdate = getMyDate(-15); enddate = getMyDate(-3);
   8:    dimensions = ["ga:pagePath,ga:hostname"]; metrics=["ga:visits"]; sort=["-ga:visits"];
   9:    entries =  getDataFromApi(id, startdate, enddate,dimensions, metrics, filters, segments, sort);
  10:    pagePaths = [];
  11:    entries.slice(0,3).forEach(function(entry){
  12:      var el = entry.getElements("http://schemas.google.com/analytics/2009", "dimension");
  13:      el.forEach(function(e){
  14:        if(e.getAttribute("name").getValue() == "ga:pagePath") pagePaths.push(e.getAttribute("value").getValue());
  15:        if(!siteurl && e.getAttribute("name").getValue() == "ga:hostname") siteurl = e.getAttribute("value").getValue();
  16:      });
  17:    });
  18:  
  19:    data = {};
  20:    var w1 = [null,null, null]; var w2 = [];
  21:    pagePaths.forEach(function(path){
  22:      Utilities.sleep(500);
  23:      w1 = [null,null,null], w2=[];
  24:      var dim_sg = "ga:medium";
  25:      dimensions = ["ga:eventCategory", "ga:eventAction", "ga:pagePath",dim_sg]; metrics = ["ga:uniqueEvents"]; sort = null;
  26:      filters="ga:eventCategory==CompRead0523B;ga:pagePath==" + path;
  27:      segments=null;
  28:      entries = getDataFromApi(id, startdate, enddate, dimensions, metrics, filters, segments, sort);
  29:      entries.forEach(function(entry){
  30:          var ds = entry.getElements("http://schemas.google.com/analytics/2009", "dimension");
  31:          var es = entry.getElements("http://schemas.google.com/analytics/2009", "metric");
  32:          var w = new Array();
  33:          ds.forEach(function(e){
  34:            if(e.getAttribute("name").getValue()=="ga:eventAction") w1[1] = parseInt(e.getAttribute("value").getValue().replace("z",""));
  35:            if(e.getAttribute("name").getValue()== dim_sg){w1[0] = e.getAttribute("value").getValue();}
  36:          });
  37:          es.forEach(function(e){
  38:            if(e.getAttribute("name").getValue() == "ga:uniqueEvents") w1[2] = parseInt(e.getAttribute("value").getValue());
  39:          });
  40:          w2.push([w1[0], w1[1],w1[2]]); //値にして設定するため
  41:          w1 = [null,null, null];
  42:        });
  43:      w2 = w2.sort(function(a,b){return a[1] > b[1]});
  44:      if(data[path] == null) data[path] = [];
  45:      data[path] = w2.map(function(x){return x});
  46:        //data[path] = w2.map(function(e){return [e[0], Math.floor((e[1]/total)*100)]});
  47:    });
  48:   // Logger.log(data);
  49:    html = outputChart(data, startdate, enddate, siteurl);
  50:    Logger.log(html);
  51:    MailApp.sendEmail(address, "CompRead","html mail", {cc: "kimiyuki[aat]gmail.com", htmlBody: html});
  52:  }
  53:  
  54:  
  55:  function outputChart(data, startdate, enddate ,siteurl){
  56:    var html = "<div>" + startdate + "から" + enddate + "のセッション数上位3ページの精読率調査です。数字はセッション数です。</div>";
  57:    for(e in data){
  58:      //Logger.log(e);
  59:      //Logger.log(data[e] instanceof Array);   
  60:      //Logger.log(data[e].length);
  61:      //Logger.log(data[e].toString());
  62:  
  63:      //making dimentionable data    
  64:      var dimmed_data = data[e].reduce(function(r, x){
  65:        if(r[x[0]] == null){
  66:          r[x[0]] = x[2];
  67:        }else{
  68:          r[x[0]] += x[2];
  69:        }
  70:        return r;
  71:      }, {});
  72:      //Logger.log(dimmed_data.toSource());
  73:  
  74:      var tmp = [];
  75:      Logger.log("object="); Logger.log(dimmed_data.toSource() + "\n");
  76:      for(c in dimmed_data){tmp.push([c, dimmed_data[c]])};
  77:      dimmed_data = tmp.sort(function(a,b){ return a[1] < b[1]});
  78:      Logger.log("dimmed_data=");
  79:      Logger.log(dimmed_data.toString()+"\n");
  80:      var label = data[e].map(function(x){return x[1]}).unique();
  81:      var data1 = data[e].filter(function(x){return x[0] == dimmed_data[0][0]}).map(function(x){ return x[2]});
  82:      var data2 = data[e].filter(function(x){return x[0] == dimmed_data[1][0]}).map(function(x){ return x[2]});
  83:      var data3 = dimmed_data.length < 3 ? "" : data[e].filter(function(x){return x[0] == dimmed_data[2][0]}).map(function(x){return x[2]});
  84:      //Logger.log(label);
  85:      //Logger.log(data1);
  86:      //Logger.log(data2);                                       
  87:      //html += "<tr><td>" + e + "</br>" + data[e].map(function(x){return x[0] + '=>' + x[1]}).join(',') + "</td></tr>";
  88:      html += "<div><div>";
  89:      html +=  makeChart(label, data1, data2,data3, dimmed_data[0][0], dimmed_data[1][0], (dimmed_data.length > 2 ? dimmed_data[2][0] : ""));
  90:      html +=  "</br>";
  91:      html += "<a href='http://" + siteurl + e + "'>" + e + "</a></div>";
  92:      html += "<div>  </div>" //全角空白を入れた。間隔を作るため
  93:    }
  94:    html += "</div>";
  95:    return html;
  96:  }
  97:  
  98:  function makeChart(label, data1, data2, data3, dataLabel1, dataLabel2, dataLabel3){
  99:        var max = data1.concat(data2).reduce(function(r, e){return r > e ? r : e;}, 10);
 100:        var chds = "chds=" + "0," + max;
 101:        var chxr = "chxr=1,0," + max;
 102:        var chco = "chco=4d89f9,c6d9fd" + (data3 != "" ? ",63C6DE" : "");
 103:        var chdl = "chdl=" + dataLabel1 + "|" + dataLabel2 + (dataLabel3 != "" ? "|"+dataLabel3 : "");
 104:        var chm = "chm=N,000000,0,,12,0,e|N,00FFFF,1,,12,0,e" + (data3 != "" ? "|N,0000FF,2,,12,0,e" : "");
 105:        var url =
 106:            "<img style='display:block;' src='http://chart.apis.google.com/chart?cht=bhg&chs=250x" + (dataLabel3 != "" ? "990" : "660") + "&chd=t:" +
 107:            data1.join(",") + "|" + data2.join(",") + (data3 != "" ? "|"+data3.join(",") : "") +
 108:            "&" + chds + "&" + chxr + "&" + chm + "&" + chdl + "&" + chco +
 109:            "&chxt=y,x&chxl=0:|" + label.reverse().join("|") + "&chxs=0,ff0000,12,0,lt|1,0000ff,10,1,lt'/>";
 110:    //Logger.log(url);
 111:    return url //.replace("&", "&amp;");  
 112:  
 113:  }
This entry was posted in 実施例 and tagged , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <img localsrc="" alt="">