可搜索,可注册,可登录,致敬逗比大佬!尽在救援版逗比根据地 dbgjd.com
投稿文章 | 广告合作 | Telegram 群组 / 公告频道 / 使用教程

Google_Analytics 异步化方案 via Openresty

News mlone11978 79℃ 0评论

网站配置 Google_Analytics 的常见方式,是在网站前端引用 Google_Analytics 的 tracker_code 和 analytics.js 用以统计用户行为。而这种方式会成为访问缓慢的原因:访客对 analytics.js 的下载请求会拖慢页面加载完毕,并需要向 Google 发送访客数据,用户行为的统计提交全部在客户端由客户完成,加重了客户端的负担。并且也有 analytics.js 会被 ublock 等屏蔽掉而导致无法收集用户行为的弊端。

如果将 Google_Analytics 的统计工作从前端转移到后端完成,就可以有效避免上述问题。

在 2016 年时就已经出现了这种方式(via),该文章使用 ngx_http_userid_module 实现 userid 的生成。而基于本文所述,使用 Openresty 的好处在于 id 的生成方案由网站所有者决定,且能够享受 lua code 带来的便(kuai)利(gan)。

基本思路

通过 Nginx proxy_pass 就能实现该目的,根据用户访问的 location,按照 Mea­sure­ment Pro­to­col 向 https://www.google-analytics.com/ 提交数据,就能将统计工作放在后端完成:

    location @google_analytics {         proxy_pass  https://www.google-analytics.com/collect?v=1&t=pageview&tid=UA-111111111-1&cid=$cookie_cid&uip=$remote_addr&dh=$host&dp=$uri&dr=$http_referer&z=$msec;     } 

配置 Nginx

在上面已提出了基本思路,完整的 Nginx 实现应该是这样的框架:

    location / {         ...          post_action @google_analytics;     }      location @google_analytics {         internal;         resolver                    8.8.8.8 [2001:4860:4860::8888];         proxy_http_version          1.1;         proxy_method                GET;         proxy_set_header            User-Agent $http_user_agent;         proxy_pass_request_headers  off;         proxy_pass_request_body     off;         proxy_pass                  https://www.google-analytics.com/collect?v=1&t=pageview&tid=UA-111111111-1&cid=$cookie_cid&uip=$remote_addr&dh=$host&dp=$uri&dr=$http_referer&z=$msec;     } 

这个时候,以上配置中有两个需要注意的地方:

  • tid=UA-111111111-1:自行修改为 Google_Analytics 分配给你网站的
  • cid=$cookie_cid:这个是用户标识,按照标准应该为 uuid 格式,为每位用户分配的标识应该独一无二。

其中,这里的变量 $cookie_cid 通过 Openresty 实现,是作为分配给每次访问的客户 id,生成方式会在下文进行说明。

配置 Openresty

要通过 Openresty 生成 uuid 分配给访客,可以通过 $remote_addr 生成,这是基于 client ip 生成的客户标识:

    local str_random = ngx.var.binary_remote_addr     local str_md5 = ngx.md5(str_random)     local str_sub = string.sub(str_md5, 1, 8) .. "-" .. string.sub(str_md5, 9, 12) .. "-" .. string.sub(str_md5, 13, 16) .. "-" .. string.sub(str_md5, 17, 20) .. "-" .. string.sub(str_md5, 21, 32)     cid = str_sub 

或者也可以通过访问时间生成,将 str_random 换一种定义方式,其中 ngx.time() 函数提供秒级的当前 unix 时间戳:

    ngx.update_time()     local str_random = ngx.time() 

然后需要做的就是把 Openresty 中的这个变量 $cid 传递到 Nginx,即在 location 中所需要的 $cookie_cid 变量。使用 cookie 传递是最简单的方法:

    local cookie_cid = nil     if (ngx.var.cookie_cid == nil) then         cid = userid.generate()     end      ngx.header["Set-Cookie"] = {"cid=" .. cookie_cid} 

然后 Nginx 中 proxy_pass 时就会读取 cookie 中的 cid 变量(即 $cookie_cid 变量),以此作为访客标识发送至 Google_Analytics 服务。

不发送的行为

“不发送的行为”包括并不限于 spider 和 request_file_not_exist 两种常见情况,爬虫和 404 我们是不会想提交给 Google_Analytics 服务的。可以加入是否执行 post_action 的判断。

通过 Openresty 判断筛选不希望行为统计被提交的情况:

    -- 这里把 ".../" 替换成你的网站文件的绝对路径     local request_filename = ".../" .. ngx.var.uri     -- 判断请求文件是否存在     local file = io.open(request_filename, "r")      if (file and ngx.re.find(ngx.var.http_user_agent, "qihoobot|Baidu", "jo") == nil) then         ngx.header["Set-Cookie"] = {"stats=" .. "1"}     end 

然后在 Nginx 中进行判断,仅满足 $cookie_stats = 1 的访问提交给统计服务:

    location / {         ...          if ($cookie_stats = "1") {             post_action @google_analytics;         }     } 

Lib 实现

本文仅提供最基本的思路介绍,完整的实现方案我已封装为 lib 并发布于 Github

本站已使用本文所述方案,效果可参见本站 cookie。

Reference

感谢以下作者提供的思路:

  • https://darknode.in/network/nginx-google-analytics/
  • https://eason-yang.com/2016/11/04/google-analytics-via-nginx/
  • https://blog.nfz.moe/archives/google-analytics-optimize.html

转载请注明:逗比根据地 » Google_Analytics 异步化方案 via Openresty

喜欢 (0)
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址