簡單 3 步驟 — 打造免費 GA4 自動數據通知機器人
使用 Google Apps Script 完成 RPA,自行串接 GA4 + Telegram Bot 數據通知機器人

Photo by BoliviaInteligente
前言
大約從 2020 年開始就自己在摸索使用手邊工具實現 RPA,從一開始只是為了自動化個人例行任務,到後來工作也加入了規模更大型的組織,時常會遇到跨團隊或仰賴人與人的任務、甚至是重複性任務,才發現 RPA 自動化的效益所在。
舉例來說:某個重複任務每個月會發生 10 次,每次需花費 30 分鐘處理,有 60 人會遇到,每年團隊等於消耗 3,600 小時在這上面,如果能投資 100 小時開發成自動化,後續解放出來的時間,就能投入在更有價值的工作上;實際等於 3,600 浪費的工時+3,600 更值得投資的產出。
詳細可參考我之前的文章:
其他做過的 RPA:
- [GMail to Slack] 運用 Google Apps Script 轉發 Gmail 信件到 Slack
- [Google Form x Google Sheet xSlack] Slack 打造全自動 WFH 員工健康狀況回報系統
- [Big Query x Slack ] Crashlytics + Big Query 打造更即時便利的 Crash 追蹤工具
- [Google Analytics x Slack] Crashlytics + Google Analytics 自動查詢 App Crash-Free Users Rate
- [Github Webhook x Line Notify] 使用 Google Apps Script 三步驟免費建立 Github Repo Star Notifier
- [Slack x OpenAI (ChatGTP) ] Slack & ChatGPT Integration
- [Google Analytics x Google Sheet] 使用 Google Apps Script 實現每日數據報表 RPA 自動化
- [iOS Shortcut x Line x Reminders] iOS 捷徑自動化應用場景 — 自動轉發簡訊與自動建立提醒待辦事項
- [Apple Store API x Google Play Console API x Github Action] Github Action x ZReviewTender 免費快速部署你的 App 商城評價監控機器人
- [Telegram Bot] 10 分鐘快速移轉 Line Notify 到 Telegram Bot 通知
- [Medium to Jekyllrb] 無痛轉移 Medium 到自架網站
從後台數據看之前蠻多文章有被 ChatGPT 或各種 GenAI 服務收錄,間接的幫助了許多非工程背景但也想嘗試使用 RPA 解決問題的朋友,因此我仍會持續分享自己生活或工作上遇到的 RPA 場景跟我的解決方案與大家分享 — ZRealm Robotic Process Automation 。
工商時間
如果您與您的團隊有自動化工具、流程串接需求,不論是 Slack App 開發、Notion、Asana、Google Sheet、Google Form、GA 數據,各種串接需求,歡迎與我 聯絡開發 。
本篇 Google Analytics 4 x Telegram Bot
這次要介紹的串接場景是接續上一篇「 10 分鐘快速移轉 Line Notify 到 Telegram Bot 通知 」時想到我的 Medium 備份站「 zhgchg.li 」一直都沒有關注他的 GA4 網站數據,想說好像可以多做一個通知機器人,每日傳送過去 7 天的網站數據到指定的 Telegram Channel 讓我知道。
本篇只是小品,如果要做完整的自動化數據報表請參考之前的文章「 使用 Google Apps Script 實現每日數據報表 RPA 自動化 」另外之前也曾串過 GA4 撈取 App Crash-free rate 可參考此篇文章「 Crashlytics + Google Analytics 自動查詢 App Crash-Free Users Rate 」。
成果

先上最終效果,Google Apps Script 每日下午 12–13 點之間會自動去撈取我想要的 Google Analytics 4 網站數據並組合成訊息透過 Telegram Bot 傳送到我的 Telegram Channel,我可以快速檢閱近 7 天網站數據。
我想要觀測的數據是:
- 近 7 天
7daysAgo ~ today總瀏覽數screenPageViews - 活躍使用者數
active7DayUsers - 新使用者數
newUsers - Top 10 瀏覽頁面
screenPageViews/pageTitle - 新使用者最初來源媒介
newUsers/firstUserSourceMedium
實際可依照你自己的需求使用 GA Dev Tools 產生調整。
Step 1. 使用 GA4 Query Explorer 官方工具 產生數據報表查詢參數
首先,我們需要使用 GA4 Query Explorer 官方提供的工具產生我們需要的查詢數據報表參數:

- Select Property: 記下你的
property 編號property 編號稍後撰寫 Google Apps Script 會使用。 - start date, end date: 報表開始~結束的日期範圍,可使用
YYYY-MM-DD或yesterday,today,NdaysAgo魔術變數。 - metrics: 選擇你想要查詢的指標
- dimensions: 選擇你想要查詢的維度
- metric aggregations: 數據合併計算規則
這邊以我的場景為例:
- property 編號:
318495208 - start_date:
7daysAgo - end_date:
yesterday因 GA 數據報表會延遲,查詢前一天~七天最準確。 - metric aggregations:
total
其他 filter, limit 可依照自己需求設定:

filter 我用不到留空;limit 我輸入 10,因為我只想知道 Top 10。
點擊「MAKE REQUEST」產生對應的數據報表查詢參數及結果:

記下以下請求參數,稍後撰寫 Google Apps Script 會使用:
{
"dimensions": [
{
"name": "pageTitle"
}
],
"metrics": [
{
"name": "screenPageViews"
}
],
"dateRanges": [
{
"startDate": "7daysAgo",
"endDate": "yesterday"
}
],
"limit": "10",
"metricAggregations": [
"TOTAL"
]
}
結果:


- 與 GA 上的數據比較是否正確,正確相符 ✅✅✅
Step 2. 建立 Google Apps Script & 使用 Google Analytics Data API 查詢資料
- 前往 https://script.google.com/home
- 建立新專案,命名專案名稱
- 點擊「服務」->「+」新增服務
- 選擇「Google Analytics Data API」
- 點擊「新增」

貼上 Google Analytics Data API 查詢程式碼並組合:
將前面步驟產生的報表查詢數據參數:
{
"dimensions": [
{
"name": "pageTitle"
}
],
"metrics": [
{
"name": "screenPageViews"
}
],
"dateRanges": [
{
"startDate": "7daysAgo",
"endDate": "yesterday"
}
],
"limit": "10",
"metricAggregations": [
"TOTAL"
]
}
轉換成程式:
function execute() {
Logger.log(JSON.stringify(fetchScreenPageViews("318495208")));
}
// 拆成獨立方法,方便日後重複使用...
// 預設 startDate=7daysAgo, endDate=yesterday
// 其他用法:
// e.g. fetchScreenPageViews("1111". "3daysAgo", "yesterday")
// e.g. fetchScreenPageViews("2222". "yesterday", "today")
function fetchScreenPageViews(propertyId, startDate = "7daysAgo", endDate = "yesterday") {
const screenPageViewsMetric = AnalyticsData.newMetric();
screenPageViewsMetric.name = "screenPageViews";
const dateRange = AnalyticsData.newDateRange();
dateRange.startDate = startDate;
dateRange.endDate = endDate;
const pageTitleDimension = AnalyticsData.newDimension();
pageTitleDimension.name = "pageTitle";
const request = AnalyticsData.newRunReportRequest();
request.dimensions = [pageTitleDimension];
request.metrics = [screenPageViewsMetric];
request.dateRanges = dateRange;
request.limit = 10;
request.metricAggregations = "TOTAL";
return AnalyticsData.Properties.runReport(request, "properties/" + propertyId);
}
程式碼解析:
// metric 指標,可以是多個,請分開宣告...
const screenPageViewsMetric = AnalyticsData.newMetric();
screenPageViewsMetric.name = "screenPageViews";
// 例如另一個 active1DayUsers:
const active1DayUsersMetric = AnalyticsData.newMetric();
active1DayUsersMetric.name = "active1DayUsers";
// 宣告日期範圍
const dateRange = AnalyticsData.newDateRange();
dateRange.startDate = startDate;
dateRange.endDate = endDate;
// dimension 維度,可以是多個,請分開宣告...
const pageTitleDimension = AnalyticsData.newDimension();
pageTitleDimension.name = "pageTitle";
// 例如另一個 dimension:
const firstUserSourceMediumDimension = AnalyticsData.newDimension();
firstUserSourceMediumDimension.name = "firstUserSourceMedium";
//
// 產生 Request 物件
const request = AnalyticsData.newRunReportRequest();
request.metrics = [active1DayUsersMetric, active1DayUsersMetric]; // 多個就都帶入...
request.dimensions = [pageTitleDimension, firstUserSourceMediumDimension]; // 多個就都帶入...
request.dateRanges = dateRange;
// 只需要前 10 筆資料 (Top 10)
request.limit = 10;
// 設定數據合併計算邏輯:Total (SUM)
request.metricAggregations = "TOTAL";
// 產生查詢結果
return AnalyticsData.Properties.runReport(request, "properties/" + propertyId).rows;
第一次執行,會需要授權(日後若程式碼有新增需要的權限也會要重新認證一次):
實際上就是授權 Google Apps Script 日後使用你的帳號身份執行這些程式,所以需要確保你選擇的帳號身份有對應的 GA 報表存取權限。

- 撰寫好程式碼後,點擊「偵錯」-> 點擊「審查權限」

- 選擇要執行的身份帳戶,通常等於當前 Google Apps Script 帳戶

- 選擇「進階」展開 -> 點擊「前往 XXX」 這是我們自己寫給自己用的應用程式,不需經過 Google 驗證。

- 點擊「允許」
允許之後再點「偵錯」或「執行」就能執行程式:

這邊我們先使用 Logger.log(JSON.stringify()) 取得輸出結果:
{
"kind": "analyticsData#runReport",
"dimensionHeaders": [
{
"name": "pageTitle"
}
],
"rowCount": 71,
"metadata": {
"currencyCode": "TWD",
"timeZone": "Asia/Taipei"
},
"rows": [
{
"dimensionValues": [
{
"value": "ZhgChgLi"
}
],
"metricValues": [
{
"value": "166"
}
]
},
{
"metricValues": [
{
"value": "109"
}
],
"dimensionValues": [
{
"value": "Apple Watch 原廠不鏽鋼米蘭錶帶開箱 | ZhgChgLi"
}
]
},
{
"dimensionValues": [
{
"value": "iOS ≥ 13.1 使用「捷徑」自動化功能搭配米家智慧家居 | ZhgChgLi"
}
],
"metricValues": [
{
"value": "101"
}
]
},
{
"dimensionValues": [
{
"value": "Medium Partner Program 終於對全球(包含台灣)寫作者開放啦! | ZhgChgLi"
}
],
"metricValues": [
{
"value": "85"
}
]
},
{
"metricValues": [
{
"value": "77"
}
],
"dimensionValues": [
{
"value": "iOS 捷徑自動化應用場景 — 自動轉發簡訊與自動建立提醒待辦事項 | ZhgChgLi"
}
]
},
{
"metricValues": [
{
"value": "51"
}
],
"dimensionValues": [
{
"value": "遊記 9/11 名古屋一日快閃自由行 | ZhgChgLi"
}
]
},
{
"metricValues": [
{
"value": "42"
}
],
"dimensionValues": [
{
"value": "iOS 隱私與便利的前世今生 | ZhgChgLi"
}
]
},
{
"dimensionValues": [
{
"value": "iOS Vision framework x WWDC 24 Discover Swift enhancements in the Vision framework Session | ZhgChgLi"
}
],
"metricValues": [
{
"value": "34"
}
]
},
{
"dimensionValues": [
{
"value": "iOS ≥ 18 NSAttributedString attributes Range 合併的一個行為改變 | ZhgChgLi"
}
],
"metricValues": [
{
"value": "30"
}
]
},
{
"metricValues": [
{
"value": "30"
}
],
"dimensionValues": [
{
"value": "手工打造 HTML 解析器的那些事 | ZhgChgLi"
}
]
}
],
"metricHeaders": [
{
"type": "TYPE_INTEGER",
"name": "screenPageViews"
}
],
"totals": [
{
"dimensionValues": [
{
"value": "RESERVED_TOTAL"
}
],
"metricValues": [
{
"value": "1229"
}
]
}
]
}
- Google Apps Script 請求 GA 數據成功!🎉🎉🎉
Step 3. 組合起來!Google Apps Script + GA4 + Telegram Bot
依照上篇文章「 10 分鐘快速移轉 Line Notify 到 Telegram Bot 通知 」建立你的 Telegram Bot 取得 Bot Token & 想要傳送到的 Channel Chat ID 。
const telegramToken = "XXXX" // 帶入你的 Telegram Bot Token
//
function execute() {
const screenPageViewsReport = fetchScreenPageViews("318495208");
//
const total = parseInt(screenPageViewsReport.totals[0].metricValues[0].value);
var message = "總瀏覽數:"+total.toLocaleString()+"\n";
screenPageViewsReport.rows.forEach(function(element, index) {
const pageTitle = element.dimensionValues[0].value;
const value = parseInt(element.metricValues[0].value);
message += "[Top "+(index + 1)+"] "+pageTitle+": "+value.toLocaleString()+"\n";
});
sendNotifyMessage(message, -xxxx); // 帶入你的 Channel Chat ID
}
// 發送訊息到 Telegram 指定 Channel Chat ID
function sendNotifyMessage(message, chatId) {
var url = "https://api.telegram.org/bot"+telegramToken+"/sendMessage";
const payload = {
"chat_id": chatId,
"text": message,
"disable_web_page_preview": true
}
const options = {
'method': 'post',
'contentType': 'application/json',
'muteHttpExceptions': true,
'payload': JSON.stringify(payload)
};
const response = UrlFetchApp.fetch(url, options);
const data = JSON.parse(response.getContentText());
if (data["ok"] == undefined || data["ok"] != true) {
if (data["error_code"] != undefined && data["error_code"] == 429) {
Utilities.sleep(1000);
sendNotifyMessage(message, chatId);
}
}
}
function fetchScreenPageViews(propertyId, startDate = "7daysAgo", endDate = "yesterday") {
const screenPageViewsMetric = AnalyticsData.newMetric();
screenPageViewsMetric.name = "screenPageViews";
const dateRange = AnalyticsData.newDateRange();
dateRange.startDate = startDate;
dateRange.endDate = endDate;
const pageTitleDimension = AnalyticsData.newDimension();
pageTitleDimension.name = "pageTitle";
const request = AnalyticsData.newRunReportRequest();
request.dimensions = [pageTitleDimension];
request.metrics = [screenPageViewsMetric];
request.dateRanges = dateRange;
request.limit = 10;
request.metricAggregations = "TOTAL";
return AnalyticsData.Properties.runReport(request, "properties/" + propertyId);
}
程式碼解析:
//...
// 依照報表回傳的 json 找到 total 位置,parseInt 將字串轉成 INT 數字格式
// .toLocaleString() -> 格式化數字,123456 -> 123,456
const total = parseInt(screenPageViewsReport.totals[0].metricValues[0].value);
var message = "總瀏覽數:"+total.toLocaleString()+"\n";
// 依照報表回傳的 json 遍歷資料,組合成訊息
screenPageViewsReport.rows.forEach(function(element, index) {
const pageTitle = element.dimensionValues[0].value;
const value = parseInt(element.metricValues[0].value);
message += "[Top "+(index + 1)+"] "+pageTitle+": "+value.toLocaleString()+"\n";
});
//...
執行:點擊上方「執行」或「偵錯」並確定方法名稱是選擇「 execute 」:


- 成功!🎉🎉🎉
設定排程定時自動執行
最後一步是我們希望報表機器人能定時自動執行,從左側選單前往「觸發條件」:

- 選擇右下角「新增觸發條件」按鈕

- 選擇鐔要執行的功能:選擇 「
execute」方法名稱 - 選擇執行的部署作業:選擇「
上端」 - 選取活動來源:選擇「
時間驅動」 - 選取時間型觸發條件類型:選擇你想要的觸發頻率
- 選取時段:選擇你想要每日自動觸發的時間
- 如果執行失敗…通知信件的頻率設定
- 儲存
完成!這樣時間到就會自動執行囉。 🎉🎉🎉
延伸作業
其他數據如 新使用者數、來源媒介等,同樣使用前面程式碼就能達成,這邊就不在重複贅述,就當成給大家的回家作業囉。



留言 · Comments