网站配置 Google Analytics 的常见方式是在网站前端引用 analytics.js 脚本,从前端利用 javascript 进行统计,这种方案的缺点是:
- 客户端到 Google Analytics 之间的网络问题,包括 analytics.js 脚本加载缓慢、向 Google Analytics 发送信息速度缓慢乃至失败等问题。
- 客户端屏蔽 Google Analytics 的相关问题,包括常见的 adblock 扩展等自带的屏蔽列表,利用 userscript 进行屏蔽等方式,这些客户端的手段都会导致统计的偏差问题。
如果将 Google Analytics 的统计工作从前端转移到后端完成,就可以有效避免上述问题,在阅读了相关参考资料后我发现直接使用 Nginx 自身的功能就可以完成这一工作,于是有了本文。
此方案的优点是:
- 只需考虑服务器到 Google Analytics 的速度,不影响客户端的体验。
- 统计数据真实准确,不受干扰与屏蔽。
- 配置简单方便,使用 Nginx 自身的功能即可完成。
配置说明
Nginx 自带的 userid 模块可以用于标记各个用户,而 post_action 配置项可以在 Nginx 收到的请求处理完成后向某处发送一个异步的 Get 请求,这个请求会附带原始请求的 referer 与user-agent,利用这两个功能的这一个,我们可以配置 Nginx 在页面访问后发送相关信息到 Google Analytics 中,其具体配置如下:
1 | userid on; |
userid模块将会在用户访问时检查 cookies 中是否有 cid 项,如果没有 cid 项,则会在返回的 header 中加入 set-cookies 头标记这个用户,并将 $uid_set 变量设定为 cid=XXXXXX 这一形式,将 $uid_got 变量设定为空。如果有 cid 项,则将 $uid_got 变量设定为 cid=XXXXXX 这一形式,将 $uid_set 变量设定为空。于是在 @tracker 部分,上述变量会将 $uid_set$uid_got 填充为cid=XXXXXX。
实际向 Google Analytics 提交数据时,tid为跟踪 ID,即类似 UA-123456-1 的用于区别是要向哪个 Google Analytics(分析)媒体资源发送数据的参数,可以从 Google Analytics 获得;cid即客户端 ID,以 cookies 的形式用于区分和追踪用户,这里通过 userid 模块完成;t、dh、dp参数用于标记事件类型,访问的网站与访问的路径;uip参数即用户的 IP 地址,用于追踪用户所处地区等信息;dr参数即用户的 referer,用于追踪用户的来源信息;z参数没有实际意义,仅仅用于附加一个时间戳以防止向 Google Analytics 提交数据时,这个请求被缓存。
调试方法
如果希望提交更多数据,并对这一过程进行调试,最简单的方法是首先将配置文件中的 proxy_pass 部分网址从 https://ssl.google-analytics.com/ 修改为 http://127.0.0.1:9999 ,再在服务器上使用nc 监听服务器上的 9999 端口:
1 | nc -k -l 0.0.0.0 9999 |
从本机访问该网站网站,就能从 nc 上看到本来将被提交到 Google Analytics 上的信息了,如:
1 | GET /collect?v=1&tid=UA-XXXXXX-Y&cid=XXXXXX&t=pageview&dh=example.com&dp=/index.html&uip=123.123.123.123&dr=https://google.com&z=1448000000.000 HTTP/1.0 |
随后通过 curl 向 Google Analytics 的调试服务器手动提交信息:
1 | curl --user-agent "Mozilla/4.0" "https://www.google-analytics.com/debug/collect?v=1&tid=UA-XXXXXX-Y&cid=XXXXXX&t=pageview&dh=example.com&dp=/index.html&uip=123.123.123.123&dr=https://google.com&z=1448000000.000" |
Google Analytics 的调试服务器会返回关于此次提交的详细信息,包括参数是否有错误、如何修正等,可以通过检查返回信息来确定配置是否正常,提交到此服务器上的数据并不会被记录到 Google Analytics 中。而 Google Analytics 的正常服务器只会返回 HTTP 状态码,难以进行调试。
手动提交上述信息后 Google Analytics 的返回如下:
1 | { |
明显可以看出此处的错误是 tid 参数错误,显然作为例子的 UA-XXXXXX-Y 并不是一个正确的 tid,更换成实际的tid 之后这个错误就被修复了。
DNT功能
用户可以启用 Do Not Track 功能向网站表明自己不希望被追踪,遵守该规则的网站就不会追踪用户的个人信息。
使用如下配置可以在只有用户未启用 DNT 功能时才向 Google Analytics 发送相关信息:
1 | location / { |
尽管如此,受 Nginx 程序本身的限制 userid 模块依旧会用 cookies 对用户进行标记,没有办法通过检测 DNT 头的方式来关闭它,但用户数据并不会被提交到 Google Analytics 上。