分享互联网知识,建站、IT话题杂谈

Nginx 异步处理Google Analytics

Google Analytics如同其它Google旗下的产品一样,在市面上同类产品中属于非常出色的一个。不过由于众所周知的原因,Google相关服务的流畅性并不理想。虽然流传很多说法表示Google Analytics的域名在国内并没有被墙,在实际优化速度过程中还是有很大影响。用Nginx来进行异步处理Google Analytics请求是一个比较完美的解决方案,下面记录一下供参考。

1 配置及环境说明

  • 搬瓦工洛杉矶CN2 512M
  • Nginx 1.6.2以上*
  • Debian 8.10 64bit
  • WordPress系统
  • LNMP环境 via LNMP一键脚本

2 生成用户信息

	## Begin of user info for nginx google analytics
	userid on;
	userid_name cid;
	userid_domain w61.gubo.org;
	userid_path /;
	userid_expires max;
	if ($http_accept_language ~* '^(.+?),') {
		set $first_language $1;
	}
	## End

这部分的作用主要是生成用户信息,用以传递给Google Analytics统计。具体用法请参考Module ngx_http_userid_module

2.1 获取客户端语言

	if ($http_accept_language ~* '^(.+?),') {
		set $first_language $1;
	}

此部分代码获取客户端的语言,是浏览器设置的偏好语言(Preferred Lanagues)而不是浏览器安装时所选择的语言。

2.2 定义cookies域

	userid_domain w61.gubo.org;

需要注意的是  userid_domain w61.gubo.org; 当中的域名,起到定义cookies的作用,如果设置不当会导致刷新一次页面产生一个新的session(对话),统计数据不准。

3 Tracker Location转发到Google Analytics

	location @tracker {
		resolver 202.45.84.58 ipv6=off;
		internal;
		proxy_method GET;
		proxy_pass https://www.google-analytics.com/collect?v=1&tid=UA-xxxxxxxx-x&$uid_set$uid_got&t=pageview&dh=$host&dp=$request_uri&uip=$remote_addr&dr=$http_referer&ul=$first_language&z=$msec;
		proxy_set_header User-Agent $http_user_agent;
		proxy_pass_request_headers off;
		proxy_pass_request_body off;
	}

这部分代码的通过proxy_pass请求Google Analytics的API从而传递统计数据,各种参数在“2.1 生成用户信息”部分已经定义。

3.1 resolver 指定dns服务器地址

resolver 8.8.8.8 ipv6=off;
  • 如果不加入这行会导致无法解析到Google Analytics域名而不能正确发送数据, 后台也就看不到统计信息
  • 在没有ipv6的机器上需要用 ipv6=off 关闭ipv6的解析,否则Nginx发送数据到ipv6地址不成功,后台也会统计不到数据
  • 某些dns解析到延迟较高的Google Analytics服务器会拖慢Nginx整体速度。调试过程中解析到一个ping延迟400多ms的服务器,页面延迟感觉非常明显,更换resolver后解决。可以使用 dig @8.8.8.8 www.google-analytics.com 来获取解析地址,然后ping对应地址测试延迟。

3.2 特定版本报错"header already sent"

2018/02/06 08:20:07 [alert] 16197#0: *36 header already sent while reading response header from upstream

通过 post_action 转发过来的信息是不会再读取返回信息的,也不会拖慢网页反应速度。但是在Nginx 1.6.2版本(Debian 8默认版本)中会报错,具体错误信息如上。这个报错信息其实是一个bug,网上信息非常少,在初期调试的时候造成很大干扰。只需编译或者用其他方式升级到新版Nginx即可解决。

4 WordPress 统计页面请求

如果不启用生成静态文件的Cache插件,Wordpress所有请求的页面文件实际上都是交给index.php进行处理,所以触发统计的规则要写在  location ~ \.php$  规则里,否则不能有效触发 @tracker 部分的配置

    location ~ \.php$ {
      ... ## 省略正常配置
      ## Google analytics nginx
      set $flag "0";
      if ($request_uri !~* "^/wp-|/feed/$|\.pagespeed\.|robots\.txt|favicon\.ico|replytocom") {
        set $flag "${flag}1";
    }   

    if ($http_user_agent !~* "qihoobot|Baiduspider|Googlebot|Googlebot-Mobile|Googlebot-Image|Mediapartners-Google|Adsbot-Google|Feedfetcher-Google|Yahoo! Slurp|Yahoo! Slurp China|YoudaoBot|Sosospider|Sogou spider|Sogou web spider|MSNBot|ia_archiver|Tomato Bot|YiSou Spider") {
        set $flag "${flag}2";
    }
	
	if ($http_dnt != 1) {
		set $flag "${flag}3";
		}
    
    if ($flag = "0123") {
        post_action @tracker;
    }
      ## End of Google analytics nginx
    }
   ... ## 省略正常配置
   }

5 完整的Nginx文件

下面就是完整的针对Wordpress进行后端异步处理Google Analytics的Nginx配置。如果启用了Wp Super Cache等缓存插件生成了静态文件或者Nginx进行反代,触发@tracker部分所需的代码则添加的位置会有所不同。

点击查看完整Nginx配置文件
高亮部分为本文中为异步处理Google Analytics添加的配置。
[code highlight="9-19,23-32,48-65"] server {

listen 80;
server_name w61.gubo.org ;
index index.html index.htm index.php default.html default.htm default.php;
root /var/www/w61.gubo.org;

## Begin of nginx google analytics
userid on;
userid_name cid;
userid_domain w61.gubo.org;
userid_path /;
userid_expires max;
if ($http_accept_language ~* '^(.+?),') {

set $first_language $1;
}
## End

location @tracker {

resolver 202.45.84.58 ipv6=off;
internal;
proxy_method GET;
proxy_pass https://www.google-analytics.com/collect?v=1&tid=UA-12034187-4&$uid_set$uid_got&t=pageview&dh=$host&dp=$request_uri&uip=$remote_addr&dr=$http_referer&ul=$first_language&z=$msec;
proxy_set_header User-Agent $http_user_agent;
proxy_pass_request_headers off;
proxy_pass_request_body off;
}

location / {

try_files $uri $uri/ /index.php;
}

location ~ \.php$ {

try_files $uri =404;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_pass unix:/var/run/php5-fpm.sock;

## Google analytics nginx
set $flag "0";
if ($request_uri !~* "^/wp-|/feed/$|\.pagespeed\.|robots\.txt|favicon\.ico|replytocom") {
set $flag "${flag}1";
}

if ($http_user_agent !~* "qihoobot|Baiduspider|Googlebot|Googlebot-Mobile|Googlebot-Image|Mediapartners-Google|Adsbot-Google|Feedfetcher-Google|Yahoo! Slurp|Yahoo! Slurp China|YoudaoBot|Sosospider|Sogou spider|Sogou web spider|MSNBot|ia_archiver|Tomato Bot|YiSou Spider") {
set $flag "${flag}2";
}

if ($http_dnt != 1) {
set $flag "${flag}3";
}

if ($flag = "0123") {
post_action @tracker;
}
## End of Google analytics nginx
}

location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|ico)$ {

expires 30d;
}

location ~ .*\.(js|css)?$ {

expires 30d;
}

}
[/code]

6 调试方法

如果需要调试,请参照Ng­inx 内配置 Google An­a­lyt­ics 指南中的调试部分,使用netcat进行调试。不知是netcat版本差异还是其它原因,使用该文中命令不能成功监听目标端口,需要使用如下命令
nc -k -l -p 9999 127.0.0.1

然后使用如下命令查看端口情况可看到9999端口已经打开,发送数据可正常接收
netstat -nlt

7 参考资料

Leave a Reply to 天毅 Cancel reply

Your email address will not be published. Required fields are marked *

16 thoughts on “Nginx 异步处理Google Analytics”