どうも、WACULでフロントエンドエンジニアをしている @Quramy です。
はじめに
WACULで運営しているAIアナリストはGoogle Analytics(以下GA)からデータを取得し、さまざまな解析を行うサービスです。
なので、日々GAのAPIやデータ可視化と戯れているわけですが、今日はGAのデータを可視化する方法について書きたいと思います。
どうやってやるか?
GAのAPI結果をグラフなどで表示する方法は、いくつか考えられます:
- GA Embed API を利用する
- APIの結果をGoogle Charts APIやchart.js, d3.js を使って自分で可視化する
大半の場合においては 1.で事が足りると思います。
ただし、Embed APIは提供されるAPIがハイレベルであり、「APIを実行する」部分と「可視化を行う」部分が密に結合している感があります。
このため、「GAのAPIは既に実行済みであり、すでに結果のオブジェクトを持っている」場合や、「GA APIのリクエストに独自のproxyを経由しているため、APIのエンドポイントが異なる」場合は利用が難しくなります。
このようなケースでは、2.を選ぶことになるでしょう。
このエントリでは、2.の方法を説明していきます。
やってみよう
GAのAPIを可視化するにあたり、手っ取り早く使えるライブラリはGoogle Charts APIです。
まずはPieChartを表示してみましょう。 Charts APIのPie Chartのガイド に"CODE IT YOURSELF ON JSFIDDLE" というリンクがあるので、こいつを叩いてJS Fiddleの画面を出しておきます。
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Task', 'Hours per Day'],
['Work', 11],
['Eat', 2],
['Commute', 2],
['Watch TV', 2],
['Sleep', 7]
]);
var options = {
title: 'My Daily Activities'
};
var chart = new google.visualization.PieChart(document.getElementById('piechart'));
chart.draw(data, options);
}
単純にPieChartを描画するサンプルコードですね。今回はこれをカスタマイズして、GAのAPIの結果を描画出来るようにしてみたいと思います。
続いて、GAのQuery Explorer から、下記のようにクエリを組んで実行してみましょう。
チャネルグループ毎のセッション数を取得するシンプルなクエリです。
余談ですが、今回題材にしているGAのViewは @QuramyのQiitaのViewです。Qiitaのアカウント設定画面 から, GA連携できるので、やってみることをオススメします。
"Run Query"をクリックすると、APIが実行されるので、このときのレスポンスを見てみましょう。
UI上は表示されていませんが、Query Explorerで実行するQueryには必ず output=dataTable
というパラメータが付与されます。
このため、レスポンスデータにはdataTable
というObjectがぶら下がります(下図):
dataTable - Data Table オブジェクトを含み、dataTable プロパティをレスポンスで出力します。この Data Table オブジェクトは、Google グラフのビジュアル表示で直接使用できます。
とあります。
一方、Google Charts APIのDataTable Classのリファレンスを読むと、以下のように引数にオブジェクトリテラルを渡すことで、DataTableのインスタンスが簡単に作れる、と記載されています:
Examples
The following example demonstrates instantiating and populating a DataTable with a literal string, with the same data as shown in the JavaScript example above:
var dt = new google.visualization.DataTable({
cols: [{id: 'task', label: 'Task', type: 'string'},
{id: 'hours', label: 'Hours per Day', type: 'number'}],
rows: [{c:[{v: 'Work'}, {v: 11}]},
{c:[{v: 'Eat'}, {v: 2}]},
{c:[{v: 'Commute'}, {v: 2}]},
{c:[{v: 'Watch TV'}, {v:2}]},
{c:[{v: 'Sleep'}, {v:7, f:'7.000'}]}]
}, 0.6);
なるほどね、APIの実行結果をDataTableに食わせれば瞬殺じゃん!
先ほどのJS Fiddleのコードを下記のように書き換えれば良さそうです。
google.setOnLoadCallback(drawChart);
function drawChart() {
var queryUrl = /* ここにQuery Explorer のAPI Query URI を貼り付ける*/
$.ajax({
url: queryUrl + '&output=dataTable'
}).done(function(response) {
var data = new google.visualization.DataTable(response.dataTable);
var options = {
title: 'Channel Group Access'
};
var chart = new google.visualization.PieChart(document.getElementById('piechart'));
chart.draw(data, options);
});
}
実行してみると、、、、
いや、これは違う。何かがおかしい。
原因は至極単純で、ga:sessions
は数値型ですが、APIの戻り値上はStringとなってしまっているため、計算が出来てなくなってしまうからです。「直接使用できます」が聞いて呆れるぜ...
実際、Embed APIのWeb Component実装のコードを紐解いてみると、https://github.com/GoogleWebComponents/google-analytics/blob/master/google-analytics-chart.html#L389 にレスポンスの型変換を明示的にやっている部分が見つかりました。
/**
* The analytics api erroneously return some values as strings that are
* supposed to be numbers. This function fixes that.
* @param {Object} dataTable - The dataTable data.
*/
function ensureProperDataTableTypes(dataTable) {
for (var i = 0; i < dataTable.rows.length; i++) {
var row = dataTable.rows[i];
for (var j = 0; j < row.c.length; j++) {
if (dataTable.cols[j].type === 'number') {
row.c[j].v = Number(row.c[j].v);
}
}
}
}
Embed APIにならって、先ほどのFiddleにこのensureProperDataTableTypes
を仕込んで再実行してみると、、、
google.setOnLoadCallback(drawChart);
function ensureProperDataTableTypes(dataTable) {
for (var i = 0; i < dataTable.rows.length; i++) {
var row = dataTable.rows[i];
for (var j = 0; j < row.c.length; j++) {
if (dataTable.cols[j].type === 'number') {
row.c[j].v = Number(row.c[j].v);
}
}
}
return dataTable;
}
function drawChart() {
var queryUrl = /* ここにQuery Explorer のAPI Query URI を貼り付ける*/
$.ajax({
url: queryUrl + '&output=dataTable'
}).done(function(response) {
var data = new google.visualization.DataTable(ensureProperDataTableTypes(response.dataTable));
var options = {
title: 'Channel Group Access'
};
var chart = new google.visualization.PieChart(document.getElementById('piechart'));
chart.draw(data, options);
});
}
おー、ようやくPieChartが描画された(JS Fiddleにも同じものを置いてます)。
ここまでをまとめると、下記となります:
- GAのAPIに
output=dataTable
を付与するとdataTable風のレスポンスが貰える - APIの結果のdataTableオブジェクトについて、適切な型変換を実施する必要がある
- Charts APIのDataTable Classのコンストラクタに食わせると、chart描画用のDataTableが作れる
ちなみに、上述のensureProperDataTableTypes
ですが、DataTableで利用可能な型にはnumber
, string
以外にも date
, datetime
, dayOfWeek
, boolean
があるので、真面目にやるのであれば、こいつらも変換する必要があります。
DataTableとDataView
このエントリではPieChartを例にして説明してきましたが、他のChartTypeでは、より複雑なDataTableを使うこともあるでしょう。
例えば、BubbleChartはData Formatとして、"名前, 数値(x座標値), 数値(y座標値), ラベル, 数値(円の大きさ)" のパターンを要求します
一方、GAのAPIの結果は、"demension1, demension2, ..., metric1, metric2,..." という列の並びになってしまうため、直接DataTableを渡してもグラフの描画が出来ないパターンがあります。
このような時は、DataViewクラスとsetColumns
を利用して、元のDataTableに対する列のマッピングを変更すると良いです:
var data = new google.visualization.DataTable(ensureProperDataTableTypes(response.dataTable));
var view = new google.visualization.DataView(data);
view.setColumns([0,2,3,0,1]); // dataTableとDataViewの列マッピングを指定
//:
chart.draw(view, options);
おまけ
このエントリのおまけとして、GAのQuery Explorer上に直接グラフ表示を行うChrome Extensionを作ってみました。
このExtensionを作るにあたり、
- Chrome Extension(webRequest, sandBox)
- Charts API
- Analytics core reporting API
- AngularJS
というGoogleどっぷりスタックを組んだのですが、Charts APIがChrome Extensionに組み込み辛すぎて泣けました。
この辺の苦労話もそのうち書きたいけど、今日はもう疲れたので、ここいらで筆を休めたいと思います。