Friday, July 13, 2007

A quick look at the Google Analytics Urchin Module

pencil icon, that"s clickable to start editing the post

In Party cookie - GA a virtual first party i saw for my self that GA do use first-party cookies. In this post I'll have a quick look at the javascript that does this, which is loaded from http://www.google-analytics.com/urchin.js and started by a call to urchinTracker();.

The JavaScript file consists basically of three sections

  • Variable declarations that can be customized
  • Variable declarations that can't be customized
  • Function definitions
where the function definition takes up approximately 90% of the LOCs. I'll happily restate that I'm no expert on JavaScript, in fact I avoid it if possible and therefore have read og even written much of it. I guess the code in the file has been optimized for minimum size (and probably also performance), and therefore variable declarations and functions do not use meaningful names, so it looks a lot like old school C (as old as my schooling goes), which makes it harder to read and understand. A quick look at the function prototypes (done with grep function urchin.js | grep -v -E "linker|typeof|onload" | sort | cut -f1-2 -d' ') gives 28 functions, that sorted goes as:

Not much help here, so there's only the (uncommented) code left. Here I've pretty printed it using the online tool http://elfz.laacz.lv/beautify/, which does a descent job, except for moving end of line comments to the next line (watch out for that in the start). I've looked for a JavaScript editor for Eclipse, that would give me pretty printing but I haven't found one yet, which surprises me since there must be a lot of people doing javascript, but it must be in other tools. Here comes the all most 1000 lines long pretty printed version:

    1 //-- Google Analytics Urchin Module
    2 //-- Copyright 2007 Google, All Rights Reserved.
    3 //-- Urchin On Demand Settings ONLY

Variables that can be customized

    4 var _uacct = "";
    5 // set up the Urchin Account
    6 var _userv = 1;
    7 // service mode (0=local,1=remote,2=both)
    8 //-- UTM User Settings
    9 var _ufsc = 1;
   10 // set client info flag (1=on|0=off)
   11 var _udn = "auto";
   12 // (auto|none|domain) set the domain name for cookies
   13 var _uhash = "on";
   14 // (on|off) unique domain hash for cookies
   15 var _utimeout = "1800";
   16 // set the inactive session timeout in seconds
   17 var _ugifpath = "/__utm.gif";
   18 // set the web path to the __utm.gif file
   19 var _utsp = "|";
   20 // transaction field separator
   21 var _uflash = 1;
   22 // set flash version detect option (1=on|0=off)
   23 var _utitle = 1;
   24 // set the document title detect option (1=on|0=off)
   25 var _ulink = 0;
   26 // enable linker functionality (1=on|0=off)
   27 var _uanchor = 0;
   28 // enable use of anchors for campaign (1=on|0=off)
   29 var _utcp = "/";
   30 // the cookie path for tracking
   31 var _usample = 100;
   32 // The sampling % of visitors to track (1-100).
   33 //-- UTM Campaign Tracking Settings
   34 var _uctm = 1;
   35 // set campaign tracking module (1=on|0=off)
   36 var _ucto = "15768000";
   37 // set timeout in seconds (6 month default)
   38 var _uccn = "utm_campaign";
   39 // name
   40 var _ucmd = "utm_medium";
   41 // medium (cpc|cpm|link|email|organic)
   42 var _ucsr = "utm_source";
   43 // source
   44 var _uctr = "utm_term";
   45 // term/keyword
   46 var _ucct = "utm_content";
   47 // content
   48 var _ucid = "utm_id";
   49 // id number
   50 var _ucno = "utm_nooverride";
   51 // don't override
   52 //-- Auto/Organic Sources and Keywords
   53 var _uOsr = new Array();
   54 var _uOkw = new Array();
   55 _uOsr[0] = "google";
   56 _uOkw[0] = "q";
   57 _uOsr[1] = "yahoo";
   58 _uOkw[1] = "p";
   59 _uOsr[2] = "msn";
   60 _uOkw[2] = "q";
   61 _uOsr[3] = "aol";
   62 _uOkw[3] = "query";
   63 _uOsr[4] = "aol";
   64 _uOkw[4] = "encquery";
   65 _uOsr[5] = "lycos";
   66 _uOkw[5] = "query";
   67 _uOsr[6] = "ask";
   68 _uOkw[6] = "q";
   69 _uOsr[7] = "altavista";
   70 _uOkw[7] = "q";
   71 _uOsr[8] = "netscape";
   72 _uOkw[8] = "s";
   73 _uOsr[9] = "cnn";
   74 _uOkw[9] = "query";
   75 _uOsr[10] = "looksmart";
   76 _uOkw[10] = "qt";
   77 _uOsr[11] = "about";
   78 _uOkw[11] = "terms";
   79 _uOsr[12] = "mamma";
   80 _uOkw[12] = "query";
   81 _uOsr[13] = "alltheweb";
   82 _uOkw[13] = "q";
   83 _uOsr[14] = "gigablast";
   84 _uOkw[14] = "q";
   85 _uOsr[15] = "voila";
   86 _uOkw[15] = "rdata";
   87 _uOsr[16] = "virgilio";
   88 _uOkw[16] = "qs";
   89 _uOsr[17] = "live";
   90 _uOkw[17] = "q";
   91 _uOsr[18] = "baidu";
   92 _uOkw[18] = "wd";
   93 _uOsr[19] = "alice";
   94 _uOkw[19] = "qs";
   95 _uOsr[20] = "seznam";
   96 _uOkw[20] = "w";
   97 _uOsr[21] = "yandex";
   98 _uOkw[21] = "text";
   99 _uOsr[22] = "najdi";
  100 _uOkw[22] = "q";
  101 _uOsr[23] = "aol";
  102 _uOkw[23] = "q";
  103 _uOsr[24] = "club-internet";
  104 _uOkw[24] = "q";
  105 _uOsr[25] = "mama";
  106 _uOkw[25] = "query";
  107 _uOsr[26] = "seznam";
  108 _uOkw[26] = "q";
  109 _uOsr[27] = "search";
  110 _uOkw[27] = "q";
  111 
  112 //-- Auto/Organic Keywords to Ignore
  113 var _uOno = new Array();
  114 //_uOno[0]="urchin";
  115 //_uOno[1]="urchin.com";
  116 //_uOno[2]="www.urchin.com";
  117 //-- Referral domains to Ignore
  118 var _uRno = new Array();
  119 //_uRno[0]=".urchin.com";

then some variables not to be customized



  120 //-- **** Don't modify below this point ***
  121 var _uff,
  122 _udh,
  123 _udt,
  124 _ubl = 0,
  125 _udo = "",
  126 _uu,
  127 _ufns = 0,
  128 _uns = 0,
  129 _ur = "-",
  130 _ufno = 0,
  131 _ust = 0,
  132 _ubd = document,
  133 _udl = _ubd.location,
  134 _udlh = "",
  135 _uwv = "1";
  136 var _ugifpath2 = "http://www.google-analytics.com/__utm.gif";
  137 if (_udl.hash)
  138     _udlh = _udl.href.substring(_udl.href.indexOf('#'));
  139 if (_udl.protocol == "https:")
  140     _ugifpath2 = "https://ssl.google-analytics.com/__utm.gif";
  141 if ( ! _utcp || _utcp == "")
  142     _utcp = "/";

now comes the functions

  143 function urchinTracker(page) {
  144     if (_udl.protocol == "file:")
  145         return;
  146     if (_uff && ( ! page || page == ""))
  147         return;
  148     var a,
  149     b,
  150     c,
  151     xx,
  152     v,
  153     z,
  154     k,
  155     x = "",
  156     s = "",
  157     f = 0;
  158     var nx = " expires=Sun, 18 Jan 2038 00:00:00 GMT;";
  159     var dc = _ubd.cookie;
  160     _udh = _uDomain();
  161     if ( ! _uVG())
  162         return;
  163     _uu = Math.round(Math.random() * 2147483647);
  164     _udt = new Date();
  165     _ust = Math.round(_udt.getTime() / 1000);
  166     a = dc.indexOf("__utma=" + _udh);
  167     b = dc.indexOf("__utmb=" + _udh);
  168     c = dc.indexOf("__utmc=" + _udh);
  169     if (_udn && _udn != "") {
  170         _udo = " domain=" + _udn + ";";
  171     }
  172     if (_utimeout && _utimeout != "") {
  173         x = new Date(_udt.getTime() + (_utimeout * 1000));
  174         x = " expires=" + x.toGMTString() + ";";
  175     }
  176     if (_ulink) {
  177         if (_uanchor && _udlh && _udlh != "")
  178             s = _udlh + "&";
  179         s += _udl.search;
  180         if (s && s != "" && s.indexOf("__utma=") >= 0) {
  181             if ( ! (_uIN(a = _uGC(s, "__utma=", "&"))))
  182                 a = "-";
  183             if ( ! (_uIN(b = _uGC(s, "__utmb=", "&"))))
  184                 b = "-";
  185             if ( ! (_uIN(c = _uGC(s, "__utmc=", "&"))))
  186                 c = "-";
  187             v = _uGC(s, "__utmv=", "&");
  188             z = _uGC(s, "__utmz=", "&");
  189             k = _uGC(s, "__utmk=", "&");
  190             xx = _uGC(s, "__utmx=", "&");
  191             if ((k * 1) != ((_uHash(a + b + c + xx + z + v) * 1) + (_udh * 1))) {
  192                 _ubl = 1;
  193                 a = "-";
  194                 b = "-";
  195                 c = "-";
  196                 xx = "-";
  197                 z = "-";
  198                 v = "-";
  199             }
  200             if (a != "-" && b != "-" && c != "-")
  201                 f = 1;
  202             else if (a != "-")
  203                 f = 2;
  204         }
  205     }
  206     if (f == 1) {
  207         _ubd.cookie = "__utma=" + a + "; path=" + _utcp + ";" + nx + _udo;
  208         _ubd.cookie = "__utmb=" + b + "; path=" + _utcp + ";" + x + _udo;
  209         _ubd.cookie = "__utmc=" + c + "; path=" + _utcp + ";" + _udo;
  210     } else if (f == 2) {
  211         a = _uFixA(s, "&", _ust);
  212         _ubd.cookie = "__utma=" + a + "; path=" + _utcp + ";" + nx + _udo;
  213         _ubd.cookie = "__utmb=" + _udh + "; path=" + _utcp + ";" + x + _udo;
  214         _ubd.cookie = "__utmc=" + _udh + "; path=" + _utcp + ";" + _udo;
  215         _ufns = 1;
  216     } else if (a >= 0 && b >= 0 && c >= 0) {
  217         _ubd.cookie = "__utmb=" + _udh + "; path=" + _utcp + ";" + x + _udo;
  218     } else {
  219         if (a >= 0)
  220             a = _uFixA(_ubd.cookie, ";", _ust);
  221         else a = _udh + "." + _uu + "." + _ust + "." + _ust + "." + _ust + ".1";
  222         _ubd.cookie = "__utma=" + a + "; path=" + _utcp + ";" + nx + _udo;
  223         _ubd.cookie = "__utmb=" + _udh + "; path=" + _utcp + ";" + x + _udo;
  224         _ubd.cookie = "__utmc=" + _udh + "; path=" + _utcp + ";" + _udo;
  225         _ufns = 1;
  226     }
  227     if (_ulink && xx && xx != "" && xx != "-") {
  228         xx = _uUES(xx);
  229         if (xx.indexOf(";") ==- 1)
  230             _ubd.cookie = "__utmx=" + xx + "; path=" + _utcp + ";" + nx + _udo;
  231     }
  232     if (_ulink && v && v != "" && v != "-") {
  233         v = _uUES(v);
  234         if (v.indexOf(";") ==- 1)
  235             _ubd.cookie = "__utmv=" + v + "; path=" + _utcp + ";" + nx + _udo;
  236     }
  237     _uInfo(page);
  238     _ufns = 0;
  239     _ufno = 0;
  240     if ( ! page || page == "")
  241         _uff = 1;
  242 }

That was the 100 lines long main method. Now follows:

  243 function _uInfo(page) {
  244     var p,
  245     s = "",
  246     dm = "",
  247     pg = _udl.pathname + _udl.search;
  248     if (page && page != "")
  249         pg = _uES(page, 1);
  250     _ur = _ubd.referrer;
  251     if ( ! _ur || _ur == "") {
  252         _ur = "-";
  253     } else {
  254         dm = _ubd.domain;
  255         if (_utcp && _utcp != "/")
  256             dm += _utcp;
  257         p = _ur.indexOf(dm);

  258         if ((p >= 0) && (p <= 8)) {
  259             _ur = "0";
  260         }
  261         if (_ur.indexOf("[") == 0 && _ur.lastIndexOf("]") == (_ur.length - 1)) {
  262             _ur = "-";
  263         }
  264     }

  265     s += "&utmn=" + _uu;
  266     if (_ufsc)
  267         s += _uBInfo();
  268     if (_uctm)
  269         s += _uCInfo();
  270     if (_utitle && _ubd.title && _ubd.title != "")

  271         s += "&utmdt=" + _uES(_ubd.title);

  272     if (_udl.hostname && _udl.hostname != "")
  273         s += "&utmhn=" + _uES(_udl.hostname);
  274     s += "&utmr=" + _ur;
  275     s += "&utmp=" + pg;
  276     if ((_userv == 0 || _userv == 2) && _uSP()) {

  277         var i = new Image(1, 1);

  278         i.src = _ugifpath + "?" + "utmwv=" + _uwv + s;

  279         i.onload = function() {
  280             _uVoid();

  281         }
  282     }
  283     if ((_userv == 1 || _userv == 2) && _uSP()) {

  284         var i2 = new Image(1, 1);

  285         i2.src = _ugifpath2 + "?" + "utmwv=" + _uwv + s + "&utmac=" + _uacct + "&utmcc=" + _uGCS();
  286         i2.onload = function() {
  287             _uVoid();
  288         }
  289     }
  290     return;
  291 }


  292 function _uVoid() {
  293     return;
  294 }


  295 function _uCInfo() {
  296     if ( ! _ucto || _ucto == "") {
  297         _ucto = "15768000";
  298     }
  299     if ( ! _uVG())
  300         return;
  301     var c = "",
  302     t = "-",
  303     t2 = "-",
  304     t3 = "-",
  305     o = 0,
  306     cs = 0,
  307     cn = 0,
  308     i = 0,
  309     z = "-",
  310     s = "";
  311     if (_uanchor && _udlh && _udlh != "")
  312         s = _udlh + "&";
  313     s += _udl.search;
  314     var x = new Date(_udt.getTime() + (_ucto * 1000));
  315     var dc = _ubd.cookie;
  316     x = " expires=" + x.toGMTString() + ";";
  317     if (_ulink && !_ubl) {
  318         z = _uUES(_uGC(s, "__utmz=", "&"));
  319         if (z != "-" && z.indexOf(";") ==- 1) {
  320             _ubd.cookie = "__utmz=" + z + "; path=" + _utcp + ";" + x + _udo;
  321             return "";
  322         }
  323     }
  324     z = dc.indexOf("__utmz=" + _udh);
  325     if (z >- 1) {
  326         z = _uGC(dc, "__utmz=" + _udh, ";");
  327     } else {
  328         z = "-";
  329     }
  330     t = _uGC(s, _ucid + "=", "&");
  331     t2 = _uGC(s, _ucsr + "=", "&");
  332     t3 = _uGC(s, "gclid=", "&");
  333     if ((t != "-" && t != "") || (t2 != "-" && t2 != "") || (t3 != "-" && t3 != "")) {
  334         if (t != "-" && t != "")
  335             c += "utmcid=" + _uEC(t);
  336         if (t2 != "-" && t2 != "") {
  337             if (c != "")
  338                 c += "|";
  339             c += "utmcsr=" + _uEC(t2);
  340         }
  341         if (t3 != "-" && t3 != "") {
  342             if (c != "")
  343                 c += "|";
  344             c += "utmgclid=" + _uEC(t3);
  345         }
  346         t = _uGC(s, _uccn + "=", "&");
  347         if (t != "-" && t != "")
  348             c += "|utmccn=" + _uEC(t);
  349         else c += "|utmccn=(not+set)";
  350         t = _uGC(s, _ucmd + "=", "&");
  351         if (t != "-" && t != "")
  352             c += "|utmcmd=" + _uEC(t);
  353         else c += "|utmcmd=(not+set)";
  354         t = _uGC(s, _uctr + "=", "&");
  355         if (t != "-" && t != "")
  356             c += "|utmctr=" + _uEC(t);
  357         else {
  358             t = _uOrg(1);
  359             if (t != "-" && t != "")
  360                 c += "|utmctr=" + _uEC(t);
  361         }
  362         t = _uGC(s, _ucct + "=", "&");
  363         if (t != "-" && t != "")
  364             c += "|utmcct=" + _uEC(t);
  365         t = _uGC(s, _ucno + "=", "&");
  366         if (t == "1")
  367             o = 1;
  368         if (z != "-" && o == 1)
  369             return "";
  370     }
  371     if (c == "-" || c == "") {
  372         c = _uOrg();
  373         if (z != "-" && _ufno == 1)

  374             return "";
  375     }
  376     if (c == "-" || c == "") {

  377         if (_ufns == 1)
  378             c = _uRef();

  379         if (z != "-" && _ufno == 1)

  380             return "";
  381     }
  382     if (c == "-" || c == "") {

  383         if (z == "-" && _ufns == 1) {

  384             c = "utmccn=(direct)|utmcsr=(direct)|utmcmd=(none)";
  385         }
  386         if (c == "-" || c == "")

  387             return "";
  388     }
  389     if (z != "-") {

  390         i = z.indexOf(".");
  391         if (i >- 1)

  392             i = z.indexOf(".", i + 1);

  393         if (i >- 1)
  394             i = z.indexOf(".", i + 1);
  395         if (i >- 1)
  396             i = z.indexOf(".", i + 1);
  397         t = z.substring(i + 1, z.length);
  398         if (t.toLowerCase() == c.toLowerCase())
  399             cs = 1;
  400         t = z.substring(0, i);
  401         if ((i = t.lastIndexOf(".")) > -1) {
  402             t = t.substring(i + 1, t.length);
  403             cn = (t * 1);
  404         }
  405     }
  406     if (cs == 0 || _ufns == 1) {
  407         t = _uGC(dc, "__utma=" + _udh, ";");
  408         if ((i = t.lastIndexOf(".")) > 9) {
  409             _uns = t.substring(i + 1, t.length);
  410             _uns = (_uns * 1);
  411         }
  412         cn ++ ;
  413         if (_uns == 0)
  414             _uns = 1;
  415         _ubd.cookie = "__utmz=" + _udh + "." + _ust + "." + _uns + "." + cn + "." + c + "; path=" + _utcp + "; " + x + _udo;
  416     }
  417     if (cs == 0 || _ufns == 1)
  418         return "&utmcn=1";
  419     else return "&utmcr=1";
  420 }

  421 function _uRef() {
  422     if (_ur == "0" || _ur == "" || _ur == "-")
  423         return "";
  424     var i = 0,
  425     h,
  426     k,
  427     n;
  428     if ((i = _ur.indexOf("://")) < 0)
  429         return "";
  430     h = _ur.substring(i + 3, _ur.length);
  431     if (h.indexOf("/") > -1) {
  432         k = h.substring(h.indexOf("/"), h.length);
  433         if (k.indexOf("?") > -1)
  434             k = k.substring(0, k.indexOf("?"));
  435         h = h.substring(0, h.indexOf("/"));
  436     }
  437     h = h.toLowerCase();
  438     n = h;
  439     if ((i = n.indexOf(":")) > -1)
  440         n = n.substring(0, i);
  441     for (var ii = 0; ii < _uRno.length; ii ++ ) {
  442         if ((i = n.indexOf(_uRno[ii].toLowerCase())) > -1 && n.length == (i + _uRno[ii].length)) {
  443             _ufno = 1;
  444             break;
  445         }
  446     }
  447     if (h.indexOf("www.") == 0)
  448         h = h.substring(4, h.length);
  449     return "utmccn=(referral)|utmcsr=" + _uEC(h) + "|" + "utmcct=" + _uEC(k) + "|utmcmd=referral";
  450 }


  451 function _uOrg(t) {
  452     if (_ur == "0" || _ur == "" || _ur == "-")
  453         return "";
  454     var i = 0,
  455     h,
  456     k;
  457     if ((i = _ur.indexOf("://")) < 0)
  458         return "";
  459     h = _ur.substring(i + 3, _ur.length);
  460     if (h.indexOf("/") > -1) {
  461         h = h.substring(0, h.indexOf("/"));

  462     }
  463     for (var ii = 0; ii < _uOsr.length; ii ++ ) {

  464         if (h.toLowerCase().indexOf(_uOsr[ii].toLowerCase()) > -1) {

  465             if ((i = _ur.indexOf("?" + _uOkw[ii] + "=")) > -1 || (i = _ur.indexOf("&" + _uOkw[ii] + "=")) > -1) {

  466                 k = _ur.substring(i + _uOkw[ii].length + 2, _ur.length);

  467                 if ((i = k.indexOf("&")) > -1)

  468                     k = k.substring(0, i);
  469                 for (var yy = 0; yy < _uOno.length; yy ++ ) {

  470                     if (_uOno[yy].toLowerCase() == k.toLowerCase()) {

  471                         _ufno = 1;
  472                         break;
  473                     }

  474                 }
  475                 if (t)
  476                     return _uEC(k);

  477                 else return "utmccn=(organic)|utmcsr=" + _uEC(_uOsr[ii]) + "|" + "utmctr=" + _uEC(k) + "|utmcmd=organic";

  478             }
  479         }
  480     }
  481     return "";

  482 }


  483 function _uBInfo() {
  484     var sr = "-",
  485     sc = "-",
  486     ul = "-",
  487     fl = "-",
  488     cs = "-",
  489     je = 1;
  490     var n = navigator;
  491     if (self.screen) {
  492         sr = screen.width + "x" + screen.height;
  493         sc = screen.colorDepth + "-bit";
  494     } else if (self.java) {
  495         var j = java.awt.Toolkit.getDefaultToolkit();
  496         var s = j.getScreenSize();
  497         sr = s.width + "x" + s.height;
  498     }
  499     if (n.language) {
  500         ul = n.language.toLowerCase();
  501     } else if (n.browserLanguage) {
  502         ul = n.browserLanguage.toLowerCase();
  503     }
  504     je = n.javaEnabled() ? 1: 0;
  505     if (_uflash)
  506         fl = _uFlash();
  507     if (_ubd.characterSet)
  508         cs = _uES(_ubd.characterSet);
  509     else if (_ubd.charset)
  510         cs = _uES(_ubd.charset);
  511     return "&utmcs=" + cs + "&utmsr=" + sr + "&utmsc=" + sc + "&utmul=" + ul + "&utmje=" + je + "&utmfl=" + fl;
  512 }


  513 function __utmSetTrans() {
  514     var e;
  515     if (_ubd.getElementById)
  516         e = _ubd.getElementById("utmtrans");
  517     else if (_ubd.utmform && _ubd.utmform.utmtrans)
  518         e = _ubd.utmform.utmtrans;
  519     if ( ! e)
  520         return;
  521     var l = e.value.split("UTM:");
  522     var i,
  523     i2,
  524     c;
  525     if (_userv == 0 || _userv == 2)
  526         i = new Array();
  527     if (_userv == 1 || _userv == 2) {
  528         i2 = new Array();
  529         c = _uGCS();
  530     }
  531 
  532     for (var ii = 0; ii < l.length; ii ++ ) {
  533         l[ii] = _uTrim(l[ii]);
  534         if (l[ii].charAt(0) != 'T' && l[ii].charAt(0) != 'I')
  535             continue;
  536         var r = Math.round(Math.random() * 2147483647);

  537         if ( ! _utsp || _utsp == "")
  538             _utsp = "|";

  539         var f = l[ii].split(_utsp),

  540         s = "";
  541         if (f[0].charAt(0) == 'T') {

  542             s = "&utmt=tran" + "&utmn=" + r;

  543             f[1] = _uTrim(f[1]);
  544             if (f[1] && f[1] != "")

  545                 s += "&utmtid=" + _uES(f[1]);

  546             f[2] = _uTrim(f[2]);
  547             if (f[2] && f[2] != "")

  548                 s += "&utmtst=" + _uES(f[2]);

  549             f[3] = _uTrim(f[3]);
  550             if (f[3] && f[3] != "")

  551                 s += "&utmtto=" + _uES(f[3]);

  552             f[4] = _uTrim(f[4]);
  553             if (f[4] && f[4] != "")

  554                 s += "&utmttx=" + _uES(f[4]);

  555             f[5] = _uTrim(f[5]);
  556             if (f[5] && f[5] != "")

  557                 s += "&utmtsp=" + _uES(f[5]);

  558             f[6] = _uTrim(f[6]);
  559             if (f[6] && f[6] != "")

  560                 s += "&utmtci=" + _uES(f[6]);

  561             f[7] = _uTrim(f[7]);
  562             if (f[7] && f[7] != "")

  563                 s += "&utmtrg=" + _uES(f[7]);

  564             f[8] = _uTrim(f[8]);
  565             if (f[8] && f[8] != "")

  566                 s += "&utmtco=" + _uES(f[8]);

  567         } else {
  568             s = "&utmt=item" + "&utmn=" + r;

  569             f[1] = _uTrim(f[1]);
  570             if (f[1] && f[1] != "")

  571                 s += "&utmtid=" + _uES(f[1]);

  572             f[2] = _uTrim(f[2]);
  573             if (f[2] && f[2] != "")

  574                 s += "&utmipc=" + _uES(f[2]);

  575             f[3] = _uTrim(f[3]);
  576             if (f[3] && f[3] != "")

  577                 s += "&utmipn=" + _uES(f[3]);

  578             f[4] = _uTrim(f[4]);
  579             if (f[4] && f[4] != "")

  580                 s += "&utmiva=" + _uES(f[4]);

  581             f[5] = _uTrim(f[5]);
  582             if (f[5] && f[5] != "")

  583                 s += "&utmipr=" + _uES(f[5]);

  584             f[6] = _uTrim(f[6]);
  585             if (f[6] && f[6] != "")

  586                 s += "&utmiqt=" + _uES(f[6]);

  587         }
  588         if ((_userv == 0 || _userv == 2) && _uSP()) {

  589             i[ii] = new Image(1, 1);

  590             i[ii].src = _ugifpath + "?" + "utmwv=" + _uwv + s;

  591             i[ii].onload = function() {
  592                 _uVoid();

  593             }
  594         }
  595         if ((_userv == 1 || _userv == 2) && _uSP()) {

  596             i2[ii] = new Image(1, 1);

  597             i2[ii].src = _ugifpath2 + "?" + "utmwv=" + _uwv + s + "&utmac=" + _uacct + "&utmcc=" + c;

  598             i2[ii].onload = function() {
  599                 _uVoid();

  600             }
  601         }
  602     }
  603     return;

  604 }


  605 function _uFlash() {
  606     var f = "-",
  607     n = navigator;
  608     if (n.plugins && n.plugins.length) {
  609         for (var ii = 0; ii < n.plugins.length; ii ++ ) {
  610             if (n.plugins[ii].name.indexOf('Shockwave Flash') !=- 1) {
  611                 f = n.plugins[ii].description.split('Shockwave Flash ')[1];
  612                 break;
  613             }
  614         }
  615     } else if (window.ActiveXObject) {
  616         for (var ii = 10; ii >= 2; ii -- ) {
  617             try {
  618                 var fl = eval("new ActiveXObject('ShockwaveFlash.ShockwaveFlash." + ii + "');");
  619                 if (fl) {
  620                     f = ii + '.0';
  621                     break;
  622                 }
  623             }
  624             catch(e) {}
  625         }
  626     }
  627     return f;
  628 }
  629 function __utmLinker(l, h) {
  630     if ( ! _ulink)
  631         return;
  632     var p,
  633     k,
  634     a = "-",
  635     b = "-",
  636     c = "-",
  637     x = "-",
  638     z = "-",
  639     v = "-";
  640     var dc = _ubd.cookie;
  641     if ( ! l || l == "")
  642         return;
  643     var iq = l.indexOf("?");
  644     var ih = l.indexOf("#");
  645     if (dc) {
  646         a = _uES(_uGC(dc, "__utma=" + _udh, ";"));
  647         b = _uES(_uGC(dc, "__utmb=" + _udh, ";"));
  648         c = _uES(_uGC(dc, "__utmc=" + _udh, ";"));
  649         x = _uES(_uGC(dc, "__utmx=" + _udh, ";"));
  650         z = _uES(_uGC(dc, "__utmz=" + _udh, ";"));
  651         v = _uES(_uGC(dc, "__utmv=" + _udh, ";"));
  652         k = (_uHash(a + b + c + x + z + v) * 1) + (_udh * 1);
  653         p = "__utma=" + a + "&__utmb=" + b + "&__utmc=" + c + "&__utmx=" + x + "&__utmz=" + z + "&__utmv=" + v + "&__utmk=" + k;
  654     }
  655     if (p) {
  656         if (h && ih >- 1)
  657             return;
  658         if (h) {
  659             _udl.href = l + "#" + p;

  660         } else {
  661             if (iq ==- 1 && ih ==- 1)

  662                 _udl.href = l + "?" + p;

  663             else if (ih ==- 1)
  664                 _udl.href = l + "&" + p;

  665             else if (iq ==- 1)
  666                 _udl.href = l.substring(0, ih - 1) + "?" + p + l.substring(ih);

  667             else _udl.href = l.substring(0, ih - 1) + "&" + p + l.substring(ih);
  668         }
  669     } else {
  670         _udl.href = l;
  671     }
  672 }


  673 function __utmLinkPost(f, h) {
  674     if ( ! _ulink)
  675         return;
  676     var p,
  677     k,
  678     a = "-",
  679     b = "-",
  680     c = "-",
  681     x = "-",
  682     z = "-",
  683     v = "-";
  684     var dc = _ubd.cookie;
  685     if ( ! f || !f.action)
  686         return;
  687     var iq = f.action.indexOf("?");

  688     var ih = f.action.indexOf("#");

  689     if (dc) {
  690         a = _uES(_uGC(dc, "__utma=" + _udh, ";"));

  691         b = _uES(_uGC(dc, "__utmb=" + _udh, ";"));

  692         c = _uES(_uGC(dc, "__utmc=" + _udh, ";"));

  693         x = _uES(_uGC(dc, "__utmx=" + _udh, ";"));

  694         z = _uES(_uGC(dc, "__utmz=" + _udh, ";"));

  695         v = _uES(_uGC(dc, "__utmv=" + _udh, ";"));

  696         k = (_uHash(a + b + c + x + z + v) * 1) + (_udh * 1);

  697         p = "__utma=" + a + "&__utmb=" + b + "&__utmc=" + c + "&__utmx=" + x + "&__utmz=" + z + "&__utmv=" + v + "&__utmk=" + k;

  698     }
  699     if (p) {
  700         if (h && ih >- 1)

  701             return;
  702         if (h) {
  703             f.action += "#" + p;

  704         } else {
  705             if (iq ==- 1 && ih ==- 1)

  706                 f.action += "?" + p;
  707             else if (ih ==- 1)

  708                 f.action += "&" + p;
  709             else if (iq ==- 1)

  710                 f.action = f.action.substring(0, ih - 1) + "?" + p + f.action.substring(ih);

  711             else f.action = f.action.substring(0, ih - 1) + "&" + p + f.action.substring(ih);

  712         }
  713     }
  714     return;
  715 }


  716 function __utmSetVar(v) {
  717     if ( ! v || v == "")
  718         return;
  719     if ( ! _udo || _udo == "") {
  720         _udh = _uDomain();
  721         if (_udn && _udn != "") {
  722             _udo = " domain=" + _udn + ";";
  723         }
  724     }
  725     if ( ! _uVG())
  726         return;
  727     var r = Math.round(Math.random() * 2147483647);
  728     _ubd.cookie = "__utmv=" + _udh + "." + _uES(v) + "; path=" + _utcp + "; expires=Sun, 18 Jan 2038 00:00:00 GMT;" + _udo;

  729     var s = "&utmt=var&utmn=" + r;
  730     if ((_userv == 0 || _userv == 2) && _uSP()) {

  731         var i = new Image(1, 1);

  732         i.src = _ugifpath + "?" + "utmwv=" + _uwv + s;

  733         i.onload = function() {
  734             _uVoid();

  735         }
  736     }
  737     if ((_userv == 1 || _userv == 2) && _uSP()) {

  738         var i2 = new Image(1, 1);

  739         i2.src = _ugifpath2 + "?" + "utmwv=" + _uwv + s + "&utmac=" + _uacct + "&utmcc=" + _uGCS();
  740         i2.onload = function() {
  741             _uVoid();
  742         }
  743     }
  744 }


  745 function _uGCS() {
  746     var t,
  747     c = "",
  748     dc = _ubd.cookie;
  749     if ((t = _uGC(dc, "__utma=" + _udh, ";")) != "-")
  750         c += _uES("__utma=" + t + ";+");
  751     if ((t = _uGC(dc, "__utmb=" + _udh, ";")) != "-")
  752         c += _uES("__utmb=" + t + ";+");
  753     if ((t = _uGC(dc, "__utmc=" + _udh, ";")) != "-")
  754         c += _uES("__utmc=" + t + ";+");
  755     if ((t = _uGC(dc, "__utmx=" + _udh, ";")) != "-")
  756         c += _uES("__utmx=" + t + ";+");
  757     if ((t = _uGC(dc, "__utmz=" + _udh, ";")) != "-")

  758         c += _uES("__utmz=" + t + ";+");

  759     if ((t = _uGC(dc, "__utmv=" + _udh, ";")) != "-")

  760         c += _uES("__utmv=" + t + ";");

  761     if (c.charAt(c.length - 1) == "+")

  762         c = c.substring(0, c.length - 1);

  763     return c;
  764 }


  765 function _uGC(l, n, s) {
  766     if ( ! l || l == "" || !n || n == "" || !s || s == "")
  767         return "-";
  768     var i,
  769     i2,
  770     i3,
  771     c = "-";
  772     i = l.indexOf(n);
  773     i3 = n.indexOf("=") + 1;
  774     if (i > -1) {
  775         i2 = l.indexOf(s, i);
  776         if (i2 < 0) {

  777             i2 = l.length;
  778         }
  779         c = l.substring((i + i3), i2);
  780     }
  781     return c;
  782 }


  783 function _uDomain() {
  784     if ( ! _udn || _udn == "" || _udn == "none") {
  785         _udn = "";
  786         return 1;
  787     }
  788     if (_udn == "auto") {
  789         var d = _ubd.domain;
  790         if (d.substring(0, 4) == "www.") {
  791             d = d.substring(4, d.length);
  792         }
  793         _udn = d;
  794     }
  795     if (_uhash == "off")
  796         return 1;
  797     return _uHash(_udn);
  798 }


  799 function _uHash(d) {
  800     if ( ! d || d == "")
  801         return 1;
  802     var h = 0,
  803     g = 0;
  804     for (var i = d.length - 1; i >= 0; i -- ) {
  805         var c = parseInt(d.charCodeAt(i));
  806         h = ((h << 6) & 0xfffffff) + c + (c << 14);
  807         if ((g = h & 0xfe00000) != 0)
  808             h = (h ^ (g >> 21));
  809     }
  810     return h;
  811 }


  812 function _uFixA(c, s, t) {
  813     if ( ! c || c == "" || !s || s == "" || !t || t == "")
  814         return "-";
  815     var a = _uGC(c, "__utma=" + _udh, s);
  816     var lt = 0,
  817     i = 0;
  818     if ((i = a.lastIndexOf(".")) > 9) {
  819         _uns = a.substring(i + 1, a.length);
  820         _uns = (_uns * 1) + 1;
  821         a = a.substring(0, i);
  822         if ((i = a.lastIndexOf(".")) > 7) {
  823             lt = a.substring(i + 1, a.length);
  824             a = a.substring(0, i);
  825         }
  826         if ((i = a.lastIndexOf(".")) > 5) {
  827             a = a.substring(0, i);
  828         }
  829         a += "." + lt + "." + t + "." + _uns;
  830     }
  831     return a;
  832 }


  833 function _uTrim(s) {
  834     if ( ! s || s == "")
  835         return "";
  836     while ((s.charAt(0) == ' ') || (s.charAt(0) == '\n') || (s.charAt(0, 1) == '\r'))
  837         s = s.substring(1, s.length);
  838     while ((s.charAt(s.length - 1) == ' ') || (s.charAt(s.length - 1) == '\n') || (s.charAt(s.length - 1) == '\r'))
  839         s = s.substring(0, s.length - 1);
  840     return s;
  841 }
  842 function _uEC(s) {
  843     var n = "";
  844     if ( ! s || s == "")
  845         return "";
  846     for (var i = 0; i < s.length; i ++ ) {
  847         if (s.charAt(i) == " ")
  848             n += "+";
  849         else n += s.charAt(i);
  850     }
  851     return n;
  852 }
  853 function __utmVisitorCode(f) {
  854     var r = 0,
  855     t = 0,
  856     i = 0,
  857     i2 = 0,
  858     m = 31;
  859     var a = _uGC(_ubd.cookie, "__utma=" + _udh, ";");
  860     if ((i = a.indexOf(".", 0)) < 0)
  861         return;
  862     if ((i2 = a.indexOf(".", i + 1)) > 0)
  863         r = a.substring(i + 1, i2);
  864     else return "";
  865     if ((i = a.indexOf(".", i2 + 1)) > 0)
  866         t = a.substring(i2 + 1, i);
  867     else return "";
  868     if (f) {
  869         return r;
  870     } else {
  871         var c = new Array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9');
  872         return c[r >> 28 & m] + c[r >> 23 & m] + c[r >> 18 & m] + c[r >> 13 & m] + "-" + c[r >> 8 & m] + c[r >> 3 & m] + c[((r & 7) << 2) + (t >> 30 & 3)] + c[t >> 25 & m] + c[t >> 20 & m] + "-" + c[t >> 15 & m] + c[t >> 10 & m] + c[t >> 5 & m] + c[t & m];
  873     }
  874 }


  875 function _uIN(n) {
  876     if ( ! n)
  877         return false;
  878     for (var i = 0; i < n.length; i ++ ) {
  879         var c = n.charAt(i);
  880         if ((c < "0" || c > "9") && (c != "."))
  881             return false;
  882     }
  883     return true;
  884 }
  885 function _uES(s, u) {
  886     if (typeof(encodeURIComponent) == 'function') {
  887         if (u)
  888             return encodeURI(s);
  889         else return encodeURIComponent(s);
  890     } else {
  891         return escape(s);
  892     }
  893 }


  894 function _uUES(s) {
  895     if (typeof(decodeURIComponent) == 'function') {
  896         return decodeURIComponent(s);
  897     } else {
  898         return unescape(s);
  899     }
  900 }


  901 function _uVG() {
  902     if ((_udn.indexOf("www.google.") == 0 || _udn.indexOf(".google.") == 0 || _udn.indexOf("google.") == 0) && _utcp == '/') {
  903         return false;
  904     }
  905     return true;
  906 }


  907 function _uSP() {
  908     var s = 100;
  909     if (_usample)
  910         s = _usample;
  911     if (s >= 100 || s <= 0)
  912         return true;
  913     return((__utmVisitorCode(1) % 10000) < (s * 100));
  914 }


  915 function urchinPathCopy(p) {
  916     var d = document,
  917     nx,
  918     tx,
  919     sx,
  920     i,
  921     c,
  922     cs,
  923     t,
  924     h,
  925     o;
  926     cs = new Array("a", "b", "c", "v", "x", "z");
  927     h = _uDomain();
  928     if (_udn && _udn != "")
  929         o = " domain=" + _udn + ";";
  930     nx = "Sun, 18 Jan 2038 00:00:00 GMT;";
  931     tx = new Date();
  932     tx.setTime(tx.getTime() + (_utimeout * 1000));
  933     tx = tx.toGMTString() + ";";
  934     sx = new Date();
  935     sx.setTime(sx.getTime() + (_ucto * 1000));
  936     sx = sx.toGMTString() + ";";
  937     for (i = 0; i < 6; i ++ ) {
  938         t = " expires=";
  939         if (i == 1)
  940             t += tx;
  941         else if (i == 2)
  942             t = "";
  943         else if (i == 5)
  944             t += sx;
  945         else t += nx;
  946         c = _uGC(d.cookie, "__utm" + cs[i] + "=" + h, ";");
  947         if (c != "-")
  948             d.cookie = "__utm" + cs[i] + "=" + c + "; path=" + p + ";" + t + o;
  949     }
  950 }


  951 function _uCO() {
  952     if ( ! _utk || _utk == "" || _utk.length < 10)
  953         return;
  954     var d = 'www.google.com';
  955     if (_utk.charAt(0) == '!')
  956         d = 'analytics.corp.google.com';
  957     _ubd.cookie = "GASO=" + _utk + "; path=" + _utcp + ";" + _udo;
  958     var sc = document.createElement('script');
  959     sc.type = 'text/javascript';
  960     sc.id = "_gasojs";
  961     sc.src = 'https://' + d + '/analytics/reporting/overlay_js?gaso=' + _utk + '&' + Math.random();
  962     document.getElementsByTagName('head')[0].appendChild(sc);
  963 }


  964 function _uGT() {
  965     var h = location.hash,
  966     a;
  967     if (h && h != "" && h.indexOf("#gaso=") == 0) {
  968         a = _uGC(h, "gaso=", "&");
  969     } else {
  970         a = _uGC(_ubd.cookie, "GASO=", ";");
  971     }
  972     return a;
  973 }

Finishing code that's always evaluated

  974 var _utk = _uGT();
  975 if (_utk && _utk != "" && _utk.length > 10) {
  976     if (window.addEventListener) {
  977         window.addEventListener('load', _uCO, false);
  978     } else if (window.attachEvent) {
  979         window.attachEvent('onload', _uCO);
  980     }
  981 }

Read more

Party cookie - GA a virtual first party

pencil icon, that"s clickable to start editing the post

User tracking depend on using cookies as i touched on in Party cookies - web analytics. For my own blog i use Google Analytics (GA), since i wanted to have an idea about visits to my blog, and since I then had choosen blogger/google i just continued with the pure shop idea (Single Sign-On among others) and that it didn't cost any thing (as in money). To have a closer look i changed my cookie settings in Firefox to ask me every time, and waouv there's a lot more serving cookies than i thought. I'm normally very relaxed about cookies and gladly use the service of persistent cookies to ease login, so i hadn't really looked at it for some time. Here's how a visit to my blog goes cookie wise.

First is a .blogger.com (from www2.blogger.com) cookie:

and as a fact www2.blogger.com does not have an A record, but an CNAME to blogger.l.google.com

dig www2.blogger.com

; <<>> DiG 9.3.4 <<>> www2.blogger.com
;; global options:  printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 29868
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 7, ADDITIONAL: 7

;; QUESTION SECTION:
;www2.blogger.com.              IN      A

;; ANSWER SECTION:
www2.blogger.com.       1689    IN      CNAME   blogger.l.google.com.
blogger.l.google.com.   184     IN      A       72.14.221.191

;; AUTHORITY SECTION:
l.google.com.           46533   IN      NS      b.l.google.com.
l.google.com.           46533   IN      NS      e.l.google.com.
l.google.com.           46533   IN      NS      f.l.google.com.
l.google.com.           46533   IN      NS      a.l.google.com.
l.google.com.           46533   IN      NS      d.l.google.com.
l.google.com.           46533   IN      NS      c.l.google.com.
l.google.com.           46533   IN      NS      g.l.google.com.

;; ADDITIONAL SECTION:
a.l.google.com.         85267   IN      A       209.85.139.9
b.l.google.com.         29215   IN      A       64.233.179.9
c.l.google.com.         29293   IN      A       64.233.161.9
g.l.google.com.         28956   IN      A       64.233.167.9
f.l.google.com.         86263   IN      A       72.14.235.9
e.l.google.com.         28956   IN      A       209.85.137.9
d.l.google.com.         29215   IN      A       66.249.93.9

;; Query time: 14 msec
;; SERVER: 192.168.1.1#53(192.168.1.1)
;; WHEN: Thu Jul 12 21:15:35 2007
;; MSG SIZE  rcvd: 305
and then no less than four GA cookie's from .blog.sweetxml.org (from blog.sweetxml.org):

and blog.sweetxml.org has a CNAME as well to ghs.google.com which again has a CNAME to ghs.l.google.com:
dig blog.sweetxml.org

; <<>> DiG 9.3.4 <<>> blog.sweetxml.org
;; global options:  printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 63018
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 7, ADDITIONAL: 7

;; QUESTION SECTION:
;blog.sweetxml.org.             IN      A

;; ANSWER SECTION:
blog.sweetxml.org.      40733   IN      CNAME   ghs.google.com.
ghs.google.com.         548066  IN      CNAME   ghs.l.google.com.
ghs.l.google.com.       26      IN      A       72.14.207.121

;; AUTHORITY SECTION:
l.google.com.           46380   IN      NS      a.l.google.com.
l.google.com.           46380   IN      NS      f.l.google.com.
l.google.com.           46380   IN      NS      c.l.google.com.
l.google.com.           46380   IN      NS      d.l.google.com.
l.google.com.           46380   IN      NS      e.l.google.com.
l.google.com.           46380   IN      NS      g.l.google.com.
l.google.com.           46380   IN      NS      b.l.google.com.

;; ADDITIONAL SECTION:
a.l.google.com.         85114   IN      A       209.85.139.9
b.l.google.com.         29062   IN      A       64.233.179.9
c.l.google.com.         29140   IN      A       64.233.161.9
g.l.google.com.         28803   IN      A       64.233.167.9
f.l.google.com.         86110   IN      A       72.14.235.9
e.l.google.com.         28803   IN      A       209.85.137.9
d.l.google.com.         29062   IN      A       66.249.93.9

;; Query time: 18 msec
;; SERVER: 192.168.1.1#53(192.168.1.1)
;; WHEN: Thu Jul 12 21:18:08 2007
;; MSG SIZE  rcvd: 323

How the h... does the user tracking cookie for GA come from blog.sweetxml.org? I'm no Javascript Whizz but it must come from the referenced JavaScript in:

<script src='http://www.google-analytics.com/urchin.js' type='text/javascript'>
</script>
<script type='text/javascript'>
_uacct = "UA-1555577-1";
urchinTracker();
</script>

Fetching http://www.google-analytics.com/urchin.js with WGet gives:

wget -S http://www.google-analytics.com/urchin.js
--21:06:01--  http://www.google-analytics.com/urchin.js
Resolving www.google-analytics.com... 64.233.183.147, 64.233.183.99, 64.233.183.104, ...
Connecting to www.google-analytics.com|64.233.183.147|:80... connected.
HTTP request sent, awaiting response...
  HTTP/1.0 200 OK
  Cache-Control: max-age=604800, public
  Content-Type: text/javascript
  Last-Modified: Mon, 18 Jun 2007 22:44:25 GMT
  Server: ucfe
  Content-Length: 21089
  Date: Thu, 12 Jul 2007 19:06:01 GMT
  Connection: Keep-Alive
Length: 21089 (21K) [text/javascript]
Saving to: `urchin.js'

I do know that cookies can be set and read through JavaScript, but it would be interesting to know what goes on in those 21K.

Read more

Thursday, July 12, 2007

Party cookies - web analytics

pencil icon, that"s clickable to start editing the post

In my post Party cookies - first or third-context i discovered how IE distinguish between first- and third-party cookies. A very common use for third party cookies is/was for tracking users on websites, but that is challenged by how both browsers and users react to cookies (both first and third part).

JupiterResearch did a study on cookie deletion in 2005, covered in Study: Consumers Delete Cookies at Surprising Rate which found that 17 percent of Internet users delete cookies on a weekly basis. Approximately 12 percent do so on a monthly basis, and 10 percent make it a daily habit

The problem with it is that:

The key finding is that a lot of companies have placed a lot of reliance on cookies for audience measurement and the cookie is at risk as a mechanism for tracking people over time," said Eric Petersen, the lead analyst on the report. That made similar reactions in other medias with titles like Faster Migration to First-Party Cookies Urged and 3rd Party Cookies Are Dead. This got addressed by tracking software like opentracker in All About (third-party) Cookies and recommeded best practice like WebTrends Advises Sites to Move to First-Party Cookies Based on Four-Fold Increase in Third-Party Cookie Rejection Rates and Best Practices for Accurate Web Analytics Avoiding Third-Party Cookie Rejection and Deletion.

In a more recent press release by ComScore Cookie-Based Counting Overstates Size of Web Site Audiences has the headline Frequent Cookie Deletion by 3 out of 10 U.S. Internet Users Leads to Overstatements in Audience Sizes by a Factor as High as 2.5. The difference here is that it's not just third party cookies that are being deleted (as expected) but also first party cookies There is a common perception that third-party cookie deletion rates should be significantly higher than first-party cookie deletion rates but there is almost no difference.

MYMOTECH has an analysis of the press release called Pass the Cookies: Interpreting Comscores Cookie Press Release.

Google Analytics that I user here at my blog (very very low traffic) should be using first party cookies, which is something I'll look into later.

Read more

Wednesday, July 11, 2007

Party cookies - first or third-context

pencil icon, that"s clickable to start editing the post

Internet Explorer 6+ (IE) has default privacy policy to block third party cookies in ex. iframe's. How exactly is first and third party defined and thereby how can this obstacle be overcome?

In the Microsoft Windows XP article Understanding cookies the description is:

A first-party cookie either originates on or is sent to the Web site you are currently viewing. These cookies are commonly used to store information, such as your preferences when visiting that site.

A third-party cookie either originates on or is sent to a Web site different from the one you are currently viewing. Third-party Web sites usually provide some content on the Web site you are viewing. For example, many sites use advertising from third-party Web sites and those third-party Web sites may use cookies. A common use for this type of cookie is to track your Web page use for advertising or other marketing purposes. Third-party cookies can either be persistent or temporary.

The definition for first-party is the Web site you are currently viewing, and reading it like this it seems that there is just one first-party and the rest i third-party. But that's not true, well that depends on how you interpret it, because the most precise definition that I've found is in Privacy in Internet Explorer 6 in the section First and Third-Party Context:

Internet Explorer 6 defines first-party content as content associated with the host domain. Third-party content originates from any other domain. For example, suppose a user visits www.wideworldimporters.com by typing this URL in the address bar, and www.wingtiptoys.com has a banner ad on this page. If these two sites set cookies, the cookies from www.wideworldimporters.com are in a first-party context while the cookies from www.wingtiptoys.com are in a third-party context.

Often commercial Web pages are an amalgamation of first- and third-party content. The Internet Explorer 6 privacy features distinguish between first- and third-party content. The underlying assumption is that users have a different relationship with first parties than with third parties. In fact, users might not be aware of the third party or be given a choice of whether to have a relationship with it. For this reason, default privacy settings for third parties are more stringent than for first parties.

but it's in the associated note it's written crystal clear:

The URLs www.wideworldimporters.com and toys.wideworldimporters.com both contain the same minimal domain, wideworldimporters.com. Content that shares the same minimal domain as the host domain is considered first-party content. Likewise, cookies set from these domains are considered first-party cookies. Minimal domains must have the same top-level domain (TLD). Some common examples of TLDs are .com, .net, and .org.

I haven't heard the term minimal domain before but it's ituitive to understand. It matches (sort of) the definition of a domain cookie as defined in RFC 2965 - HTTP State Management Mechanism:

Host names can be specified either as an IP address or a HDN string. Sometimes we compare one host name with another. (Such comparisons SHALL be case-insensitive.) Host A's name domain-matches host B's if

  • their host name strings string-compare equal; or
  • A is a HDN string and has the form NB, where N is a non-empty name string, B has the form .B', and B' is a HDN string. (So, x.y.com domain-matches .Y.com but not Y.com.)

It's fair enough to expect the owner of a domain to take responsibility of all webservers/hosts on that domain, making it a domain of trust. Though be aware that the P3P privacy policy is per host (and/or subdomain) and not per minimal domain as illustrated in spywarewarrior's Internet Privacy w/ IE6 & P3P: A Summary of Findings the section First-Party vs. Third-Party.

Next I'll have a quick look at P3P.

Read more

Tuesday, May 22, 2007

WS-RX hopefully on it's way to become an OASIS standard

pencil icon, that"s clickable to start editing the post

It's been a long journey even though or maybe just because it started out with two specifications. Paul Freemantle wrote about the reason for the last delay of WS-RX but now the Balloting for OASIS Standard - WS-ReliableMessaging 1.1 is on. The critical number of affirmative votes required to approve this ballot is 51, and right now the status page gives a count of 43 positive votes of a potential total of 337, so with more than a week left it finally looks like the last child of the WS-*X family will succeed.

Read more