本篇要解決的問題
一間公司裡可能旗下會有多個網站,想同時查看所有網站的 GA 數據,通常需要開啟多個瀏覽器視窗並排顯示,操作較為繁瑣。
如果可以改由 API 來取得 GA 的數據,工程師就可以把各站的資料顯示在一個頁面上,而不用同時開多個 GA 來看。
開通 GA API
取得 GCP 專案編號
要先有 Google Cloud Platform(GCP)的專案,沒有的話登入自己的 Google 帳號,就可以先增一個。
專案編號就在 資訊主頁 上:
開通 GA API 功能
在使用 API 前,必須先於 GCP 開通對應的功能。
GCP 的專案點擊選單中的「API 和服務」> 「程式庫」:
搜尋框上搜尋「google analytics data api」,會看到結果清單裡會出現「Google Analytics Data API」,點進去後,再點擊啟用,就完成了:
取得 GA 的資源 ID
看要抓的是哪一個 GA 的資料,進到 GA 後台,進到「管理」,點擊「資源詳細資料」:
接著右上角就會看到資源編號:
調用 GA API 程式碼部份
因為調用 Google 的 API,要先經過認證的程序,但如果是寫在跟 GA 相同帳號的 Google Apps Script,就可以省掉這一段。
Google Apps Script 上新增專案
到 Google Apps Script 的頁面上,新增一個專案:
接著可以直接複製貼上以下的程式碼。
瀏覽量、活躍人數
以下程式碼是抓瀏覽量、活躍人數的:
var propertyId = "xxxxxx"; // 替換成 GA 的資源編號
var startDate = "2025-01-01", // 替換成想要從哪一天開始抓的日期
function getGA4Data() {
var apiUrl = `https://analyticsdata.googleapis.com/v1beta/properties/${propertyId}:runReport`;
var payload = {
"dateRanges": [{
"startDate": startDate,
"endDate": "today"
}],
"metrics": [
{ "name": "screenPageViews" }, // 瀏覽數
{ "name": "activeUsers" } // 活躍用戶數
]
};
var options = {
"method": "post",
"contentType": "application/json",
"headers": {
"Authorization": "Bearer " + ScriptApp.getOAuthToken()
},
"muteHttpExceptions": true,
"payload": JSON.stringify(payload)
};
var response = UrlFetchApp.fetch(apiUrl, options);
var data = JSON.parse(response.getContentText());
// 檢查回應中是否有 rows 資料
if (data.rows && data.rows.length > 0) {
// 取得瀏覽數和活躍用戶數
var screenPageViews = data.rows[0].metricValues[0].value;
var activeUsers = data.rows[0].metricValues[1].value;
// 回傳資料
return {
"totalPageViews": screenPageViews,
"activeUsers": activeUsers
};
} else {
// 若無符合資料,則回傳 0 作為預設值
return {
"totalPageViews": 0,
"activeUsers": 0
};
}
}
瀏覽量、活躍人數:指定頁面標題
除了抓全站的資料,可以抓指定網頁的 title 是什麼結尾,比如這邊抓的是「會員中心」為結尾的頁面:
var propertyId = "xxxxxx"; // 替換成 GA 的資源編號
var startDate = "2025-01-01", // 替換成想要從哪一天開始抓的日期
var pageTitle = "會員中心"; // 替換成想要篩選的頁面標題文字
function getGA4DataPage() {
var apiUrl = `https://analyticsdata.googleapis.com/v1beta/properties/${propertyId}:runReport`;
var payload = {
"dateRanges": [{
"startDate": startDate,
"endDate": "today"
}],
"metrics": [
{ "name": "screenPageViews" }, // 瀏覽數
{ "name": "activeUsers" } // 活躍用戶數
],
"dimensionFilter": {
"filter": {
"fieldName": "unifiedScreenName",
"stringFilter": {
"value": pageTitle,
"matchType": "ENDS_WITH"
}
}
}
};
var options = {
"method": "post",
"contentType": "application/json",
"headers": {
"Authorization": "Bearer " + ScriptApp.getOAuthToken()
},
"muteHttpExceptions": true,
"payload": JSON.stringify(payload)
};
var response = UrlFetchApp.fetch(apiUrl, options);
var data = JSON.parse(response.getContentText());
if (data.rows && data.rows.length > 0) {
var screenPageViews = data.rows[0].metricValues[0].value;
var activeUsers = data.rows[0].metricValues[1].value;
return {
"totalPageViews": screenPageViews,
"activeUsers": activeUsers
};
} else {
return {
"totalPageViews": 0,
"activeUsers": 0
};
}
}
即時人數
var propertyId = "xxxxxx"; // 替換成 GA 的資源編號
function getGA4RealtimeData() {
var apiUrl = `https://analyticsdata.googleapis.com/v1beta/properties/${propertyId}:runRealtimeReport`;
var payload = {
"metrics": [{
"name": "activeUsers"
}]
};
var options = {
"method": "post",
"contentType": "application/json",
"headers": {
"Authorization": "Bearer " + ScriptApp.getOAuthToken()
},
"muteHttpExceptions": true,
"payload": JSON.stringify(payload)
};
var response = UrlFetchApp.fetch(apiUrl, options);
var data = JSON.parse(response.getContentText());
// 取得即時人數
return data.rows[0].metricValues[0].value;
}
即時人數:指定頁面標題
這邊一樣是抓「會員中心」為結尾的頁面:
var propertyId = "xxxxxx"; // 替換成 GA 的資源編號
var pageTitle = "會員中心"; // 替換成想要篩選的頁面標題文字
function getGA4RealtimeDataPage() {
var apiUrl = `https://analyticsdata.googleapis.com/v1beta/properties/${propertyId}:runRealtimeReport`;
// 在 payload 中新增 dimensions 和 dimensionFilter
var payload = {
"metrics": [{
"name": "activeUsers"
}],
"dimensions": [{
"name": "unifiedScreenName"
}],
"dimensionFilter": {
"filter": {
"fieldName": "unifiedScreenName",
"stringFilter": {
"value": pageTitle,
"matchType": "ENDS_WITH"
}
}
}
};
var options = {
"method": "post",
"contentType": "application/json",
"headers": {
"Authorization": "Bearer " + ScriptApp.getOAuthToken()
},
"muteHttpExceptions": true,
"payload": JSON.stringify(payload)
};
var response = UrlFetchApp.fetch(apiUrl, options);
var data = JSON.parse(response.getContentText());
var totalActiveUsers = 0;
// 累加所有匹配頁面的人數
if (data.rows && data.rows.length > 0) {
data.rows.forEach(function (row) {
totalActiveUsers += parseInt(row.metricValues[0].value, 10);
});
}
return totalActiveUsers.toString(); // 返回所有匹配頁面的總人數
}
以 POST 的參數,判斷要給哪種資料
上面一共寫了四個函式,我們需要一個參數,讓 API 知道要回應的是哪個資料。
這邊用的參數是 type
,type
不同值,就給不同資料,共有 4 個值可以寫:
-
data
:瀏覽量、活躍人數。 -
dataPage
:瀏覽量、活躍人數:指定頁面標題。 -
realtimeData
:即時人數。 -
realtimeDataPage
:即時人數:指定頁面標題。
// 回應錯誤訊息
function createErrorResponse(message, code) {
var errorResponse = {
success: false,
error: message,
code: code || 400,
timestamp: new Date().toISOString()
};
var jsonOutput = ContentService.createTextOutput(JSON.stringify(errorResponse));
jsonOutput.setMimeType(ContentService.MimeType.JSON);
return jsonOutput;
}
// 處理 POST
function doPost(e) {
// 確認有傳入內容
if (!e.postData || !e.postData.contents) {
return createErrorResponse("無效請求:未收到 POST 資料。" + e.postData);
}
// 將 POST 資料解析成 JSON
var requestData;
try {
requestData = JSON.parse(e.postData.contents);
} catch (error) {
return createErrorResponse("JSON 格式無效。");
}
// 檢查是否有 type 參數
if (!requestData.type) {
return createErrorResponse("缺少「type」參數。");
}
var output;
// 根據 type 參數執行不同的邏輯
switch (requestData.type) {
// 瀏覽量、活躍人數
case "data":
var reportData = getGA4Data();
output = {
"totalPageViews": reportData.totalPageViews,
"activeUsers": reportData.activeUsers
};
break;
// 瀏覽量、活躍人數:指定頁面標題
case "dataPage":
var reportData = getGA4DataPage();
output = {
"totalPageViews": reportData.totalPageViews,
"activeUsers": reportData.activeUsers
};
break;
// 即時人數
case "realtimeData":
var reportData = getGA4RealtimeData();
output = {
"activeUsers": reportData
};
break;
// 即時人數:指定頁面標題
case "realtimeDataPage":
var reportData = getGA4RealtimeDataPage();
output = {
"activeUsers": reportData
};
break;
default:
return createErrorResponse("type 錯誤");
}
// 回傳 JSON 格式的結果
var jsonOutput = ContentService.createTextOutput(JSON.stringify(output));
jsonOutput.setMimeType(ContentService.MimeType.JSON);
return jsonOutput;
}
Google Apps Script 連結到 GCP 專案
左側選單點擊「設定」,接著頁面往下滑,有一項「 Google Cloud Platform (GCP) 專案」,點擊這項的「變更專案」:
接著輸入框就填上第一步在 GCP 上取得的編號,再點擊「設定專案」就可以了:
如果專案存在,連結就會成功,成功的畫面像這樣:
設定完後,這份 GAS 檔就可以使用 GCP 上開啟的 GA API。
部署 GAS
Google Apps Script 的程式如果要能對外,要部署出去才行。
點擊右上角的「部署」> 「管理部署作業」:
部署的類型是「網頁應用程式」:
「誰可以存取」要選擇「所有人」:
選好後,點擊「部署」,需要授權時就直接授權。
部署成功,就會取得一個網址,這個網址就是對外的 API 網址了:
最後,只要 POST 到這個網址,帶上指定的參數 type
,就可以取得我們想要的資料。
手動補權限
如果 POST 後,取到的資料一直是 0,代表部署時提供的權限不完整,就要手動補授權。
點擊左側的「專案設定」,在編輯器中顯示「appsscript.json」資訊清單檔案 打勾:
接著回到編輯器,會看到 appsscript.json 這個檔案,補上以下:
"oauthScopes": [
"https://www.googleapis.com/auth/script.external_request",
"https://www.googleapis.com/auth/analytics.readonly"
]
最後再次部署,會出現要補權限的授權,一律給過就行,就可以取得 GA 上的資料了。
完整程式碼
完整的 Google Apps Script 程式碼如下,可以直接複製貼上: