友盟Web端统计服务源码分析

友盟是阿里巴巴旗下的一个用户行为统计工具,官方网址为 https://www.umeng.com/

该文章主要描述友盟工具在web端()的实施使用,工作原理,相关源码分析,以及功能分析.

实施使用

1.在友盟中的域名列表中配置好要统计的域名

  1. 在自己网站的HTML页面中嵌入以下友盟提供的跟踪代码:

工作原理

跟踪代码请求 JS文件 http://s4.cnzz.com/z_stat.php?id=1278216955 (源码分析区域有完整的代码)

该JS文件为友盟主要文件里面透出 push 方法:

e = window
p() { this.c = “1278216955”; this.ca = “z”; this.Y = “”; this.V = “”; this.X = “”; this.D = “1574231684”; this.$ = “z3.cnzz.com”; this.W = “”;

this.H = “CNZZDATA” + this.c; this.G = “CNZZDbridge” + this.c; this.O = “_cnzz_CV” + this.c; this.P = “CZ_UUID” + this.c;

this.K = “UM_distinctid”; this.A = “0”; this.J = {}; this.a = {}; this.Ca() }

Ca: function () { try { this.ma(), this.ja(), this.ha(), this.U(), this.ya(), this.S(), this.Ba(), this.w(), this.wa(), this.va(), this.za(), this.o(), this.ua(),

this.xa(), this.Aa(), this.sa(), this.qa(), this.ta(), this.Ga(), e[this.G] = e[this.G] || {}, this.ra("_cnzz_CV") } catch (a) { h(a, “i failed”) } },

Ga: function () { try { if (“undefined” === typeof e._cz_account || e._cz_account === this.c) { e._cz_account = this.c;

if ("[object Array]" === {}.toString.call(e._czc)) for (var a = e._czc, b = 0, c = a.length; b < c; b++)this.L(a[b]); this.Ea() } } catch (d) { h(d, “pP failed”) } },

Ea: function () { try { var a = this; e._czc = { push: function () { return a.L.apply(a, arguments) } } } catch (b) { h(b, “oP failed”) } },

L 方法中包含循环识别如下方法:
_trackPageview

       case  "_trackPageview":  if  (a[1])  {
                  this.a.f  =  q  +  "//"  +  e.location.host;  "/"  !==  a[1].charAt(0)  &&  (this.a.f  +=  "/");  this.a.f  +=  a[1];  
                  if  (""  ===  a[2])  this.a.g = ""; 
                  else if (a[2]) {
            var b = a[2]; "http" !==
              b.substr(0, 4) && (b = q + "//" + e.location.host, "/" !== a[2].charAt(0) && (b += "/"), b += a[2]); this.a.g = b
            } 
            this.s(); "undefined" !== typeof this.a.g && delete this.a.g; "undefined" !== typeof this.a.f && delete this.a.f
          } break; 

最终发送到 z3.cnzz.com/stat.htm

http://z3.cnzz.com/stat.htm?id=1278216955&r=http%3A%2F%2Flocalhost%3A9000%2Fquxiaoyuan.com&lg=zh-cn&ntime=1574671861&cnzz_eid=826526004-1574065940-null&showp=1280x800&p=http%3A%2F%2Flocalhost%3A9000%2Fhttp%3A%2F%2Flocalhost%3A9000%2FOperatingList&t=Node%E8%BF%90%E8%90%A5%E5%90%8E%E5%8F%B0&umuuid=16e7de0705c25-0f2122b28ba4ba-1d3c6a5d-fa000-16e7de0705d81e&h=1&rnd=822479286

_trackEvent

    (
    c.push(g(a[1])), c.push(g(a[2])), c.push(a[3] ? g(a[3]) : ""), 
    a[4] = parseFloat(a[4]), 
    c.push(isNaN(a[4]) ? 0 : a[4]), 
    c.push(a[5] ? g(a[5]) : ""), this.v = c.join("|"), this.s(), delete this.v
    ); break; 

最终发送到 ei.cnzz.com/stat.htm

http://ei.cnzz.com/stat.htm?id=1278216955&r=&lg=zh-cn&ntime=1574231684&cnzz_eid=2142869084-1574065940-&showp=1280x800&p=http://fe.quxiaoyuan.com:9000/#/&ei=node-admin|点击动作|4|0|&t=Node运营后台&umuuid=16e7da43ba314c-08446083910c49-1d3c6a5d-fa000-16e7da43ba48a&h=1&rnd=199224148

_setCustomVar

    case "_setCustomVar": if (3 <= a.length) {
      if (!a[1] || !a[2]) return !1; var d = a[1], f = a[2], k = a[3] || 0; a = 0; 
      for (var n in this.a.b) a++; if (5 <= a) return !1; 
      var u = 0 == k ? "p" : -1 == k || -2 == k ? k : (new Date).getTime() + 1E3 * k; 
      this.a.b[d] = {}; 
      this.a.b[d].da = f; 
      this.a.b[d].h = u; 
      this.I()
    } break; 

this.O = “_cnzz_CV”
I: function () { try {
var a = [], b;
for (b in this.a.b) { var c = []; c.push(b); c.push(this.a.b[b].da); c.push(this.a.b[b].h); var d = c.join("|"); a.push(d) }
if (0 === a.length) return !0; var f = new Date; f.setTime(f.getTime() + 157248E5);
var k = this.O + “=”; this.b = g(a.join("&")); k += this.b; k += “; expires=” + f.toUTCString();
l.cookie = k + “; path=/”
} catch (n) { h(n, “sCV failed”) } },

最终载入Cookie

_cnzz_CV1278216955=%E4%BC%9A%E5%91%98%E7%BA%A7%E5%88%AB%7C%E9%92%BB%E7%9F%B3%7C0

以后在_trackEvent的时候会额外增加参数:

http://ei.cnzz.com/stat.htm?id=1278216955&r=&lg=zh-cn&ntime=1574650380&cnzz_eid=826526004-1574065940-null&showp=1280x800&p=http%3A%2F%2Flocalhost%3A9000%2F&ei=node-admin%7C%25E7%2582%25B9%25E5%2587%25BB%25E5%258A%25A8%25E4%25BD%259C%7C2%7C0%7C&cv=%E4%BC%9A%E5%91%98%E7%BA%A7%E5%88%AB%7C%E9%92%BB%E7%9F%B3%7C0&t=Node%E8%BF%90%E8%90%A5%E5%90%8E%E5%8F%B0&umuuid=16e7de0705c25-0f2122b28ba4ba-1d3c6a5d-fa000-16e7de0705d81e&h=1&rnd=1014584379

key
value
id 1278216955
r
lg
zh-cn
ntime 1574650380
cnzz_eid 826526004-1574065940-null
showp 1280x800
p http://localhost:9000/
ei node-admin|%E7%82%B9%E5%87%BB%E5%8A%A8%E4%BD%9C|2|0|
cv 会员级别|钻石|0
t Node运营后台
umuuid 16e7de0705c25-0f2122b28ba4ba-1d3c6a5d-fa000-16e7de0705d81e
rnd 1014584379

_deleteCustomVar

case “_deleteCustomVar”: 2 <= a.length && (d = a[1], this.a.b[d] && (delete this.a.b[d], this.I())); break;

最终载入Cookie

_trackPageContent

case “_trackPageContent”: a[1] && (this.F = a[1], this.s(), delete this.F);
最终发送到 ca.cnzz.com

_trackPageAction

case “_trackPageAction”: c = []; a[1] && a[2] && (c.push(g(a[1])), c.push(g(a[2])), this.u = c.join("|"), this.s(), delete this.u); break;
最终发送到 ca.cnzz.com

_setUUid

case “_setUUid”: var w = a[1]; if (128 < w.length) return !1;
var v = new Date; v.setTime(v.getTime() + 157248E5); this.aa(this.P, w, v)
}
aa: function (a, b, c, d, f, k) { a = g(a) + “=” + g(b); c instanceof Date && (a += “; expires=” + c.toGMTString()); d && (a += “; path=” + d); f && (a += “; domain=” + f); k && (a += “; secure”); l.cookie = a },
最终载入cookie

http://s4.cnzz.com/z_stat.php?id=1278216955 该链接引用的JS源码最下面有段调用代码:

try { var t = new p; e[t.G].bobject = t; !1 !== e._cz_autoPageview ? t.s() : t.Z(); 
  p.prototype.getACookie = p.prototype.m; 
  p.prototype.callRequest = p.prototype.j; 
  p.prototype.createScriptIcon = p.prototype.pa; 
  p.prototype.createIcon = p.prototype.oa; 
  t.Ia(); t.ga() } catch (a) { h(a, "main failed") }




  Ia: function () {
  try {
    var a = z + "?", b = []; b.push("web_id=" + g(this.c)); 
    this.Y && b.push("show=" + g(this.Y)); 
    this.X && b.push("online=" + g(this.X)); 
    this.V && b.push("l=" + g(this.V)); 
    this.ca && b.push("t=" + this.ca); 
    a += b.join("&"); 
    this.na(a,"utf-8")
  } catch (c) { h(c, "rN failed") }
  },

na: function (a, b) { try { if (b = b || “utf-8”, “1” === this.A) { var c = l.createElement(“script”); c.type = “text/javascript”; c.async = !0; c.charset = b; c.src = a; var d = l.getElementsByTagName(“script”)[0]; d.parentNode && d.parentNode.insertBefore(c, d) } else l.write(x("%3Cscript src=’" + a + “’ charset=’” + b + “’ type=‘text/javascript’%3E%3C/script%3E”)) } catch (f) { h(f, “cAS failed”) } }

na方法中引入了 https://c.cnzz.com/core.php?web_id=1278216955&t=z (源码分析区域有完整的代码)
该JS文件主要为热点图提供方法服务

源码最下面调用 new t

var m = “http://hm2.cnzz.com/”, q = [‘http://fe.quxiaoyuan.com:9000/#/OperatingList’], g = document, f = window, n = encodeURIComponent, r = “unknow”, l = null, t = function () { this.c() };

c: function () {
if (!1 === this.f()) return !1; this.a(g, “mousedown”, this.b); var a = f.navigator.userAgent;
l = g.documentElement && 0 !== g.documentElement.clientHeight ? g.documentElement : g.body; a = a ? a.toLowerCase().replace(/-/g, “”) : “”; for (var b = “netscape;se 1.;se 2.;saayaa;360se;tencent;qqbrowser;mqqbrowser;maxthon;myie;theworld;konqueror;firefox;chrome;safari;msie 5.0;msie 5.5;msie 6.0;msie 7.0;msie 8.0;msie 9.0;msie 10.0;Mozilla;opera”.split(";"), d = 0; d < b.length; d += 1)
if (-1 !== a.indexOf(b[d])) { r = b[d]; break }
},

b: function (a) {
a || (a = f[a]); var b = a.target || a.srcElement;
“IMG” === b.tagName && (b = b.parentNode);
b = “A” === b.tagName ? 1 : 0; var d = a.which || a.button, p = a.clientX; a = a.clientY; var e = f.pageYOffset || l.scrollTop;
p += f.pageXOffset || l.scrollLeft; a += e; e = l.clientWidth || f.innerWidth; var k = f.location.href, c = [];
c.push(“id=1278216955”); c.push(“x=” + p); c.push(“y=” + a); c.push(“w=” + e); c.push(“s=” + f.screen.width + “x” + f.screen.height); c.push(“b=” + r); c.push(“c=” + d); c.push(“r=” + n(g.referrer)); c.push(“a=” + b);
“” !== f.location.hash && c.push(“p=” + n(k));
c.push(“random=” + n(Date())); b = c.join("&"); var h = new Image; h.onload = h.onerror = h.onabort = function () { h = h.onload = h.onerror = h.onabort = null };
“https:” === u && (m = m.replace(/^http:/, “https:”)); h.src = m + “heatmap.gif?” + b; return !0
},

h.src = m + “heatmap.gif?” + b; return !0 最终发送到hm2.cnzz.com/heatmap

http://hm2.cnzz.com/heatmap.gif?id=1278216955&x=59&y=184&w=436&s=1280x800&b=chrome&c=1&r=&a=1&p=http://fe.quxiaoyuan.com:9000/#/&random=Wed Nov 20 2019 15:27:48 GMT+0800 (中国标准时间)

兜底发送到 z3.cnzz.com

http://z3.cnzz.com/stat.htm?id=1278216955&r=&lg=zh-cn&ntime=1574231684&cnzz_eid=2142869084-1574065940-&showp=1280x800&p=http://fe.quxiaoyuan.com:9000/#/&t=Node运营后台&umuuid=16e7da43ba314c-08446083910c49-1d3c6a5d-fa000-16e7da43ba48a&h=1&rnd=520124255

所有的源码中发生的错误均会发送到 http://jserr.cnzz.com/log.php

你可能感兴趣的:(友盟Web端统计服务源码分析)