Skip to content

Instantly share code, notes, and snippets.

@xiaopc
Last active October 25, 2023 14:50
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save xiaopc/0602f06ca465d76bd9efd3dda9393738 to your computer and use it in GitHub Desktop.
Save xiaopc/0602f06ca465d76bd9efd3dda9393738 to your computer and use it in GitHub Desktop.
Google Analytics 4 Proxy with Cloudflare Workers
// 2023.4.23 更新,修复 gtag.js 加了个回车导致失效的问题
// 2023.3.2 更新,修复上报到 region*.google-analytics.com 未被代理的问题
addEventListener('fetch', (event) => {
// 这里可以加 filter
return event.respondWith(handleRequest(event));
});
// worker 应用的路由地址,末尾不加 '/'
const DOMAIN = 'https://example.workers.dev/routerpath';
// 响应上报的接口路径,可自定义
const COLLECT_PATH = 'any-collect-dest-path';
// 原 gtag 地址
const JS_URL = 'https://www.googletagmanager.com/gtag/js?id=G-**********'
// 下面不需要改
const G_DOMAIN = /https\:\/\/[a-z"+\s]*\.google-analytics\.com/g;
const G_COLLECT_PATH = 'g\/collect';
async function handleRequest(event) {
const url = event.request.url;
if (url.match(`${DOMAIN}/a.js`)) {
const requestJs = await (await fetch(JS_URL)).text();
const jsText = requestJs.replaceAll(G_DOMAIN, DOMAIN).replaceAll(G_COLLECT_PATH, COLLECT_PATH);
return new Response(jsText, {
status: 200,
statusText: 'OK',
headers: {
'Content-Type': 'application/javascript',
},
});
} else if (url.match(`${DOMAIN}/${COLLECT_PATH}`)) {
const newReq = await readRequest(event.request);
event.waitUntil(fetch(newReq));
}
return new Response(null, {
status: 204,
statusText: 'No Content',
});
}
async function readRequest(request) {
const { url, headers } = request;
const body = await request.text();
const ga_url = url.replace(`${DOMAIN}/${COLLECT_PATH}`, `https://www.google-analytics.com/${G_COLLECT_PATH}`);
const nq = {
method: 'POST',
headers: {
Host: 'www.google-analytics.com',
Origin: headers.get('origin'),
'Cache-Control': 'max-age=0',
'User-Agent': headers.get('user-agent'),
Accept: headers.get('accept'),
'Accept-Language': headers.get('accept-language'),
'Content-Type': headers.get('content-type') || 'text/plain',
Referer: headers.get('referer'),
},
body: body,
};
return new Request(ga_url, nq);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment