Created
March 29, 2025 08:50
-
-
Save letswritetw/5bcebc7b1b4d405f4459fe8a871d4f2c to your computer and use it in GitHub Desktop.
使用 Google Apps Script 串接 Google Analytics API,整合多站數據
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var propertyId = "XXXXXXXXXX"; // 替換成 GA 的資源編號 | |
var startDate = "2025-01-01"; // 替換成想要從哪一天開始抓的日期 | |
var pageTitle = "XXXXXXXXX"; // 替換成想要篩選的頁面標題文字 | |
// 瀏覽量、活躍人數 | |
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 | |
}; | |
} | |
} | |
// 瀏覽量、活躍人數:指定頁面標題 | |
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 | |
}; | |
} | |
} | |
// 即時人數 | |
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; | |
} | |
// 即時人數:指定頁面標題 | |
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(); // 返回所有匹配頁面的總人數 | |
} | |
// 回應錯誤訊息 | |
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; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment