代理 Google Analytics
在使用 Google Analytics 的时候,只需加上这么一段 js 就能开始统计数据了:
<script async src="https://www.googletagmanager.com/gtag/js?id=<YOUR_GAID>"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '<YOUR_GAID>');
</script>
但这会带来如下几个问题:
- 提供的网址在大陆地区不稳定
- 容易被广告插件拦截从而影响准确性
之前我使用 配合 Measurement Protocol 优化 Google Analytics 的方式来解决以上问题,同时支持了 SPA 也能自由控制功能与开销之前的取舍,就是麻烦,不能开箱即用,还有后期维护问题。
后来,在查看文档的时候,发现官方已经升级到了 v4 的版本 ,即 Google Analytics v4 + Measurement Protocol v2 的组合,并且默认就能自动追踪 SPA 的路由变化,不像之前需要额外引入插件使用,真的能开箱即用了。剩下就是怎么解决上面这些问题了,思路就是使用自定义的地址来替换并代理官方地址,目前我找到这些方案:
- Google Tag Manager 支持在自己的服务器上搭建统计服务。缺点在于只能使用 Google Cloud Platform 的服务器
- save-analytics-from-content-blockers 劫持 gtag 的 js 文件,修改其中用于收集数据的 API 地址,并对这些地址做混淆。使用的时候,只需修改官方 js 代码中 gtag 的引用路径即可。
第二种很好用很全面,就是这个得用容器跑,而我只是想简单的使用统计服务就可以了,于是稍微整合下两种方法:
在第一种方法中,文档说到,可以使用参数 transport_url
来定义 "收集API" 的域名,解决了稳定性的问题,但仍然会被拦截,因为这个参数无法修改默认路径(/g/collect
),所以像方法二那样劫持 gtag,替换默认的 /g/collect
为其他就可以了。
- Vercel Function :
const Fastify = require("fastify");
const reply = require("fastify-reply-from");
const axios = require("axios").default;
const app = Fastify();
app.register(reply);
app.get("/gtag-js", async (request, reply) => {
const { query } = request;
const response = await axios.get("https://www.googletagmanager.com/gtag/js", {
params: query,
});
reply.headers({
"content-type": "application/javascript; charset=UTF-8",
});
reply.send(response.data.replace(/"\/g\/collect"/g, `"/g-collect"`));
});
app.all("/g-collect", function (request, reply) {
reply.from(`https://www.google-analytics.com/g/collect`);
});
module.exports = async function (req, res) {
await app.ready();
app.server.emit("request", req, res);
};
- Client JS:
<script async src="https://<YOUT_DOMAIN>/gtag-js?id=<YOUR_GAID>"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '<YOUR_GAID>', {
transport_url: 'https://<YOUT_DOMAIN>'
});
</script>
使用 Measurement Protocol v2 的情况下不能像 v1 那样主动指定访客的地理位置。