Edited at

GASを使ってAndroidアプリのインストール数を自動で取得してスプレッドシートに入れる

More than 3 years have passed since last update.


はじめに

Androidアプリのインストール数を取得したいという要望があり、Google Apps Scriptなら手軽に書けてスプレッドシートにもサクッと挿入できるのでは…?と思ってやってみたらできたので、メモとして書いておきます。

基本コピペをすればできるように書いたつもりなので、GASの知識がなくても自動で取得するようにできる…はず。


流れ

画像多めですごく長いので、大まかにやることの流れだけ書いておきます

1. GASでGoogle Cloud Storageにアクセスできるように認証情報を作成する

2. 認証情報を使ってGCSからレポートを取得するのに必要なAccessTokenを取得するスクリプトを書く(コピペ)

3. 自動実行できるようにRefreshTokenをつかってAccessTokenを取得するスクリプトを書く(コピペ)

4. Google Play Developer ConsoleでインストールレポートのURIをメモる

5. Androidアプリのインストール数を取得してスプレッドシートに挿入するスクリプトを書く(ほぼコピペ)

6. スクリプトを実行する

7. 定期実行する設定を行う


Google API ConsoleでAPIを有効にする

Google PlayのインストールレポートはGoogle Cloud Storageの中に入っているので、それをダウンロードできるようにGoogle Cloud Storage JSON APIを有効にしておく


Google API Consoleで認証情報を作成する


クライアントIDとクライアント シークレット


  1. 認証情報を作成ボタンを押して、「OAuth クライアント ID」を選択



  2. 名前は適当に決めて、「承認済みのリダイレクトURI」のところにはGoogle Apps ScriptのURLのmacros/d/から/editの間にあるKey的なやつを取り出して以下の様なURLにして入れておく

    (下で説明してるスクリプトエディタを開いたときのURLから取り出す)


https://script.google.com/macros/d/<<--Key的なやつ-->>/usercallback



3. 作成してできたクライアントIDとクライアント シークレットをどこかにメモしておく


認証情報をスクリプトプロパティにセットする


  1. スクリプトエディタを開く



  2. プロジェクトのプロパティを開く



  3. スクリプトのプロパティタブを開いて、「行を追加」からclientIdとclientSecretを追加して「保存」ボタンを押す



これで準備はOK


AccessTokenを取得する


  1. スクリプトの名前を分かりやすいように変えておく




  1. AccessTokenの取得スクリプトを書く(コピペでOK)

var prop = PropertiesService.getScriptProperties()

var clientId = prop.getProperty("clientId");
var clientSecret = prop.getProperty("clientSecret");
var redirect_uri = "https://script.google.com/macros/d/<<--Key的なやつ-->>/usercallback";

function startOAuth(){
var url = 'https://accounts.google.com/o/oauth2/auth?client_id=' + clientId;
url += '&redirect_uri=' + encodeURIComponent(redirect_uri);
url += '&scope=' + encodeURIComponent("https://www.googleapis.com/auth/devstorage.read_only");
url += '&state=' + ScriptApp.newStateToken().withMethod('callback').withArgument('name', 'value').withTimeout(2000).createToken();
url += '&response_type=code';
url += '&approval_prompt=force';
url += '&access_type=offline';

var template = HtmlService.createTemplate('<center><a href="<?= AUTH_URL ?>" target="_blank">認証開始</a>. </center>' +
'<center>認証完了したらタブを閉じて再度実行してください</center>');
template.AUTH_URL = url;
var page = template.evaluate();
// 認証URLへ飛ばす
SpreadsheetApp.getUi().showModalDialog(page, "Google API認証");
}

function callback(e){
Logger.log(e.parameter.code);
var params = {
"method" : "POST",
"payload" : {
"code" : e.parameter.code,
"client_id" : clientId,
"client_secret" : clientSecret,
"redirect_uri" : redirect_uri,
"grant_type" : "authorization_code"
},
"muteHttpExceptions" : true
};
var res = UrlFetchApp.fetch('https://accounts.google.com/o/oauth2/token', params);
var dat = JSON.parse(res.getContentText());
var access_token = dat.access_token;
var refresh_token = dat.refresh_token;

prop.setProperty('access_token', access_token);
prop.setProperty('refresh_token', refresh_token);
}


実行してみる


  1. 実行メニューからstartOAuthを選んで実行



  2. 許可を求められるので許可する



  3. また許可を求められるので許可する 



  4. スプレッドシート側にこんな画面がでてくるので認証開始を押す



  5. また許可を求められるので許可する



  6. 何も返してないので何も出てきませんが、こんな感じの画面が出てきたら完了



  7. スクリプトのログを確認



  8. こんな感じでAccessTokenっぽいものが出てきてたらOK



  9. また、スクリプトのプロパティにaccess_tokenとrefresh_tokenが入っていればOK




RefreshTokenを使ってAccessTokenを取得する

AccessTokenには期限があるため、上記の認証方法では、しばらくするとまた認証許可を行わなければならないため、定期的に自動で取得することができません。

そこで、認証時に取得したRefreshTokenを使ってAccessTokenを取得することで、毎回新しいAccessTokenを取得できるようにします。(コピペでOK。上記のスクリプトに追記する)

function getAccessToken() {

if (prop.getProperty("access_token") == null) {
startOAuth();
return;
}

var payload;
if (prop.getProperty("refresh_token") != null) {
payload = {
"client_id" : clientId,
"client_secret" : clientSecret,
"redirect_uri" : redirect_uri,
"grant_type" : "refresh_token",
"refresh_token" : prop.getProperty("refresh_token")
};
} else {
return null;
}

var params = {
"method" : "POST",
"payload" : payload,
"muteHttpExceptions" : true
};
var res = UrlFetchApp.fetch('https://accounts.google.com/o/oauth2/token', params);
var dat = JSON.parse(res.getContentText());
var access_token = dat.access_token;
prop.setProperty('access_token', access_token);
Logger.log(access_token);
return access_token;
}


というわけで実行してみる


  1. getAccessTokenを実行



  2. ログを見て、無事に取得できてればOK



Google Play Developer ConsoleでレポートのURIを確認する


  1. GPDCの統計情報からアプリを選ぶ



  2. 下の方にあるレポートの直接URIの/stats/installsと書いてあるやつの黒で隠してある部分の数字をメモる




Androidアプリのインストール数を取得してスプレッドシートに挿入する


前準備



  1. 元データという名前のシートを作る

    (名前は何でもいいけどスクリプトの中に書いちゃったので)

  2. 一番上にカラム名と、dateの部分に日付を入れておく

    (スプレッドシートに記載してある日付を元にその行に値を入れるので、日付入ってないと動きません)



スクリプトファイルを2つ作る

メニューからスクリプトファイルを選んで、


  1. Utils



  2. AndroidAppReport



を作成する


Utils.gsに以下をコピペ

var SPREADSHEET = SpreadsheetApp.openById("ここにスプレッドシートのKeyを記入");

/** スプレッドシートを取得 */
function getSheetByName(sheetName) {
return SPREADSHEET.getSheetByName(sheetName);
}

// スプレッドシートに値を入れる
function setValueToSpreadsheet(sheetName, arrayValue, rowCount, columnCount) {
// スプレッドシートを取得
var sheet = getSheetByName(sheetName);
// シートに書き込む
sheet.getRange(rowCount, columnCount, arrayValue.length, arrayValue[0].length).setValues(arrayValue);
}

/** 今月の行の位置を取得する */
function getThisMonthRow(offset) {
if(!hasSheet("tmp")) {
SPREADSHEET.insertSheet("tmp");
}
var sheet = SPREADSHEET.getSheetByName("tmp");
var date = getDate(offset);
var r = sheet.getRange(1, 1).setFormula("MATCH(DATE("+Utilities.formatDate(date, "JST", "yyyy,MM,01")+"),元データ!B:B,0)");
var reply = sheet.getDataRange().getValues();
SPREADSHEET.deleteSheet(sheet);

return reply;
}

/** 年月を取得 */
function getFormatDateString(isSlash, offSet) {
var myDate = new Date();
var dayOfMonth = myDate.getDate();
myDate.setDate(dayOfMonth + offSet);
if (isSlash) {
return Utilities.formatDate(myDate, "JST", "yyyy/MM");
}
return Utilities.formatDate(myDate, "JST", "yyyyMM");
}

/** 日付を取得する */
function getDate(offSet) {
var myDate = new Date();
var dayOfMonth = myDate.getDate();
myDate.setDate(dayOfMonth + offSet);
return myDate;
}

/** シートが存在するかどうか */
function hasSheet(sheetName) {
var sheet = getSheetByName(sheetName);
if (sheet == null) {
return false;
}
return true;
}

/** 正規表現でセパレート */
function separate(num){
return String(num).replace( /(\d)(?=(\d\d\d)+(?!\d))/g, '$1,');
}

/** Google Cloud Storageからファイルを取得する */
function getFromGcs(url) {
var token = getAccessToken();
var response = UrlFetchApp.fetch(url, {
muteHttpExceptions:true,
headers: {
"Authorization": "Bearer " + token,
},
method: "GET"
});
return response.getContentText();
}

/** 余計な文字を除外して取得 */
function fixedString(str, package_name) {
var fixed_str = "";
for (var i = 0; i < str.length; ++i) {
if (str.charCodeAt(i) != 0 && str.charCodeAt(i) != 65533) {
fixed_str += str[i];
}
}
fixed_str = fixed_str.replace(new RegExp(package_name, 'g'), "");
return fixed_str;
}

一番上の、ここにスプレッドシートのKeyを記入と書いてある部分に以下のここと書いてある部分をコピーして貼り付けておく

https://docs.google.com/spreadsheets/d/ここ/edit


AndroidAppReport.gsに以下をコピペ

レポートのURIを確認したときにメモった数字を、一番上の部分に記入し、ここにアプリのパッケージ名を記入と書いてある部分に、レポートを取得したいアプリのパッケージ名を記入する。

var bucket_id = "ここにレポートのURIを確認したときの数字を記入";

function main() {
getInstalls("ここにアプリのパッケージ名を記入");
}

function getInstalls(package_name) {
// URLを作成する
var object_url = "https://www.googleapis.com/storage/v1/b/pubsite_prod_rev_" + bucket_id + "/o/stats%2Finstalls%2Finstalls_" + package_name + "_" + getFormatDateString(false, -3) + "_overview.csv";
// Google Cloud Storageからファイルの情報を取得する
var data = getFromGcs(object_url);
// jsonをparseする
var obj_meta_data = JSON.parse(data);

// 実際のデータが入ってるURLからcsvを取得してくる
data = getFromGcs(obj_meta_data.mediaLink);
// 余計な文字列を削除する
var fixed_data = fixedString(data, package_name);
// csvをparseする
var csv_data = Utilities.parseCsv(fixed_data);
// 一番上の行を消す
csv_data.shift();
// 今月最初の日付の位置を取得する(今日が2016/06/27なら2016/06/01の位置が返ってくる)
var this_month_row = getThisMonthRow(-3);
if (this_month_row > 0) {
// スプレッドシートにデータを挿入する
setValueToSpreadsheet("元データ", csv_data, this_month_row, 2);
}
}


実行する

AndroidAppReport.gsを開いて、上のメニューからmainを実行する。

許可を求められるので、許可する

スプレッドシートへのアクセス許可を求められるので、許可する

エラーが出なければ無事に実行完了しているはずなので、スプレッドシートを確認する

できた!


インストール数の取得を定期的に実行させる

Google Apps Scriptではトリガーというものをセットして任意の処理を定期的に実行させることができるので、それを利用してインストール数を自動で取得できるようにする


  1. このボタンを押す



  2. こんな感じで設定して保存ボタンを押す


これで毎日7時くらいにスプレッドシートに自動で値が挿入されるようになります。

エラーが発生したときに通知させたいときは「通知」ボタンからその設定もすることができます。

すばらしい!


おまけ


Chatworkに通知できるようにする

弊社ではChatworkを使っているので、Chatworkにも最新の数値を自動で通知するようにしてみました。

これがChatworkにpostするfunction。

var API_KEY = "ここにAPIKeyを記入";

function chatworkPost(room_id, message) {
var options = {
method: 'post',
headers: {
"X-ChatWorkToken": API_KEY,
},
payload: {
"body": message
}
};
var response = UrlFetchApp.fetch("https://api.chatwork.com/v1/rooms/" + room_id + "/messages", options);
return response;
}

あとは下記のスクリプトをgetInstallsの一番下に追記するだけでOK

function getInstalls(package_name) {

/** 省略 */

var date = csv_data[csv_data.length -1][0].split("-");
var format_date = date[0] + "" + date[1] + "" + date[2] + "";
var str = "[info][title]";
str += format_date + " のAndroidアプリインストールレポート[/title]";
str += "【端末】現在のインストール数\t\t\t\t: " + separate(csv_data[csv_data.length -1][2]) + "\n";
str += "【端末】デイリーインストール数\t\t\t\t: " + separate(csv_data[csv_data.length -1][3]) + "\n";
str += "【端末】デイリーアンインストール数\t\t\t: " + separate(csv_data[csv_data.length -1][4]) + "\n";
str += "【端末】デイリーアップグレード数\t\t\t: " + separate(csv_data[csv_data.length -1][5]) + "\n";
str += "【ユーザー】現在のインストール数\t\t\t: " + separate(csv_data[csv_data.length -1][6]) + "\n";
str += "【ユーザー】デイリーインストール数\t\t\t: " + separate(csv_data[csv_data.length -1][8]) + "\n";
str += "【ユーザー】デイリーアンインストール数\t\t: " + separate(csv_data[csv_data.length -1][9]) + "\n";
str += "【ユーザー】合計インストール数\t\t\t\t: " + separate(csv_data[csv_data.length -1][7]) + "[/info]";
chatworkPost(ROOM_ID, str);
}


おわりに

自動取得できるcsvファイルは3日ほど遅れているので、常に最新値を取得できるわけではないですが、スプレッドシートに値があれば色々なことができると思うので、ぜひ使ってみてはいかがでしょうか。

以上、おつかれさまでした。


参考