相信用過google的analytics的朋友都了解其功能的強大.
由於工作需要,最近將其urchin.js的代碼down了一份下來研究了一下.由於其註釋很少,命名也很難讀懂.研究了1個月.小有所成.將其代碼重寫並加上了註釋.與大家一同分享.這裡面將google的用戶識別代碼刪除. /**//*
=======================================
|--------Author By BlackSoul---------|
|------------2006.04.27--------------|
|[email protected] ------|
|------------QQ:9136194--------------|
|------http://blacksoul.cnblogs.cn---|
========================================
*/
//定義全域量
var ur = ""; //來源位址
var urp = new Array(); //來源參數名稱
var urpv = new Array(); //來源參數值
var arrayCount = 0; //參數數目
pageOpen = new Date(); //進入頁面的時間
var reqURL = " http://192.168.0.219/Analytics/ "; //接收資料的頁面位址
var GUID = Math.round(Math.random()*2147483647); //使用者唯一隨機數
var title = document.title; //網頁標題
var uexp = pageOpen.getTime() + ( 1000 * 60 * 60 * 24 * 30 ); //設定cookie過期時間既回訪使用者的限定
var rtu = "false"; //指示使用者是否回訪使用者
//瀏覽器特徵資訊
var brower = new Array();
/**//*
* brower[0] 瀏覽器類型
* brower[1] 瀏覽器版本
* brower[2] 瀏覽器java是否開啟1開-1關
* brower[3] 瀏覽器flash版本
* brower[4] 瀏覽器作業系統
* brower[5] 瀏覽器分辨率
* brower[6] 瀏覽器色深
* brower[7] 瀏覽器語言
* brower[8] 瀏覽器插件
*/
var sEn=new Array(); //搜尋引擎的名稱
var keyWord=new Array(); //關鍵字傳輸形式
sEn[0]="google"; keyWord[0]="q";
sEn[1]="yahoo"; keyWord[1]="p";
sEn[2]="msn"; keyWord[2]="q";
sEn[3]="aol"; keyWord[3]="query";
sEn[4]="lycos"; keyWord[4]="query";
sEn[5]="ask"; keyWord[5]="q";
sEn[6]="altavista"; keyWord[6]="q";
sEn[7]="search"; keyWord[7]="q";
sEn[8]="netscape"; keyWord[8]="query";
sEn[9]="earthlink"; keyWord[9]="q";
sEn[10]="cnn"; keyWord[10]="query";
sEn[11]="looksmart"; keyWord[11]="key";
sEn[12]="about"; keyWord[12]="terms";
sEn[13]="excite"; keyWord[13]="qkw";
sEn[14]="mamma"; keyWord[14]="query";
sEn[15]="alltheweb"; keyWord[15]="q";
sEn[16]="gigablast"; keyWord[16]="q";
sEn[17]="voila"; keyWord[17]="kw";
sEn[18]="virgilio"; keyWord[18]="qs";
sEn[19]="teoma"; keyWord[19]="q";
sEn[20]="baidu"; keyWord[20]="wd";
//test data----------------------------////////////////// ////////////-----------/-/-/-/-/-/-/-/-/-/-/-
sEn[21]="localhost"; keyWord[21]="q";
這裡面定義一些全域的量,其中upr,urpv為來源參數和指,例如來源為http://www.google.com/?p=BlackSoul&q=javascript ,則urp[0]="p",urp[ 1]="q" 對應的urpv[0]="BlackSoul",urpv[1]="javascript".
但是最終傳輸的時候是以分隔符號的形式傳遞給伺服器端的.
GUID為隨機數,google是這麼做的.當初沒有想通為什麼要保存一個隨機數,後來分析數據的才明白過來.為了驗證用戶的唯一性.
以下是函數處理:
//-----------------------------比較url,如果為搜尋引擎則儲存關鍵字-------- -----
function getKeyword(url)
{
var hostname;
if(url.indexOf(".") == -1)
{hostname = url;}
else
{hostname = url.substring(url.indexOf("."),url.lastIndexOf("."));}
for(var i = 0; i < sEn.length; i++)
{
if(hostname == sEn[i])
{
for(var j = 0; j < urp.length; j ++)
{
if(urp[j] == keyWord[i])
{
return urpv[j];
}
}
}
}
return "";
}
//將URL轉換為地址和頁面參數和參數值參數uri為頁面地址
function gethn(uri)
{
if(!uri || uri == "") return "";
ur = uri;
var sub;
//帶參數
if(ur.indexOf("?") != -1)
{
var url = ur.substring(0,ur.indexOf("?"));
var para = ur.substring(ur.indexOf("?")+1,ur.length);
while(para.length > 0)
{
if(para.indexOf("&") == -1)
{
urp[arrayCount] = para.substring(0,para.indexOf("="));
urpv[arrayCount] = para.substring(para.indexOf("=")+1,para.length);
break;
}
sub = para.substring(0,para.indexOf("&"));
urp[arrayCount] = sub.substring(0,sub.indexOf("="));
urpv[arrayCount] = sub.substring(sub.indexOf("=")+1,sub.length);
para = para.substring(para.indexOf("&")+1,para.length);
arrayCount ++;
}
return url;
}
else
return ur;
}
//----------------------------取得網域----------------- ----------------------------
function getHostName(url)
{
url = url.substring(url.indexOf('://')+3,url.length);
url = url.substring(0,url.indexOf("/"));
return url;
}
//-----------------------------------獲得flash版本----------------- -------------------------
function getFlash() {
var f="-1",n=navigator;
if (n.plugins && n.plugins.length) {
for (var ii=0;ii<n.plugins.length;ii++) {
if (n.plugins[ii].name.indexOf('Shockwave Flash')!=-1) {
f=n.plugins[ii].description.split('Shockwave Flash ')[1];
break;
}
}
} else if (window.ActiveXObject) {
for (var ii=10;ii>=2;ii--) {
try {
var fl=eval("new ActiveXObject('ShockwaveFlash.ShockwaveFlash."+ii+"');");
if (fl) { f=ii + '.0'; break; }
}
catch(e) {}
}
}
if(f == "-1")
return f;
else
return f.substring(0,f.indexOf(".")+2);
}
//--------------------------設定非同步傳輸------------------ -----------------
function createXMLHttpRequest()
{
if (window.XMLHttpRequest)
{
return new XMLHttpRequest();
}
else if (window.ActiveXObject)
{
return new ActiveXObject("Microsoft.XMLHttp");
}
} 以上的方法可以取得一些基本資訊.但是關鍵的問題還是設定使用者cookie,判斷回訪,判斷最後一次造訪時間,並設定其GUID.這裡看了很久沒有發現google是怎麼做的...於是自己想了一些笨辦法.請看一下程式碼:
//瀏覽器特徵資訊
function BrowserInfo()
{
brower[0] = navigator.appName;
brower[7] = navigator.language;
if(brower[0] == "Netscape")
{
var browerInfo = navigator.userAgent;
brower[1] = browerInfo.substring(browerInfo.lastIndexOf(" ")+1,browerInfo.length);
brower[0] = brower[1].substring(0,brower[1].lastIndexOf("/"));
brower[1] = browerInfo.substring(browerInfo.lastIndexOf("/")+1,browerInfo.length);
brower[7] = navigator.language;
}
else if(brower[0] == "Microsoft Internet Explorer")
{
brower[1] = navigator.userAgent.split(";")[1];
brower[7] = navigator.userLanguage;
}
brower[2] = navigator.javaEnabled()?1:-1;
brower[3] = getFlash();
brower[4] = getOS();
if (self.screen) {
sr=screen.width+"x"+screen.height;
sc=screen.colorDepth+"-bit";
}
else if (self.java)
{
var j=java.awt.Toolkit.getDefaultToolkit();
var s=j.getScreenSize();
sr=s.width+"x"+s.height;
}
//解析度
brower[5] = sr;
//色深
brower[6] = sc;
//插件列表
brower[8] = getPlugin();
}
//-----------------------------------取得目前位址--------------------- --------
function getHref()
{
return document.location.href;
}
//---------------------cookie操作開始--------------------- -------------------------------------------------- ------------------------------------------
function setCookie(name, value)
//設定Cookie值
{
var expdate = new Date();
var argv = setCookie.arguments;
var argc = setCookie.arguments.length;
var expires = 15768000;
var path = (argc > 3) ? argv[3] : null;
var domain = (argc > 4) ? argv[4] : null;
var secure = (argc > 5) ? argv[5] : false;
if(expires!=null)
{
//設定過期時間24小時
expdate.setTime(uexp);
document.cookie = name + "=" + escape (value) +((expires == null) ? "" : ("; expires="+ expdate.toGMTString()))
+ ((path == null) ? "" : ("; path=" + path)) +((domain == null) ? "" : ("; domain=" + domain))
+ ((secure == true) ? "; secure=" : "");
}
}
function delCookie(name)
//刪除Cookie
{
var exp = new Date();
exp.setTime (exp.getTime() - 1);
var cval = getCookie (name);
document.cookie = name + "=" + cval + "; expires="+ exp.toGMTString();
}
//獲得Cookie的值
function getCookie(fname)
{
var name,value;
var cookies = new Object();
var beginning,middle,end;
beginning = 0;
while(beginning < document.cookie.length)
{
middle = document.cookie.indexOf("=",beginning);
end = document.cookie.indexOf(";",beginning);
if(end == -1)
{
end = document.cookie.length;
}
if((middle > end) || (middle == -1))
{
name = document.cookie.substring(beginning,end);
value = "";
}
else
{
name = document.cookie.substring(beginning,middle);
value = document.cookie.substring(middle+1,end);
}
if(name == fname)
{
return unescape(value);
}
beginning = end + 2;
}
}
//-----取得GUID的cookie是否存在取得----------------------------------- ----------------
function getCookieValue()
{
var guid = getCookie("GUID");
if(guid != null)
{
return guid;
}
else
{
return "noCookie";
}
}
//---------------------取得註冊用戶cookie---------------------- -----------------------
function getRegUserCookie()
{
return ;
}
//-----------------------------cookie 操作完畢---------------- -------------------------------------------------- ------------------------------------------
//------ ---------------------得作業系統-------------------------- -
function getOS()
{
var OSlist = new Array();
var OSName = new Array();
OSlist[0] = " Windows4.0"; OSName[0] = "Windows 95";
OSlist[1] = " Windows 98"; OSName[1] = "Windows 98";
OSlist[2] = " Windows NT 5.0"; OSName[2] = "Windows 2000";
OSlist[3] = " Windows NT 5.1"; OSName[3] = "Windows XP";
OSlist[4] = " Windows NT 5.2"; OSName[4] = "Windows Server 2003";
var ua = navigator.userAgent.split(";");
for(var i = 0; i < OSlist.length; i++)
{
if(ua[2] == OSlist[i])
return OSName[i];
}
return ua[2];
}
//取得插件
function getPlugin()
{
var plugin = "";
var ua = navigator.userAgent.split(";");
if(ua.length < 4)
return "";
for(var i = 4; i < ua.length; i++)
{
plugin += ua[i] + ",";
}
return plugin.substring(0,plugin.length-2);
}
需要說明的一點是GetResidentTime這個函數,google採用了img.load的方法加載了接收處理資訊頁面的,需要再伺服器端配置將後綴為.gif或你所取的其他形式的文件使用aspx的方式編譯運行.因為我原來考慮的是使用xmlHttp非同步呼叫.但是頁面退出的時候有時候不執行.所以就棄用了.代碼如下: function GetResidentTime()
{
pageClose = new Date();
minutes = (pageClose.getMinutes() - pageOpen.getMinutes());
if(minutes < 0)
{
minutes = minutes + 60;
}
seconds = (pageClose.getSeconds() - pageOpen.getSeconds());
if(seconds < 0){ seconds += 60;}
time = (seconds + (minutes * 60));
//------------------------修改此處為接收連結位址XML 非同步傳輸-------------- ----------------------
// var xmlHttp = createXMLHttpRequest();
// xmlHttp.open("POSt", reqURL + firstvisit.aspx?" + StrPara(), false);
// xmlHttp.send(null);
//----------------------------圖片形式傳遞----------------- --------------------------------------
if(isReturn() == false)
{
var i = new Image(1,1);
i.src = reqURL + "firstVisit.aspx?" + StrPara() + "&GUID=" + GUID;
i.onload = function() {LoadVoid();}
//進入頁面的信息
if(getCookieValue("GUID") == "noCookie"){return ;}
i.src = reqURL + "pageView.gif?" + pageView() + "&st=" + time;
i.onload=function() {LoadVoid();}
}
else
{
var i=new Image(1,1);
i.src = reqURL + "pageView.gif?" + pageView() + "&st=" + time;
i.onload=function() {LoadVoid();}
}
} 最後就是呼叫了。我使用了window.onunload = GetResidentTime
傳遞的參數大家可以列印出來看一下.應該可以明白其意思.
剩下的就是伺服器端的處理了,在伺服器端處理其實相當簡單.取得request的值,驗證並保存入資料庫.現在有了資料,分析的事情就由用戶按照自己的要求來處理了..補充一句,ip位址是由伺服器端來取得保存的.
使用的時候記得一定將其放到伺服器端,然後使用<javascript language="javascript" type="text/javascript" src=伺服器位址+路徑+"statistics.js"> </script> 附上完整的程式碼http://blacksoul.cnblogs.com/archive/2006/05/19/404563.html