Google Analytics4(GA4)让我十分反感的几点,一是统计脚本太大了,居然有170多KB,二是国内有时候下载不下来,三是GA可谓是树大招风,早已被几乎所有的广告拦截器拦截了。本文是通过创建一个自己的JS统计脚本来解决上述的几个痛点的,该脚本仅为3KB大小,可以比肩例如Umami的自建方案了。

创建mini GA4

该脚本只是实现了Google Analytics的其中四个主要功能,因而大小骤降了十几倍,因此在Google Analytics开启 增强型衡量功能 后只选中“网页浏览量”,"滚动次数","网站搜索","文件下载次数"。

原始JS为 minimal-analytics-4-min.js

这里提供一个压缩后的JS,复制到网站的head内:

<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-XXXXXXXXXX",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://www.google-analytics.com/g/collect",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>

做一下简单的解释:

设置GA4 Measurement ID: 在代码中的trackingId变量处设置你的GA4 Measurement ID。

const j="G-XXXXXXXXXX"; // 替换成你的GA4 Measurement ID   

配置文件扩展名: 如果需要跟踪其他文件类型,可以修改extensions数组,添加你想要跟踪的文件扩展名。

const 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"];   

脚本通过使用navigator.sendBeaconXMLHttpRequest发送数据到GA4的收集端点https://www.google-analytics.com/g/collect

避免广告拦截器误伤

防止广告拦截器拦截有很多解决方案,比较熟悉的应该是通过Cloudflare Worker反代,这里可参考Plausible的官方文档

本文使用的则是基于Netilify提供的重定向规则,通过设置重定向来隐藏请求。下面以Hugo博客为例进行操作演示

在根目录创建一个_redirects文件,这是一个“无文件扩展名”的纯文本文件,在文件中添加以下行:

/g/collect https://www.google-analytics.com/g/collect 200

然后修改之前的mini GA4文件,将其中的 https://www.google-analytics.com/g/collect 修改为你自己网站的域名,比如本站,则修改为 https://doufoo.com/g/collect

更新netlify.toml 在其中新增下面:

     [build]
       publish = "public"
       command = "hugo --gc --minify -b $URL && cp _redirects public/_redirects"

意思是在构建命令时把根目录下的_redirects文件复制到public目录下。

验证

上面的配置以后,Netlify就可以正确应用你的重定向规则了,如何验证重定向规则是否生效,可以点击你的网站的任意页面,打开控制台查看https://yourdomain.com/g/collect的状态码。如果为204则证明重定向规则生效,如果为404或者其他,请排查重定向操作的问题。

最后再通过谷歌家的PageSpeed Insights验证一下网页的性能

image-20240629144220065

pagespeed报告

可以看到加载非常丝滑。

缺点

使用Netlify固然可以伪装,但是导致了一个问题便是统计的位置信息不准确,重定向规则在Netlify的CDN服务器执行,所有的流量都被记录为该CDN服务器的位置信息。就比如某个中国的用户访问了网页,但是Netlify分发的CDN节点并不在中国,而是在新加坡,那么此条流量就会被GA定位到新加坡。

参考链接