广告素材:http://imgad0.pconline.com.cn/ivy/image/201311/19/13848568762230.swf
分析环境
操作系统:OS X Mavericks
浏览器:Google Chrome 版本 31.0.1650.48
先查一下监测公司的来历
打开万网,查询监测域名mlt01,查看 mlt01.com 的信息:
http://whois.www.net.cn/whois/domain/mlt01.com
注册商 Sponsoring Registrar 北京万网志成科技有限公司
注册日期 Registration Date(EDT) 28-nov-2011
展开 查看完整注册信息,能找到以下资料:
Registrant ID ................... hc177366686-cn
Registrant Name ................. Wang Cain
Registrant Organization ......... Menlo Technology Co, Ltd.
Registrant Address .............. Room 1, Building 1, No.333 HongQiao Road
Registrant City ................. shang hai shi
Registrant Province/State ....... shang hai
Registrant Postal Code .......... 200000
Registrant Country Code ......... CN
Registrant Phone Number ......... +86.02162675588
Registrant Fax .................. +86.02162675588
Registrant Email ................ [email protected]
Google Menlo Technology Co,就能找到公司信息:
http://www.adchina.com/en/us/Menlo.aspx
易传媒,我们的老朋友了!
注册人为易传媒解决方案副总裁@王华CainWang。
易传媒的两篇介绍文档:
http://www.docin.com/p-278696126.html
http://www.docin.com/p-462701156.html
常规监测分为三类:
按 ⌘ + ⌥ + I
打开 Chrome 控制台,激活流量面板,访问素材地址,可看到以下网络请求:
http://mlt01.com/o.htm?pv=0&sp=0,858396,872117,88763,0,1,1
这是易传媒的流量监测,很常规的请求,写 Cookie,记 Referer,User-Agent,还传了两个我们看不懂的参数。
Date:Wed, 20 Nov 2013 04:23:58 GMT
Expires:Mon, 1 Jan 1970 00:00:00 GMT
P3P:CP="NOI CURa ADMa DEVa OUR IND UNI COM NAV INT"
Server:nginx
Set-Cookie:CITY=900:255,-1:255,; domain=.mlt01.com; expires=Thu, 20-Nov-2014 04:23:58 GMT; path=/
Set-Cookie:cpcap=; path=/
Set-Cookie:lv5w8bs=; expires=Tue, 19-Nov-2013 04:23:58 GMT; path=/
Set-Cookie:categoryid=; path=/
Set-Cookie:mbcap=; path=/
Set-Cookie:CSV=; domain=.mlt01.com; expires=Fri, 20-Nov-2043 04:23:58 GMT; path=/
X-Powered-By:UrlRewriter.NET 2.0.0
点击监测有三个参数:
pv = 1
sp = 0,858396,872117,88763,0,1,1
target = http://lefen.lenovo.com/index.php/pph/see/42
对比之前的流量监测,我们会有以下结论:
易传媒用 o.htm 处理流量请求,用 c.htm 处理点击请求,记住这些规则,能有效防止错把点击加成了流量之类的事故。
流量的 sp 参数和点击的 sp 参数完全一致,这给他们后期做点击和流量的一致性分析,提供了数据基础。如果某个IP只做了点击,而没有对应的曝光,很容易被纠出来。
target 表示跳转目标,到联想的乐份俱乐部,这个由某标负责的项目,页面水平直追当代大学生的毕业设计稿,URL Rewrite 都做得这么业余,怀疑有过二次转包。
点击监测同样会记录 Referer, 写 Cookie:
Date:Wed, 20 Nov 2013 05:01:57 GMT
Expires:Mon, 1 Jan 1970 00:00:00 GMT
Location:http://lefen.lenovo.com/index.php/pph/see/42
P3P:CP="NOI CURa ADMa DEVa OUR IND UNI COM NAV INT"
Server:nginx
Set-Cookie:clk=84704:0,84483:0,82730:0,84445:0,84918:8,; expires=Fri, 20-Nov-2043 05:01:57 GMT; path=/
Via:HTTP/1.1 GWA
页面上没有添加联想自己的监测,但理论上这种动态项目,最后一道防线,就是系统日志了,这些暂不考虑。
重点专注第三方监测
查看页面源代码,发现有两家:
<script type="text/javascript">
var _bdhmProtocol = (("https:" == document.location.protocol) ? " https://" : " http://");
document.write(unescape("%3Cscript src='" + _bdhmProtocol + "hm.baidu.com/h.js%3Ffe5c1502be9adcdabd9978e353b291a1' type='text/javascript'%3E%3C/script%3E"));
</script>
网络面板的请求非常多,可以过滤一下请求,激活网络面板,按 ⌘ + F
,输入 baidu,勾选 Filter,就可以很方便的查看百度请求了。
百度统计为全方位监测,可通过 Request Headers、Query String Parameters、Response Header 查看详细信息。
<!-- PV监测代码 -->
<script type="text/javascript">
MltTracker= {
mid: 250051, //获取mediabuyid
ers: [{ "type": "pageview",uid: "",pid:"" }],
track: function (er)
{
this.ers.push(er);
}};
(function ()
{
var js = document.createElement("script"), scri = document.getElementsByTagName("script")[0];
js.type = "text/javascript";
js.async = true;
scri.parentNode.insertBefore(js, scri);
js.src = location.protocol == "https:" ? "https://secure.mlt01.com/nt.js" : "http://static.mlt01.com/nt.js";
})();
</script>
做页面的同学,非常体贴,专门做了注释。
相对百度,易传媒的监测更加细致:
Query String Parameters
rct:html
g:0
mid:250051
u:1,11
sr:1280,800
dt:联想智能手机|乐粉俱乐部|品牌汇
src:5
ssn:16902307135873180,1,1384922155,1,1384922155
jsv:4
type:pageview
甚至取了页面标题 dt,有效了堵住了某些直接刷监测代码优化数据的渠道。
易传媒的监测代码
!
function(a) {
if ("undefined" == typeof _MltTracker) {
_MltTracker = null;
var d, b = 15552e6,
c = 2592e6,
e = _MltTracker = function(a) {
return new e.prototype.init(a)
};
e.extend = function(a, b) {
var c;
for (c in b) b.hasOwnProperty(c) && (a[c] = b[c]);
return a
},
e.extend(e, {
idle: [1, 1],
getProtocol: function() {
return "https:" === location.protocol ? "https://": "http://"
},
joinParameters: function(b, c) {
var e, d = [];
if ("," === c) for (e in b) b.hasOwnProperty(e) && "" !== b[e] && b[e] != a && Array.prototype.push.call(d, b[e]);
else if ("&" === c) for (e in b) b.hasOwnProperty(e) && "" !== b[e] && b[e] != a && Array.prototype.push.call(d, e + "=" + b[e]);
return d.join(c)
},
getCurrentUrl: function() {
var b = "";
try {
b = top.location.href
} catch(c) {
b = location.href
}
return encodeURIComponent(b)
},
getPreviousUrl: function() {
var a = "";
try {
a = top.document.referrer
} catch(b) {
try {
a = document.referrer
} catch(c) {}
}
return encodeURIComponent(a)
},
getQueryString: function(a) {
var b, c, f, g, h, d = {};
if (!e.queryString) {
try {
b = top.location.search
} catch(i) {
b = location.search
}
if (b) for (b = b.substr(1), c = b.split("&"), f = 0, g = c.length; g > f; f++) h = c[f].split("="),
2 === h.length && (d[h[0]] = h[1]);
e.queryString = d
}
return e.queryString[a]
},
getCookieEnabled: function() {
return navigator.cookieEnabled ? 1 : 0
},
getFlashVersion: function() {
var a = "0,0,0,0";
try {
navigator.plugins && navigator.plugins["Shockwave Flash"] ? a = navigator.plugins["Shockwave Flash"].description: window.ActiveXObject && new ActiveXObject("ShockwaveFlash.ShockwaveFlash") && (a = new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version"))
} catch(b) {}
return a = a.match(/\d+/g),
a[0]
},
load: function(a, b, c, d, e) {
var f, i, g = /loaded|complete/i,
h = "_script_$" + Math.ceil(1e10 * Math.random());
b ? (f = document.createElement("script"), f.type = "text/javascript", f.async = !0, f.charset = "utf-8", f.id = h, i = document.getElementsByTagName("script")[0], i.parentNode.insertBefore(f, i), f.src = a) : (window.ActiveXObject && (g = /complete/i), document.write('<script type="text/javascript" charset="utf-8" src="' + a + '" id="' + h + '"></scri' + "pt>")),
f = document.getElementById(h),
f && (f.onload = f.onreadystatechange = function() { (!f.readyState || f.readyState.match(g)) && ("function" == typeof c && c(), c = null, e = null, f && f.parentNode && (f.onload = f.onreadystatechange = null, f = null))
}),
d && setTimeout(function() {
f && ("function" == typeof e && e(), e = null, d = null, f.src = "javascript:void(0)")
},
d)
},
getTopDomain: function(a) {
if (!arguments.callee.domain) {
for (var b = a || location.hostname,
c = b.split("."), d = /com|edu|gov|int|mil|net|org|biz|info|pro|name|museum|coop|aero|xxx|idv/, e = c.length - 1, f = 0; e > -1; e--) if (d.test(c[e])) {
f = e;
break
}
f = 0 === f ? 1 : f,
arguments.callee.domain = c.slice(f - 1).join(".")
}
return arguments.callee.domain
},
cookie: function(a, b, c) {
if ("undefined" == typeof b) {
var e = ";?" + a + "=([^;]*);?",
f = new RegExp(e);
return f.test(document.cookie) ? RegExp.$1: null
}
null === b && (b = "", c = c || {},
c.expires = -1);
var d = a + "=" + b;
c && (c.path && (d += "; path=" + c.path), c.expires instanceof Date && (d += "; expires=" + c.expires.toGMTString()), c.domain && (d += "; domain=" + c.domain), c.secure && (d += "; secure")),
document.cookie = d
},
fc: function() {}
}),
e.prototype = {
constructor: "_MltTracker",
jsv: 4,
init: function(a) {
if (a.mid) {
var f, g, h, i, c = this;
for (c.mid = a.mid, a.ecc && (c.ecc = a.ecc), h = c.zcookie("mltn"), i = c.zcookie("mlts"), d = "." + e.getTopDomain(), (d.lastIndexOf(".") < 1 || !/\w/.test(d)) && (d = null), h || c.zcookie("mltn", [0, 0, 0, 0, 0].join(">"), {
domain: d,
expires: new Date((new Date).getTime() + b),
path: "/"
}), a.serverbaseurl && (c.serverbaseurl = a.serverbaseurl), f = 0, g = a.ers.length; g > f; f++) c.track(a.ers[f])
}
},
zcookie: function(a, b, c) {
var d = this,
f = d.mid,
g = new RegExp("@" + f + "~([^@]+)+@"),
h = e.cookie(a);
return "undefined" == typeof b ? h && g.test(h) ? RegExp.$1: null: (b = h ? g.test(h) ? h.replace(g, "@" + f + "~" + b + "@") : h + "@" + f + "~" + b + "@": "@" + f + "~" + b + "@", e.cookie(a, b, c), void 0)
},
track: function(a) {
var b = this; !
function() {
if (e.idle[1]) {
var c = b.getServerUrl() + b.getParameters(a);
e.idle[1] = 0,
b.cer = a,
e.load(c, 1,
function() {
e.idle[1] = 1
})
} else setTimeout(arguments.callee, 0)
} ()
},
generateCurrentUrl: function(a) {
var b = "";
try {
b = 0 == a.indexOf("/") ? top.location.protocol + "//" + top.location.host + a: /^https?:\/\//.test(a) ? a: top.location.protocol + "//" + top.location.host + top.location.pathname.slice(0, top.location.pathname.lastIndexOf("/")) + "/" + a
} catch(c) {
b = 0 == a.indexOf("/") ? location.protocol + "//" + location.host + a: /^https?:\/\//.test(a) ? a: location.protocol + "//" + location.host + location.pathname.slice(0, location.pathname.lastIndexOf("/")) + "/" + a
}
return encodeURIComponent(b)
},
getParameters: function(b) {
var d, h, j, l, c = this,
f = {
rct: "html",
g: 0,
mid: c.mid,
u: [e.getCookieEnabled(), e.getFlashVersion()].join(","),
sr: [screen.width, screen.height].join(","),
dt: encodeURIComponent(document.title)
},
g = c.zcookie("mltis"),
i = c.zcookie("mlts"),
k = c.zcookie("mltn");
if (g && (h = g.split(">"), f.aid = h[1], f.bid = h[2], f.cid = h[3]), i && (j = i.split(">"), f.src = j.join(",")), k && (l = k.split(">"), 0 != l[0] && (f.ssn = l.join(","))), c.ecc && (f.curl = encodeURIComponent(document.referrer)), b.path && "pageview" === b.type ? (f.purl = c._purl || e.getCurrentUrl(), f.curl = c.generateCurrentUrl(b.path), c._purl = f.curl, b.path = null) : f.purl = e.getPreviousUrl(), f.jsv = c.jsv, "object" == typeof b) for (d in b) b.hasOwnProperty(d) && "" !== b[d] && b[d] != a && (f[d] = encodeURIComponent(b[d]));
return e.joinParameters(f, "&")
},
s: function(a, e, f, g, h, i, j) {
var k = this;
switch (a) {
case 1:
k.zcookie("mltis", [a, e || 0, f || 0, g || 0].join(">"), {
domain: d,
expires: new Date((new Date).getTime() + c),
path: "/"
}),
k.zcookie("mlts", [a, encodeURIComponent(e || 0), encodeURIComponent(f || 0), encodeURIComponent(g || 0)].join(">"), {
domain: d,
expires: new Date((new Date).getTime() + b),
path: "/"
});
break;
case 2:
k.zcookie("mlts", [a, encodeURIComponent(e || ""), encodeURIComponent(f || ""), encodeURIComponent(g || ""), encodeURIComponent(h || "")].join(">"), {
domain: d,
expires: new Date((new Date).getTime() + b),
path: "/"
});
break;
case 3:
k.zcookie("mlts", [a, encodeURIComponent(e || ""), encodeURIComponent(f || "")].join(">"), {
domain: d,
expires: new Date((new Date).getTime() + b),
path: "/"
});
break;
case 4:
k.zcookie("mlts", [a, encodeURIComponent(e || "")].join(">"), {
domain: d,
expires: new Date((new Date).getTime() + b),
path: "/"
});
break;
case 5:
k.zcookie("mlts", [a].join(">"), {
domain: d,
expires: new Date((new Date).getTime() + b),
path: "/"
});
break;
case 6:
k.zcookie("mltis", [a, e || 0, f || 0, g || 0].join(">"), {
domain: d,
expires: new Date((new Date).getTime() + c),
path: "/"
}),
k.zcookie("mlts", [a, encodeURIComponent(h || ""), encodeURIComponent(i || ""), encodeURIComponent(j || "")].join(">"), {
domain: d,
expires: new Date((new Date).getTime() + b),
path: "/"
})
}
},
n: function(a, c) {
var e = this,
f = e.zcookie("mltn"),
g = f.split(">");
g[0] != a && (g[1] = 0, g[3] = 0),
"pageview" === e.cer.type && (g[3] = parseInt(g[3], 10) + 1, g[4] = c),
g[0] = a,
g[1] = parseInt(g[1], 10) + 1,
g[2] = c,
e.zcookie("mltn", g.join(">"), {
domain: d,
expires: new Date((new Date).getTime() + b),
path: "/"
})
},
getServerUrl: function() {
var a = this;
return e.getProtocol() + a.getBaseUrl() + "nt.htm?"
},
getBaseUrl: function() {
var a = this;
return a.serverbaseurl ? a.serverbaseurl: "https:" === location.protocol ? "secure.mlt01.com/": "mlt01.com/"
}
},
e.prototype.init.prototype = e.prototype
}
} (),
"undefined" != typeof MltTracker && "_MltTracker" !== MltTracker.constructor && (MltTracker = _MltTracker(MltTracker));