GA4 自动数据通知机器人|3 步骤用 Google Apps Script 串接 Telegram Bot
针对希望即时掌握网站数据的使用者,教你用 3 步骤打造免费 GA4 自动通知机器人,结合 Google Apps Script 与 Telegram Bot,定时推送近 7 天流量与热门页面,减少人工查询时间,提升数据监控效率。
Click here to view the English version of this article.
點擊這裡查看本文章正體中文版本。
基于 SEO 考量,本文标题与描述经 AI 调整,原始版本请参考内文。
简单 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 会使用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
"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 查询程式码并组合:
将前面步骤产生的报表查询数据参数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
"dimensions": [
{
"name": "pageTitle"
}
],
"metrics": [
{
"name": "screenPageViews"
}
],
"dateRanges": [
{
"startDate": "7daysAgo",
"endDate": "yesterday"
}
],
"limit": "10",
"metricAggregations": [
"TOTAL"
]
}
转换成程式:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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);
}
程式码解析:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// 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())
取得输出结果:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
{
"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
。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
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);
}
程式码解析:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//...
// 依照报表回传的 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
」方法名称选择执行的部署作业:选择「
上端
」选取活动来源:选择「
时间驱动
」选取时间型触发条件类型:选择你想要的触发频率
选取时段:选择你想要每日自动触发的时间
如果执行失败…通知信件的频率设定
储存
完成!这样时间到就会自动执行啰。 🎉🎉🎉
延伸作业
其他数据如 新使用者数、来源媒介等,同样使用前面程式码就能达成,这边就不在重复赘述,就当成给大家的回家作业啰。
有任何问题及指教欢迎 与我联络 。
本文首次发表于 Medium (点击查看原始版本),由 ZMediumToMarkdown 提供自动转换与同步技术。