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

推荐订阅源

P
Proofpoint News Feed
Martin Fowler
Martin Fowler
The GitHub Blog
The GitHub Blog
B
Blog RSS Feed
U
Unit 42
阮一峰的网络日志
阮一峰的网络日志
量子位
GbyAI
GbyAI
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
云风的 BLOG
云风的 BLOG
小众软件
小众软件
博客园 - 三生石上(FineUI控件)
L
LangChain Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园_首页
IT之家
IT之家
V
Visual Studio Blog
Y
Y Combinator Blog
Blog — PlanetScale
Blog — PlanetScale
宝玉的分享
宝玉的分享
Apple Machine Learning Research
Apple Machine Learning Research
I
InfoQ
D
Docker
V
V2EX

流动

山西之旅 | 流动 博客焕新,记录继续 | 流动 友链 | 流动 博客加速实践 广府古城一日游 我做了一个口播短视频二创工具:VideoRemaker Windows 下 Codex Cli 更新报 Move-Item is denied 错误的解决 Caddy 转发 GOST 报 TLS internal error 问题的排查与解决 对口型视频合成方案对比:Wav2Lip、VideoReTalking 与 MuseTalk 2026 音色克隆方案对比:IndexTTS-2、CosyVoice、GPT-SoVITS、Fish Speech、VoxCPM 部署与实测 AI Agent折腾记(OpenClaw / Hermes Agent) 我的2025年 大连之行 回家收麦 六一儿童节爬长城 Golang database/sql 数据库断线自动重连机制解析 Golang默认Http Client导致的cannot assign requested address错误 清明踏春,爬山看海 购入小牛G400T电动车 北京的三月飞雪 wrenAI本地LLM模型部署 天津一日游 2024年终总结 停止使用staticfile.org服务 使用 ImageMagick 自动添加水印,保护图片版权 如何注册一个.sol域名 奥森公园半日游 昌平42公里骑行绿道打卡 十月一日爬慕田峪长城 当Hugo遇上AVIF,优化图片加载
加速Google Analytics
Liudon · 2023-12-02 · via 流动

起因

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

最近在优化页面访问速度,发现Google Analytics是一个优化点。

优化

1. 访问加速

国内访问Google Analytics很慢,同时还面临着各种广告屏蔽插件拦截。

这里借助Cloudflare Worker实现Google Analytics反代,同时更换采集路由规避广告屏蔽插件的拦截。

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

addEventListener('fetch', (event) => {
    // 这里可以加 filter
    return event.respondWith(handleRequest(event));
  });
  
  // worker 应用的路由地址,末尾不加 '/',改为你的博客地址
  const DOMAIN = 'xxx.com';
  // 博客插入的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);
  }

页面插入对应js

<!-- Google tag (gtag.js) -->
<script async src="https://xxx.com/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>

2. 文件瘦身

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

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

搜索一番,找到一个瘦身版Google Analytics

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变量值。

<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-G9ZDJQN9E2",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>

效果