惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

小众软件
小众软件
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
WordPress大学
WordPress大学
月光博客
月光博客
Hugging Face - Blog
Hugging Face - Blog
博客园 - 聂微东
博客园 - 【当耐特】
博客园_首页
The Cloudflare Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Apple Machine Learning Research
Apple Machine Learning Research
Last Week in AI
Last Week in AI
酷 壳 – CoolShell
酷 壳 – CoolShell
大猫的无限游戏
大猫的无限游戏
雷峰网
雷峰网
量子位
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
Tailwind CSS Blog
IT之家
IT之家
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
GbyAI
GbyAI
V
Visual Studio Blog
F
Fortinet All Blogs
Martin Fowler
Martin Fowler

膨胀自留地

使用CloudFlare标记管理功能优雅的使用谷歌分析 四天轻松版北京旅游攻略 Adsense税务居住地证明申请教程:如何申请中国税收居民身份证明以及Google Adsense更新新加坡税务信息教程 常见的 VPS 优化措施 HTML实现table表格移动端自动转为卡片样式 个人网站接入 Google 登录 如何从 GitHub 永久删除泄露的 .env 文件 Cloudflare设置www的域名跳转到不带www的域名 顶级iOS神器!全面解开App Store限制,AssPP Pro保姆级教程 BroadcastChannel将你的 Telegram Channel 转为微博客 Medama开源轻量级网站统计(分析)系统 白嫖一个网站监控面板:uptime-kuma 部署TraffMonetizer利用闲置VPS挂机赚钱 Counterscale-使用CloudflareWorkers部署的免费网站数据统计工具,界面类似umami 封装一个最简单的Axios,避免过度封装! 如何使用Cloudflare Email Routing创建域名邮箱免费发送邮件 使用Cron定时更新Hosts解决Gihub无法访问问题 容器化MariaDB/Mysql实现定时备份 JetBrains全家桶许可证服务器怎么找,JetBrains激活教程 图片加速接口:缓存图片,加速访问,解决防盗链 MySQL模糊查询再也不用like+%了,全文索引介绍及使用简介 为什么这么多人推荐你办理流量卡?流量卡怎么赚钱?怎么避坑? etcd入门之在Centos上安装部署 Grafana在linux下安装和基本使用入门 Prometheus介绍、安装和基本功能快速入门 无需加速器,油猴插件解锁xbox云游戏 阿里云盘自动每日签到,无需部署,无需服务器 自定义VSCode终端主题样式 一行 CSS 代码实现响应式布局 – 使用 Grid 实现的响应式布局 加不加「/」?Nginx location 路径与 proxy_pass 的规律
借助Cloudflare Worker实现Google Analytics反代加速,规避广...
2024-02-22 · via 膨胀自留地

#编程技术 2024-02-22 15:47:00 | 全文 1847 字,阅读约需 4 分钟 | 加载中... 次浏览

👋 相关阅读


自从 CNZZ 砍掉了免费服务,百度统计免费版除基础数据以外的功能也关闭了,51.la 刚重构的 v6 突然承接到这两家的「难民」,也饱受巨大的流量冲击。于是尝试过自建统计服务 Umami 来统计博客流量数据(使用 Vercel 部署 Umami,从零开始搭建一个免费的个人博客数据统计),但是,自己搭建的服务总归不如大厂的公共服务来的稳定,而且自建还需要占用资源,于是又开始研究 Google Analytics。

Google Analytics 是一款优秀的流量分析服务,集成方便,使用简单。

但是,众所周知,国内网络环境使用 Google Analytics 页面访问速度肉眼可见的变慢,同时还面临着各种广告屏蔽插件拦截,所以 Google Analytics 是一个很大的优化点。

本文就记录一下借助 Cloudflare Worker 实现 Google Analytics 反代加速的过程,顺便还能更换采集路由规避广告屏蔽插件的拦截。

强调一下,反代 Google Analytics 目前的问题是,Measurement Protocol 现在不能手动设置来源 IP,这意味着无法获取访客地理位置、运营商等信息. 不过如果在 Workers 使用如 lib-qqwry 去查询 IP 库后修改上报内容,或许不失为一种权宜之策。

1、访问加速

Cloudflare 基础使用就不赘述了,在 Dashboard 里找到 Workers 开通就好. 创建服务那里,「启动器」选择初始模板,随便选即可。

新建的 Worker,代码如下,保存后部署。

addEventListener('fetch', (event) => {
    // 这里可以加 filter
    return event.respondWith(handleRequest(event));
  });
  
  // worker应用的路由地址,末尾不加 '/',比如:ga.wangtwothree.workers.dev
  const DOMAIN = 'xxx.workers.dev';
  // 插入的js地址文件名,可自定义
  const JS_FILE = '自定义ga.js'
  // 响应上报的接口路径,可自定义,规避广告屏蔽插件拦截
  const COLLECT_PATH = 'collect_path';
  // 原 gtag 地址,将G-XXX改为你的id
  const JS_URL = 'https://www.googletagmanager.com/gtag/js?id=G-XXX'
  
  // 下面不需要改
  const G_DOMAIN = 'google-analytics.com';
  const G_COLLECT_PATH = 'g\/collect';
  
  async function handleRequest(event) {
    const url = event.request.url;
    if (url.match(`${DOMAIN}/${JS_FILE}`)) {
      const requestJs = await (await fetch(JS_URL)).text();
      const jsText = requestJs.replaceAll('\"www\"', '\"\"').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}`, `www.${G_DOMAIN}/${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);
  }

然后按照 Google Analytics 里的说明安装统计代码,只是把 JS 地址改成上面配置的地址。安装后查看下页面,在 F12 Devtools 里看下有没有 POST 到 COLLECT_PATH 的成功 204 响应。成功的话,就可以在 Google Analytics 的实时页面看到统计了。

页面插入对应 js 示例

<!-- Google tag (gtag.js) -->
<script async src="https://xxx.workers.dev/自定义ga.js"></script> // 对应worker里的DOMAIN 和 JS_FILE,需要保持一致
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'G-XXX'); // 将G-XXX改为你的id
</script>

接下来的可选操作是将自己的域名解析到 Worker.

如果域名是 NS 接入 Cloudflare 那就很简单了,假设域名是 example.com 想用 subdomain.example.com,若这个二级域名已经使用且经过 Cloudflare(开启了橙色云朵)即可下一步,没有的话需要设置这个二级域名为任意记录,并开启橙色云朵. 然后在 Workers 里「触发器-添加路由」添加 subdomain.example.com/* 即可.

如果域名是之前用 Partners 方法用 CNAME 接入的(现在 Partners 已经不能新增接入了),可以在 Partners 那边给二级域名开启橙色云朵,然后同样进行第二步操作. 其实还有一个方法,Cloudflare Pages 支持 CNAME 接入,可以创建一个空白 Pages,CNAME 到 yourpages.pages.dev,成功之后这个二级域名即接入了 Cloudflare 网络,那么还如前文所述一样操作即可.

当然,改完后不要忘记把 Workers 代码里的 DOMAIN 变量修改过来,还要更新页面安装的 JS 地址.

相比仅代理上报接口(Measurement Protocol),代理 gtag.js 的好处是不用自己维护这个文件的更新,且不用修改其他的代码(如使用 Google Analytics 做了自定义事件上报等等),甚至(或许可以,但未测试)支持 Tag Manager,功能更丰富. 当然缺点也显而易见,gtag.js 也会消耗一次请求,访问量较大时免费的请求数可能会吃紧。

2、文件瘦身

通过性能分析,发现 gtag.js 文件过大,影响页面加载速度。

虽然使用了 Cloudfare 代理,但是 Google Analytics 原始的 js 文件为 80KB 左右。

搜索一番,找到一个瘦身版 Google Analytics:https://minimalanalytics.com/

Minimal Google Analytics Snippet A simple snippet for tracking page views on your website without having to add external libraries. Also works for single page applications made with the likes of react and vue.js.

Before Google Tag Manager + Analytics = 73kB

After Snippet = 1.5kB

使用瘦身版插入的 js 片断,只有 1.5kb 大小。

唯一的缺点就是只有基本统计功能,这对于我来说足够了。

将页面插入的 js 代码,更换为下述代码,需要将其中的 xxx.com/collect_path 改为第一步定义的 DOMAIN 和 COLLECT_PATH 变量值,并且将 G-XXXXXXXX 替换为你自己的 ID。

<script>
enScroll=!1,enFdl=!1,extCurrent=void 0,filename=void 0,targetText=void 0,splitOrigin=void 0;const lStor=localStorage,sStor=sessionStorage,doc=document,docEl=document.documentElement,docBody=document.body,docLoc=document.location,w=window,s=screen,nav=navigator||{},extensions=["pdf","xls","xlsx","doc","docx","txt","rtf","csv","exe","key","pps","ppt","pptx","7z","pkg","rar","gz","zip","avi","mov","mp4","mpe","mpeg","wmv","mid","midi","mp3","wav","wma"];function a(e,t,n,o){const j="G-XXXXXXXX",r=()=>Math.floor(Math.random()*1e9)+1,c=()=>Math.floor(Date.now()/1e3),F=()=>(sStor._p||(sStor._p=r()),sStor._p),E=()=>r()+"."+c(),_=()=>(lStor.cid_v4||(lStor.cid_v4=E()),lStor.cid_v4),m=lStor.getItem("cid_v4"),v=()=>m?void 0:enScroll==!0?void 0:"1",p=()=>(sStor.sid||(sStor.sid=c()),sStor.sid),O=()=>{if(!sStor._ss)return sStor._ss="1",sStor._ss;if(sStor.getItem("_ss")=="1")return void 0},a="1",g=()=>{if(sStor.sct)if(enScroll==!0)return sStor.sct;else x=+sStor.getItem("sct")+ +a,sStor.sct=x;else sStor.sct=a;return sStor.sct},i=docLoc.search,b=new URLSearchParams(i),h=["q","s","search","query","keyword"],y=h.some(e=>i.includes("&"+e+"=")||i.includes("?"+e+"=")),u=()=>y==!0?"view_search_results":enScroll==!0?"scroll":enFdl==!0?"file_download":"page_view",f=()=>enScroll==!0?"90":void 0,C=()=>{if(u()=="view_search_results"){for(let e of b)if(h.includes(e[0]))return e[1]}else return void 0},d=encodeURIComponent,k=e=>{let t=[];for(let n in e)e.hasOwnProperty(n)&&e[n]!==void 0&&t.push(d(n)+"="+d(e[n]));return t.join("&")},A=!1,S="https://xxx.com/collect_path",M=k({v:"2",tid:j,_p:F(),sr:(s.width*w.devicePixelRatio+"x"+s.height*w.devicePixelRatio).toString(),ul:(nav.language||void 0).toLowerCase(),cid:_(),_fv:v(),_s:"1",dl:docLoc.origin+docLoc.pathname+i,dt:doc.title||void 0,dr:doc.referrer||void 0,sid:p(),sct:g(),seg:"1",en:u(),"epn.percent_scrolled":f(),"ep.search_term":C(),"ep.file_extension":e||void 0,"ep.file_name":t||void 0,"ep.link_text":n||void 0,"ep.link_url":o||void 0,_ss:O(),_dbg:A?1:void 0}),l=S+"?"+M;if(nav.sendBeacon)nav.sendBeacon(l);else{let e=new XMLHttpRequest;e.open("POST",l,!0)}}a();function sPr(){return(docEl.scrollTop||docBody.scrollTop)/((docEl.scrollHeight||docBody.scrollHeight)-docEl.clientHeight)*100}doc.addEventListener("scroll",sEv,{passive:!0});function sEv(){const e=sPr();if(e<90)return;enScroll=!0,a(),doc.removeEventListener("scroll",sEv,{passive:!0}),enScroll=!1}document.addEventListener("DOMContentLoaded",function(){let e=document.getElementsByTagName("a");for(let t=0;t<e.length;t++)if(e[t].getAttribute("href")!=null){const n=e[t].getAttribute("href"),s=n.substring(n.lastIndexOf("/")+1),o=s.split(".").pop();(e[t].hasAttribute("download")||extensions.includes(o))&&e[t].addEventListener("click",fDl,{passive:!0})}});function fDl(e){enFdl=!0;const t=e.currentTarget.getAttribute("href"),n=t.substring(t.lastIndexOf("/")+1),s=n.split(".").pop(),o=n.replace("."+s,""),i=e.currentTarget.text,r=t.replace(docLoc.origin,"");a(s,o,i,r),enFdl=!1}
</script>

VIA

加速Google Analytics | 流动 https://liudon.com/posts/optimize-google-analytics/

Cloudflare Workers 反代 Google Analytics · xiaopc https://xiaopc.org/2022/04/04/%E6%97%A7%E6%96%87%E6%9B%B4%E6%96%B0-cloudflare-workers-%E5%8F%8D%E4%BB%A3-google-analytics/

Minimal Google Analytics Snippet | Minimal Analytics https://minimalanalytics.com/


×