简单 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 查询资料
-
建立新专案,命名专案名称
-
点击「服务」->「+」新增服务
-
选择「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