前回の記事に引き続き、実際に作っていくところです。
コードを書く前にいくつか準備が必要です。Googleアプリは準備が不要でコードをガリガリできるところが魅力なのですが、GCPと絡むとそこら辺の魅力が半減です。
まずは、いつも通りスプレッドシートからApps Scriptプロジェクトを作成してください。
そのあと、AppsScriptの設定からマニフェストファイルを表示する設定に変更します。
「appsscript.json」マニフェスト ファイルをエディタで表示する にチェックを入れます。
ついでに、Google Cloud Platform(GCP)プロジェクト番号も入れましょう。
GCPと自分のGoogleアカウントを紐づけ、プロジェクトを作成しOAuth権限設定をし、APIライブラリからGA4のAPI、スプレッドシートのAPI、GmailのAPIを有効にします。
面倒なのでこんな風に書きましたが、こちらの記事が非常に参考になります。ありがとうございます。
で、GASに戻ります。
コード
やりたいことはGA4の情報をとってくること、取ってきた情報をもとにデータ整形すること、それをCSVダウンロードすること、定期的にメールでも送信すること。ついでにスプレッドシートのサイドバーも使用してツールっぽくしたいと思います。
盛りだくさんですね。
まずは、マニフェストファイルをみましょう。
{
"timeZone": "Etc/GMT-9",
"dependencies": {
},
"exceptionLogging": "STACKDRIVER",
"oauthScopes": ["https://www.googleapis.com/auth/script.external_request", "https://www.googleapis.com/auth/analytics.readonly", "https://www.googleapis.com/auth/spreadsheets","https://www.googleapis.com/auth/script.container.ui","https://www.googleapis.com/auth/drive","https://www.googleapis.com/auth/drive.file","https://www.googleapis.com/auth/script.send_mail"],
"runtimeVersion": "V8"
}
で、GA4の情報を取得するコードです。
getGa4PV.gsという名前のファイルです。
//GA4 APIのrunReportを実行する関数
function getGa4PV(start_date, end_date) {
//アクティブなスプレッドシートからrunReportの出力結果を格納するシートを読み込み
let mySheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("GA4data");
//runReportのAPIリクエストを行うPOSTのURLを定義(***がGA4のプロパティID)
let apiURL = 'https://analyticsdata.googleapis.com/v1beta/properties/*********:runReport';
//POSTする際に必要となるディメンションやメトリクス、データ期間を設定
let setDimension = [{'name': 'pagePathPlusQueryString'}];
let setMetrics = {'name': 'screenPageViews'};
let setDateRange = {'startDate': start_date,'endDate': end_date};
//APIリクエスト時にセットするペイロード値を設定する
let payload = {
'dimensions' : setDimension,
'metrics': setMetrics,
'dateRanges': setDateRange
};
//HTTPSのPOST時のオプションパラメータを設定する。APIの認証のため、headersの情報も必須
let options = {
'payload' : JSON.stringify(payload),
'myamethod' : 'POST',
'muteHttpExceptions' : true,
'headers' : {"Authorization" : "Bearer " + ScriptApp.getOAuthToken()},
'contentType' : 'application/json'
};
//APIリクエストを行った結果のJSONデータを変換する
let response = UrlFetchApp.fetch(apiURL,options);
let json = JSON.parse(response);
//スプレッドシートにレポートデータを格納できるように、forループの処理で二次元配列に格納する
let ga4Data = [];
for(let i=0;i<json["rows"].length;i++){
ga4Data[i] = [json["rows"][i]["dimensionValues"][0]["value"],json["rows"][i]["metricValues"][0] ["value"]];
}
//スプレッドシートにrunReportの実行結果を格納
mySheet.getRange(2, 1, ga4Data.length, ga4Data[0].length).setValues(ga4Data);
SpreadsheetApp.flush();
}
GA4のプロパティIDの部分はご自身のものに変えてくださいね。
GA4dataというシートに下記内容の情報を取得して書き込みます。
let setDimension = [{'name': 'pagePathPlusQueryString'}];
→ディメンションにクエリ文字入りURIを指定
let setMetrics = {'name': 'screenPageViews'};
→ディメンションに対してページビューを指定
期間は関数の引数で指定します。サイドバー上(HTML)で期間を指定し、GASに引き渡します。
このGA4dataというシートにGA4の情報がドバっと出てきます。
このシートを参照するシート([結果]という文字をシート名に入れる)を作成し、お好きなように関数等で必要なデータを抜き出し整形する感じです。
私の場合は、URLにコンテンツのIDやコンテンツ名が組み込まれているWEBサイトなので、IDやコンテンツ名のマスターを作成し、それにマッチするGA4dataの値を集計し、SORT関数等でランキング形式に整形しています。
次はindex.htmlというファイルです。サイドバーに表示する内容です。
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons1.css">
</head>
<body>
<div class="sidebar">
<div class="block form-group">
<h2>取得期間を指定</h2>
<p>start
<input type="date" min="2021-05-01" id="start_date"><br>
~
end
<input type="date" min="2021-05-01" id="end_date">
</p>
</div>
<div class="block form-group">
<p>
<button class="blue" onclick="getPV()" id="getPVbuttom">結果を取得する</button>
<button class="gray" onclick="getCSV()" id="getCSVbuttom">CSVを取得する</button>
</p>
<p>
※[結果]シートが全てダウンロードされます。
</p>
</div>
</div>
</body>
<script>
function getPV(){
alert("情報更新中...\n画面を閉じずに少々お待ちください。");
const start_date = document.getElementById("start_date").value;
const end_date = document.getElementById("end_date").value;
google.script.run
.withSuccessHandler(successPV)
.runScripts(start_date, end_date);
}
function successPV(message){
alert(message);
}
function getCSV(){
alert("ダウンロードを開始します。アラートが出る場合は許可してください。");
google.script.run
.withSuccessHandler(dlCSV)
.getCSV();
}
function dlCSV(dataList) {
dataList.forEach(data => {
const blob = new Blob([ data.body ], { "type" : "text/csv"});
const link = document.createElement('a');
link.download = `${data.title}.csv`;
link.href = window.URL.createObjectURL(blob);
link.click();
});
}
</script>
</html>
HTMLだけでは表示できませんので、これを表示するためのコードも書きます。
sidebar.gsというファイル名にしました。
function onOpen() {
SpreadsheetApp.getUi()
.createMenu('GA4情報取得ダイアログを開く')
.addItem('GA4情報取得ダイアログ', 'showSidebar')
.addToUi();
}
function showSidebar() {
const htmlOutput = HtmlService.createHtmlOutputFromFile('index').setTitle('GA4情報取得ダイアログ');
SpreadsheetApp.getUi().showSidebar(htmlOutput);
}
function runScripts(start_date, end_date) {
getGa4PV(start_date,end_date);
SpreadsheetApp.flush();
return("情報を更新しました");
}
onOpen関数でサイドバーを表示します。スプレッドシートを開いた時点でこの関数を実行するために、トリガーを設定します。あとでトリガーのところもみましょう。
さあ、次はCSVを取得するコードです。
getCSV.gsというファイルです。
function getCSV() {
//シート名に[結果]とつくものをCSVとしてダウンロード
const sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
const datetime = Utilities.formatDate(new Date(),'Asia/Tokyo', 'yyyyMMddHHmm');
let sheet_name = "";
let dataList = [];
sheets.forEach(function(sheet){
sheet_name = sheet.getSheetName();
if(sheet_name.match(/[結果]/)){
const values = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheet_name).getDataRange().getValues();
dataList.push({
title: sheet_name + '_' + datetime,
body: values.join("\r\n")
});
}
});
return dataList;
}
スプレッドシートのシート名が”[結果]トップページPV数”みたいなシートの情報をCSVとして取得します。
最後に、CSVをメール送信するコードです。
素直にsendMail.gsです。
function sendMail() {
//前月の開始終了日を取得
const date = new Date();
const this_year = date.getFullYear();
const now_month = date.getMonth()+1; //1月=0,12月=11なので+1
const last_month = now_month -1;
const start = new Date(this_year, last_month-1, 1); //初日
const end = new Date(this_year, last_month, 0);//末尾
const start_date = Utilities.formatDate(start, 'JST', 'yyyy-MM-dd');
const end_date = Utilities.formatDate(end, 'JST', 'yyyy-MM-dd');
//GA4dataシートの情報を更新
getGa4PV(start_date,end_date);
const data = getCSV();
const target_list = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("通知設定").getDataRange().getValues().flat().filter(function(x){return !(x === null || x === undefined || x === "");});;
let attachments = [];
data.forEach(data => {
attachments.push({fileName:data.title + ".csv", mimeType:'text/comma-separated-values', content: data.body});
});
for(let i = 1; i < target_list.length; i++){
MailApp.sendEmail(target_list[i], "PV数月次レポート- "+ last_month +"月", "添付されているCSVをご確認ください。\n不具合不明点はシステム管理までご連絡ください。", {attachments:attachments});
}
}
スプレッドシートの”通知設定”というシートにメールアドレスを記載していき、その人を対象にメールを送ります。実行はGASのトリガー機能を使います。
さて、最後にトリガーを確認しましょう。
sendMailは時間主導型で毎月1日0時~1時に実行します。
onOpenはスプレッドシート主導型で起動時に実行します。
onOpenがあるのでshowSidebarは不要かもしれませんね。(面倒で試してません。。)
コードを書いていく上での感じたポイントは、
・SpreadsheetApp.flush(); を処理の最後実行しないとGA4情報取得APIはうまく動いているのにスプレッドシート状で見た目が更新されないことがある
・CSVデータをメールやHTMLに渡す際に、Blob(Binary large object)という形に変換しないといけない
・HTMLからCSVをダウンロードするために、テキストデータを渡してHTML上でBlobに変換、そのリンクを作成しリンククリックするというちょっと回りくどいやり方をしている(たぶんこうするしかない)
といったところでしょうか。
もしGA4の情報をGA4にアクセスしてGUIで参照している方がいれば、是非自動化してみてください。
コメント