为了了解网站的访问情况,很多网站用了第三方的统计,比如google统计,百度统计,51.la,CNZZ等,但是统计的准确性不能而之,有的网站干脆放多个第三方的统计,以便做个比较,得到更准确的结果。
根据笔者对第三方统计的使用经验,第一:第三方统计有一定的水分存在,第二:因为具有通用性,并不能得到个性化的统计结果。第三:无法确定某个推广源的统计信息。因为这种问题的存在,公司有新的需要,便开发了一个简单的推广访问记录功能。
说起来并不复杂,只要用AJAX方法在后台添加访问记录即可,系统并没有根据Cookie来做跟踪记录,只是根据IP来,所以统计结果上可能有点出入,会少统计些。如果要更真实的统计结果,还是根据cookie统计为好,好了,下面就来介绍这个功能的实现。
思路是这样的,页面中只有加入一个js文件,就能统计到该页面的访问信息,如果运用了模板功能,就只要在模板中加入此js即可,此js我们暂命名为visit.js,放在根目录下,建议链接放在页面的底部即可。js文件里通过xmlhttpRequest这个对象把访问记录信息添加到数据库Visit表中,表设计的字段如下:
下面来介绍js的实现,js方法需异步调用后台方法,这个文件我们定义为AJAX.aspx,方法比较简单,就是获取js文件当中传递过来的参数,然后添加到数据库中去。
js中代码如下:
1 Visit.js 2 3 var req; 4 var visitID; 5 creatReq(); 6 7 function creatReq() { 8 9 // 获取当前网站的更目录,这比较重要,全局通用的保证 10 var path = getRootPath(); 11 // 后台处理的文件地址,注意,必须把这个文件的前台页面大部分清空,只留下第一行 12 var url = path + "AJAX.aspx"; 13 14 if (window.XMLHttpRequest) { 15 req = new XMLHttpRequest; 16 } 17 else if (window.ActiveXObject) { 18 req = new ActiveXObject("Microsoft.XMLHttp"); 19 } 20 if (req) { 21 // 获取当前的网址 22 var link = window.location.href; 23 // 获取上页地址 24 var oldlink = document.referrer; 25 // 获取当前访问页的标题 26 var titleName = document.title; 27 // 屏幕分辨率 28 var screen = window.screen.width + "*" + window.screen.height; 29 // 异步请求发送 30 req.open("GET", url + "?id=" + escape(link) + "&oldlink=" + escape(oldlink) + "&title=" + escape(titleName) + "&sys=" + getSysInfo() + "&s=" + screen + "&b=" + GetBrowserType() + " " + GetBrowserVersion() + "&p=" + remote_ip_info.province + "&c=" + remote_ip_info.city + "&k=" + GetKeyword(oldlink), true); 31 req.onreadystatechange = callback; // 制定回调函数 32 req.send(null); 33 } 34 } 35 36 // 获取当前网站的更目录,这比较重要,全局通用的保证 37 function getRootPath() { 38 return window.location.protocol + "//" + window.location.host + "/"; 39 } 40 41 42 // 获取来自搜索引擎的关键词 43 function GetKeyword(url) { 44 if (url.toString().indexOf("baidu") > 0) { 45 return request(url, "wd"); 46 } 47 else if (url.toString().indexOf("google") > 0) { 48 return request(url, "q"); 49 } 50 else if (url.toString().indexOf("sogou") > 0) { 51 return request(url, "query"); 52 } 53 else if (url.toString().indexOf("soso") > 0) { 54 return request(url, "w"); 55 } 56 else { 57 return ""; 58 } 59 } 60 61 // 获取链接地址中某个参数的值 62 function request(url, paras) { 63 var paraString = url.substring(url.indexOf("?") + 1, url.length).split("&"); 64 var paraObj = {} 65 for (i = 0; j = paraString[i]; i++) { 66 paraObj[j.substring(0, j.indexOf("=")).toLowerCase()] = j.substring(j.indexOf("=") + 1, j.length); 67 } 68 var returnValue = paraObj[paras.toLowerCase()]; 69 if (typeof (returnValue) == "undefined") { 70 return ""; 71 } else { 72 return returnValue; 73 } 74 } 75 76 77 // 回调函数,可以获取添加后的访问ID,以便其他操作。 78 function callback() { 79 if (req.readyState == 4) { 80 if (req.status == 200) { 81 visitID = req.responseText.toString(); 82 } 83 else { 84 85 } 86 } 87 else { 88 89 } 90 } 91 92 93 // 获取系统信息 94 function getSysInfo() { 95 96 var ua = navigator.userAgent.toLowerCase(); 97 isWin7 = ua.indexOf("nt 6.1") > -1 98 isVista = ua.indexOf("nt 6.0") > -1 99 isWin2003 = ua.indexOf("nt 5.2") > -1 100 isWinXp = ua.indexOf("nt 5.1") > -1 101 isWin2000 = ua.indexOf("nt 5.0") > -1 102 isWindows = (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1) 103 isMac = (ua.indexOf("macintosh") != -1 || ua.indexOf("mac os x") != -1) 104 isAir = (ua.indexOf("adobeair") != -1) 105 isLinux = (ua.indexOf("linux") != -1) 106 var broser = ""; 107 if (isWin7) { 108 sys = "Windows 7"; 109 } else if (isVista) { 110 sys = "Vista"; 111 } else if (isWinXp) { 112 sys = "Windows xp"; 113 } else if (isWin2003) { 114 sys = "Windows 2003"; 115 } else if (isWin2000) { 116 sys = "Windows 2000"; 117 } else if (isWindows) { 118 sys = "Windows"; 119 } else if (isMac) { 120 sys = "Macintosh"; 121 } else if (isAir) { 122 sys = "Adobeair"; 123 } else if (isLinux) { 124 sys = "Linux"; 125 } else { 126 sys = "Unknow"; 127 } 128 return sys; 129 } 130 131 // 获取浏览器类型 132 function GetBrowserType() { 133 134 var ua = navigator.userAgent.toLowerCase(); 135 136 if (ua == null) return "ie"; 137 138 else if (ua.indexOf('chrome') != -1) return "chrome"; 139 140 else if (ua.indexOf('opera') != -1) return "opera"; 141 142 else if (ua.indexOf('msie') != -1) return "ie"; 143 144 else if (ua.indexOf('safari') != -1) return "safari"; 145 146 else if (ua.indexOf('firefox') != -1) return "firefox"; 147 148 else if (ua.indexOf('gecko') != -1) return "gecko"; 149 150 else return "ie"; 151 152 } 153 154 // 获取浏览器版本 155 function GetBrowserVersion() { 156 157 var ua = navigator.userAgent.toLowerCase(); 158 159 if (ua == null) return "null"; 160 161 else if (ua.indexOf('chrome') != -1) return ua.substring(ua.indexOf('chrome') + 7, ua.length).split(' ')[0]; 162 163 else if (ua.indexOf('opera') != -1) return ua.substring(ua.indexOf('version') + 8, ua.length); 164 165 else if (ua.indexOf('msie') != -1) return ua.substring(ua.indexOf('msie') + 5, ua.length - 1).split(';')[0]; 166 167 else if (ua.indexOf('safari') != -1) return ua.substring(ua.indexOf('safari') + 7, ua.length); 168 169 else if (ua.indexOf('gecko') != -1) return ua.substring(ua.indexOf('firefox') + 8, ua.length); 170 171 else return "null"; 172 173 }
这里有一个特殊说明,根据IP来获取省份和城市信息,目前用的是新浪提供的js文件,没有用网上流传的IP库信息,用新浪的这个js有时候获取的是乱码信息,这个问题偶尔会出现。
这是新浪的地址引用:<script language='javascript' type='text/javascript' src='http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=js'></script>
下面说后台,AJAX.aspx文件的前台删除大部分内容,只留下第一行信息,后台就是获取js传递过来的信息,代码如下:
AJAX.ASPX //放在Page_load里面的内容 visitModel.VisitReferrer = Request.QueryString["oldlink"].ToString() ; visitModel.VisitReferrerType = int.Parse(GetVisitReferrerType(Request.QueryString["oldlink"].ToString())); visitModel.VisitResolution = Request.QueryString["s"].ToString(); visitModel.VisitURL = Request.QueryString["id"].ToString(); visitModel.VisitTimeIn = System.DateTime.Now; visitModel.VisitIP = GetClientIP(); visitModel.VisitOS = Request.QueryString["sys"].ToString(); visitModel.VisitURLTitle = Request.QueryString["title"].ToString(); visitModel.VisitBrowserType = Request.QueryString["b"].ToString(); visitModel.VisitReferrerKeywords = ; visitModel.VisitProvince = Request.QueryString["p"].ToString(); visitModel.VisitCity = Request.QueryString["c"].ToString(); // 获取source后面的内容] string url = Request.QueryString["id"].ToString(); if (url.IndexOf("fromsource=") > 0) { int startindex= url.IndexOf("fromsource="); int endindex = url.Length - startindex - 11 ; string id = url.Substring(startindex + 11, endindex); visitModel.FromSource= id; } // 这里执行添加到数据库的操作并返回添加以后ID信息 int newID =visitDAL.Add(visitModel); Response.Write(newID.ToString()); // 获取IP地址 private string GetClientIP() { string result = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]; if (null == result || result == String.Empty) { result = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"]; } if (null == result || result == String.Empty) { result = HttpContext.Current.Request.UserHostAddress; } return result; } // 获取来源类型 protected string GetVisitReferrerType(string url) { url = url.Trim(); if ("" == url) { return "0"; //没有来源 } else if (url.IndexOf("fromsource=") > -1) { return "1"; //推广链接 } else if (url.IndexOf("baidu.com") > -1 ) { return "2"; // 百度搜索引擎 } else if (url.IndexOf("google.com") > -1) { return "3"; // Google搜索引擎 } else if (url.IndexOf("sogou.com") > -1) { return "4"; // 搜狗搜索引擎 } else if (url.IndexOf("soso.com") > -1) { return "5"; // 搜搜搜索引擎 } else { return "6"; // 其他浏览 } }
目前还有几个主要问题:
1、一是MAC地址没法获取,
2、用户离开网站的时间基本上获取不到,之前用js获取过,但实际效果还是不理想。
3、关键词的获取目前还有时是乱码,不能正确的获取。google出现乱码的机会多些。
好了,到这里一个简单的访问记录便好了,根据Fromsource字段可以统计推广来源信息,但各种各样的统计报表服务还需要根据需求来做。
目前举个简单的例子,统计每天访问的UV,PV,来自百度的访问IP,推广来源IP数,还有就是一跳率信息。根据我们上面的表结构,SQL语句如下:
1 统计每日UV,PV 2 3 SELECT CONVERT(VARCHAR(12), visittimein, 23) + '(' + DATENAME(weekday, 4 CONVERT(VARCHAR(12), visittimein, 23))+ ')' 访问日期 , 5 COUNT(DISTINCT visitip) UV , 6 ( SELECT SUM(RealVisitPageCount) VisitOne 7 FROM ( SELECT n.VisitIP , 8 COUNT(DISTINCT n.VisitURL) RealVisitPageCount 9 FROM dbo.VisitInfo n 10 WHERE CONVERT(VARCHAR(12), n.VisitTimeIn, 23) = CONVERT(VARCHAR(12), t.visittimein, 23) 11 GROUP BY n.VisitIP 12 ) a 13 ) PV , 14 COUNT(DISTINCT CASE WHEN visitreferrertype = 3 THEN visitip 15 END) 来自百度IP , 16 COUNT(DISTINCT CASE WHEN CustomLinkID != '' THEN visitip 17 END) 推广IP , 18 CAST (( SELECT SUM(RealVisitPageCount) VisitOne 19 FROM ( SELECT n.VisitIP , 20 COUNT(DISTINCT n.VisitURL) RealVisitPageCount 21 FROM dbo.VisitInfo n 22 WHERE CONVERT(VARCHAR(12), n.VisitTimeIn, 23) = CONVERT(VARCHAR(12), t.visittimein, 23) 23 GROUP BY n.VisitIP 24 HAVING COUNT(DISTINCT n.VisitURL) = 1 25 ) a 26 ) * 100 / COUNT(DISTINCT visitip) AS VARCHAR(2)) + '%' AS 一跳率 27 28 FROM VisitInfo t 29 30 GROUP BY CONVERT(VARCHAR(12), visittimein, 23) 31 ORDER BY 访问日期 DESC
结果显示如下:
这是测试的结果
当然随着数据量的增加,数据记录越来越多,感觉要做一张结果分析统计表,把每天的信息分析统计结果直接放到里面去,每天分析,以后直接查询该表即可
如果需要其他的分析报表,比如根据地区进行分析,根据浏览器进行兼容性分析,这里就不一一探讨了。还有一些就是跟踪统计分析,这里也没有实现,如果需要更好的记录访问信息,
笔者认为,还是基于Cookie实现比较合理,尤其是电子商务网站,可以跟踪用户是否注册,是否购买商品等转化率问题。
原文地址http://www.cnblogs.com/netsql/archive/2011/12/24/2300510.html