广告监测分析案例
广告素材:Here
跳转链接:Here
分析环境
操作系统: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 ................ cain.wang@menlotechnologies.cn
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
常规监测分为三类:
1、流量监测
按 ⌘ + ⌥ + 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
2、点击监测
点击监测有三个参数:
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
3、页面监测
页面上没有添加联想自己的监测,但理论上这种动态项目,最后一道防线,就是系统日志了,这些暂不考虑。
重点专注第三方监测
查看页面源代码,发现有两家:
1)、百度统计
<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 查看详细信息。
2)、易传媒
<!-- 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 = b); 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));