ZhgChg.Li

GA4 自动数据通知机器人|3 步骤用 Google Apps Script 串接 Telegram Bot

针对希望即时掌握网站数据的使用者,教你用 3 步骤打造免费 GA4 自动通知机器人,结合 Google Apps Script 与 Telegram Bot,定时推送近 7 天流量与热门页面,减少人工查询时间,提升数据监控效率。

GA4 自动数据通知机器人|3 步骤用 Google Apps Script 串接 Telegram Bot
本文使用 AI 翻译,如有不妥敬请告知。"

简单 3 步骤 — 打造免费 GA4 自动数据通知机器人

使用 Google Apps Script 完成 RPA,自行串接 GA4 + Telegram Bot 数据通知机器人

Photo by BoliviaInteligente

Photo by BoliviaInteligente

前言

大约从 2020 年开始就自己在摸索使用手边工具实现 RPA,从一开始只是为了自动化个人例行任务,到后来工作也加入了规模更大型的组织,时常会遇到跨团队或仰赖人与人的任务、甚至是重复性任务,才发现 RPA 自动化的效益所在。

举例来说:某个重复任务每个月会发生 10 次,每次需花费 30 分钟处理,有 60 人会遇到,每年团队等于消耗 3,600 小时在这上面,如果能投资 100 小时开发成自动化,后续解放出来的时间,就能投入在更有价值的工作上;实际等于 3,600 浪费的工时+3,600 更值得投资的产出。

详细可参考我之前的文章:

其他做过的 RPA:

从后台数据看之前蛮多文章有被 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 免费限制、详细使用、部署、功能介绍本篇不会再多介绍,请参考 之前文章

  • Telegram Bot 创建、使用本篇也不会再多介绍,同样请参考 之前文章

成果

先上最终效果,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 官方提供的工具产生我们需要的查询数据报表参数:

  1. Select Property: 记下你的 property 编号 property 编号稍后撰写 Google Apps Script 会使用。

  2. start date, end date: 报表开始~结束的日期范围,可使用 YYYY-MM-DDyesterday , today , NdaysAgo 魔术变数。

  3. metrics: 选择你想要查询的指标

  4. dimensions: 选择你想要查询的维度

  5. metric aggregations: 数据合并计算规则

这边以我的场景为例:

  1. property 编号: 318495208

  2. start_date: 7daysAgo

  3. end_date: yesterday 因 GA 数据报表会延迟,查询前一天~七天最准确。

  4. 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 」:

  • 成功!🎉🎉🎉

设定排程定时自动执行

最后一步是我们希望报表机器人能定时自动执行,从左侧选单前往「触发条件」:

  • 选择右下角「新增触发条件」按钮

  1. 选择镡要执行的功能:选择 「 execute 」方法名称

  2. 选择执行的部署作业:选择「 上端

  3. 选取活动来源:选择「 时间驱动

  4. 选取时间型触发条件类型:选择你想要的触发频率

  5. 选取时段:选择你想要每日自动触发的时间

  6. 如果执行失败…通知信件的频率设定

  7. 储存

完成!这样时间到就会自动执行啰。 🎉🎉🎉

延伸作业

其他数据如 新使用者数、来源媒介等,同样使用前面程式码就能达成,这边就不在重复赘述,就当成给大家的回家作业啰。

在 GitHub 上补充修正
编辑这篇文章
本文首次发表于 Medium
点此查看原文
分享这篇文章
复制链接 · 分享到社群
ZhgChgLi
作者

ZhgChgLi

An iOS, web, and automation developer from Taiwan 🇹🇼 who also loves sharing, traveling, and writing.

留言 · Comments