[JavaScript] Reading Google Analytics ga.js Source Code After Restoration

Tadashi Shigeoka ·  Sun, January 8, 2012

I was curious about what kind of processing is done in Google Analytics, which is familiar for access analysis, so I’ve been reading the source code.

・Source Code: http://google-analytics.com/ga.js

The essential source code is compressed JavaScript, so what was restored with JsDecoder is

JsDecoder - javascript decoder - decode obfuscated script

■ Code Restored with JsDecoder

(function ()
{
    var g = void 0, h = true, i = null, j = false, ba = encodeURIComponent, ca = Infinity, da = setTimeout, 
    ea = decodeURIComponent, k = Math;
    function fa(a, b)
    {
        return a.onload = b
    }
    function ga(a, b)
    {
        return a.name = b
    }
    var m = "push", ha = "slice", ia = "replace", ja = "load", ka = "floor", n = "charAt", la = "value", 
    p = "indexOf", ma = "match", r = "name", oa = "host", t = "toString", u = "length", v = "prototype", 
    w = "split", pa = "stopPropagation", qa = "scope", x = "location", y = "getString", z = "substring", 
    ra = "navigator", A = "join", C = "toLowerCase", D;
    function sa(a, b)
    {
        switch (b) {
            case 0:
                return "" + a;
            case 1:
                return a * 1;
            case 2:
                return!!a;
            case 3:
                return a * 1E3
        }
        return a
    }
    function E(a, b)
    {
        return g == a || "-" == a && !b || "" == a
    }
    function ta(a)
    {
        if (!a || "" == a) {
            return "";
        }
        for (; a && " \n\\r\  "[p](a[n](0)) > -1; ) {
            a = a[z](1);
        }
        for (; a && " \n\\r\  "[p](a[n](a[u] - 1)) > -1; ) {
            a = a[z](0, a[u] - 1);
        }
        return a
    }
    function ua(a)
    {
        var b = 1, c = 0, d;
        if (!E(a))
        {
            b = 0;
            for (d = a[u] - 1; d >= 0; d--) {
                c = a.charCodeAt(d), b = (b << 6 & 268435455) + c + (c << 14), c = b & 266338304, b = c != 0 ? b^c >> 21 : b;
            }
        }
        return b
    }
    function va()
    {
        return k.round(k.random() * 2147483647)
    }
    function wa() {}
    function F(a, b)
    {
        return ba instanceof Function ? b ? encodeURI(a) : ba(a) : (G(68), escape(a))
    }
    function H(a)
    {
        a = a[w]("+")[A](" ");
        if (ea instanceof Function) {
            try {
                return ea(a) 
            }
            catch (b) {
                G(17) 
            }
        }
        else {
            G(68);
        }
        return unescape(a)
    }
    var xa = function (a, b, c, d)
    {
        a.addEventListener ? a.addEventListener(b, c, !!d) : a.attachEvent && a.attachEvent("on" + b, 
        c)
    },
    ya = function (a, b, c, d)
    {
        a.removeEventListener ? a.removeEventListener(b, c, !!d) : a.detachEvent && a.detachEvent("on" + b, 
        c)
    };
    function I(a)
    {
        return a && a[u] > 0 ? a[0] : ""
    }
    function za(a)
    {
        var b = a ? a[u] : 0;
        return b > 0 ? a[b - 1] : ""
    }
    var Aa = function ()
    {
        this.prefix = "ga.";
        this.I = {}
    };
    Aa[v].set = function (a, b)
    {
        this.I[this.prefix + a] = b;
    };
    Aa[v].get = function (a)
    {
        return this.I[this.prefix + a];
    };
    Aa[v].contains = function (a)
    {
        return this.get(a) !== g;
    };
    function Ba(a)
    {
        a[p]("www.") == 0 && (a = a[z](4));
        return a[C]()
    }
    function Ca(a, b)
    {
        var c, d = {
            url : a, protocol : "http", host : "", path : "", c : new Aa, anchor : ""
        };
        if (!a) {
            return d;
        }
        c = a[p]("://");
        if (c >= 0) {
            d.protocol = a[z](0, c), a = a[z](c + 3);
        }
        c = a.search("/|\\\\?|#");
        if (c >= 0) {
            d.host = a[z](0, c)[C](), a = a[z](c);
        }
        else {
            return d.host = a[C](), d;
        }
        c = a[p]("#");
        if (c >= 0) {
            d.anchor = a[z](c + 1), a = a[z](0, c);
        }
        c = a[p]("?");
        c >= 0 && (Da(d.c, a[z](c + 1)), a = a[z](0, c));
        d.anchor && b && Da(d.c, d.anchor);
        a && a[n](0) == "/" && (a = a[z](1));
        d.path = a;
        return d
    }
    function Da(a, b)
    {
        function c(b, c)
        {
            a.contains(b) || a.set(b, []);
            a.get(b)[m](c)
        }
        for (var d = ta(b)[w]("&"), e = 0; e < d[u]; e++) if (d[e]) {
            var f = d[e][p]("=");
            f < 0 ? c(d[e], "1") : c(d[e][z](0, f), d[e][z](f + 1))
        }
    }
    function Ea(a, b)
    {
        if (E(a)) {
            return "-";
        }
        if ("[" == a[n](0) && "]" == a[n](a[u] - 1)) {
            return "-";
        }
        var c = J.domain;
        c += b && b != "/" ? b : "";
        return a[p](c) == (a[p]("http://") == 0 ? 7 : a[p]("https://") == 0 ? 8 : 0) ? "0" : a;
    };
    function Fa(a, b, c)
    {
        k.random() * 100 >= 1 || (a = ["utmt=error", "utmerr=" + a, "utmwv=5.2.2", "utmn=" + va(), "utmsp=1"], 
        b && a[m]("api=" + b), c && a[m]("msg=" + F(c[z](0, 100))), K.q && a[m]("aip=1"), Ga(a[A]("&")));
    };
    var Ha = 0;
    function L(a)
    {
        return (a ? "_" : "") + Ha++
    }
    var Ia = L(), Ja = L(), Ka = L(), La = L(), Ma = L(), M = L(), N = L(), Na = L(), Oa = L(), Pa = L(), 
    Qa = L(), Ra = L(), Sa = L(), Ta = L(), Ua = L(), Va = L(), Wa = L(), Xa = L(), Ya = L(), Za = L(), 
    $a = L(), ab = L(), bb = L(), cb = L(), db = L(), eb = L(), fb = L(), gb = L(), hb = L(), ib = L(), 
    jb = L(), kb = L(), lb = L(), mb = L(), nb = L(), O = L(h), ob = L(), pb = L(), qb = L(), rb = L(), 
    sb = L(), tb = L(), ub = L(), vb = L(), wb = L(), xb = L(), P = L(h), yb = L(h), zb = L(h), Bb = L(h), 
    Cb = L(h), Db = L(h), Eb = L(h), Fb = L(h), Gb = L(h), Hb = L(h), Ib = L(h), Q = L(h), Jb = L(h), 
    Kb = L(h), Lb = L(h), Mb = L(h), Nb = L(h), Ob = L(h), Pb = L(h), Qb = L(h), Rb = L(h), Sb = L(h), 
    Tb = L(h), Ub = L(h), Vb = L(h), Wb = L(), Xb = L(), Yb = L();
    L();
    var Zb = L(), $b = L(), ac = L(), bc = L(), cc = L(), dc = L(), ec = L(), hc = L(), ic = L(), jc = L();
    L();
    var kc = L(), lc = L();
    // ... (code continues for over 2000 lines) ...
})();

■ Original Source Code Before Restoration (http://google-analytics.com/ga.js)

(function(){var g=void 0,h=true,i=null,j=false,ba=encodeURIComponent,ca=Infinity,da=setTimeout,ea=decodeURIComponent,k=Math;function fa(a,b){return a.onload=b}function ga(a,b){return a.name=b}var m="push",ha="slice",ia="replace",ja="load",ka="floor",n="charAt",la="value",p="indexOf",ma="match",r="name",oa="host",t="toString",u="length",v="prototype",w="split",pa="stopPropagation",qa="scope",x="location",y="getString",z="substring",ra="navigator",A="join",C="toLowerCase",D;function sa(a,b){switch(b){case 0:return""+a;case 1:return a*1;case 2:return!!a;case 3:return a*1E3}return a}function E(a,b){return g==a||"-"==a&&!b||""==a}function ta(a){if(!a||""==a)return"";for(;a&&" \n\\r\  "[p](a[n](0))>-1;)a=a[z](1);for(;a&&" \n\\r\  "[p](a[n](a[u]-1))>-1;)a=a[z](0,a[u]-1);return a}function ua(a){var b=1,c=0,d;if(!E(a)){b=0;for(d=a[u]-1;d>=0;d--)c=a.charCodeAt(d),b=(b<<6&268435455)+c+(c<<14),c=b&266338304,b=c!=0?b^c>>21:b}return b}
function va(){return k.round(k.random()*2147483647)}function wa(){}function F(a,b){return ba instanceof Function?b?encodeURI(a):ba(a):(G(68),escape(a))}function H(a){a=a[w]("+")[A](" ");if(ea instanceof Function)try{return ea(a)}catch(b){G(17)}else G(68);return unescape(a)}var xa=function(a,b,c,d){a.addEventListener?a.addEventListener(b,c,!!d):a.attachEvent&&a.attachEvent("on"+b,c)},ya=function(a,b,c,d){a.removeEventListener?a.removeEventListener(b,c,!!d):a.detachEvent&&a.detachEvent("on"+b,c)};
function I(a){return a&&a[u]>0?a[0]:""}function za(a){var b=a?a[u]:0;return b>0?a[b-1]:""}var Aa=function(){this.prefix="ga.";this.I={}};Aa[v].set=function(a,b){this.I[this.prefix+a]=b};Aa[v].get=function(a){return this.I[this.prefix+a]};Aa[v].contains=function(a){return this.get(a)!==g};function Ba(a){a[p]("www.")==0&&(a=a[z](4));return a[C]()}function Ca(a,b){var c,d={url:a,protocol:"http",host:"",path:"",c:new Aa,anchor:""};if(!a)return d;c=a[p]("://");if(c>=0)d.protocol=a[z](0,c),a=a[z](c+3);c=a.search("/|\\\\?|#");if(c>=0)d.host=a[z](0,c)[C](),a=a[z](c);else return d.host=a[C](),d;c=a[p]("#");if(c>=0)d.anchor=a[z](c+1),a=a[z](0,c);c=a[p]("?");c>=0&&(Da(d.c,a[z](c+1)),a=a[z](0,c));d.anchor&&b&&Da(d.c,d.anchor);a&&a[n](0)=="/"&&(a=a[z](1));d.path=a;return d}
function Da(a,b){function c(b,c){a.contains(b)||a.set(b,[]);a.get(b)[m](c)}for(var d=ta(b)[w]("&"),e=0;e=1||(a=["utmt=error","utmerr="+a,"utmwv=5.2.2","utmn="+va(),"utmsp=1"],b&&a[m]("api="+b),c&&a[m]("msg="+F(c[z](0,100))),K.q&&a[m]("aip=1"),Ga(a[A]("&")))};var Ha=0;function L(a){return(a?"_":"")+Ha++}
var Ia=L(),Ja=L(),Ka=L(),La=L(),Ma=L(),M=L(),N=L(),Na=L(),Oa=L(),Pa=L(),Qa=L(),Ra=L(),Sa=L(),Ta=L(),Ua=L(),Va=L(),Wa=L(),Xa=L(),Ya=L(),Za=L(),$a=L(),ab=L(),bb=L(),cb=L(),db=L(),eb=L(),fb=L(),gb=L(),hb=L(),ib=L(),jb=L(),kb=L(),lb=L(),mb=L(),nb=L(),O=L(h),ob=L(),pb=L(),qb=L(),rb=L(),sb=L(),tb=L(),ub=L(),vb=L(),wb=L(),xb=L(),P=L(h),yb=L(h),zb=L(h),Bb=L(h),Cb=L(h),Db=L(h),Eb=L(h),Fb=L(h),Gb=L(h),Hb=L(h),Ib=L(h),Q=L(h),Jb=L(h),Kb=L(h),Lb=L(h),Mb=L(h),Nb=L(h),Ob=L(h),Pb=L(h),Qb=L(h),Rb=L(h),Sb=L(h),Tb=
L(h),Ub=L(h),Vb=L(h),Wb=L(),Xb=L(),Yb=L();L();var Zb=L(),$b=L(),ac=L(),bc=L(),cc=L(),dc=L(),ec=L(),hc=L(),ic=L(),jc=L();L();var kc=L(),lc=L();var mc=function(){function a(a,c,d){R(S[v],a,c,d)}T("_getName",Ka,58);T("_getAccount",Ia,64);T("_visitCode",P,54);T("_getClientInfo",Ta,53,1);T("_getDetectTitle",Wa,56,1);T("_getDetectFlash",Ua,65,1);T("_getLocalGifPath",fb,57);T("_getServiceMode",gb,59);U("_setClientInfo",Ta,66,2);U("_setAccount",Ia,3);U("_setNamespace",Ja,48);U("_setAllowLinker",Qa,11,2);U("_setDetectFlash",Ua,61,2);U("_setDetectTitle",Wa,62,2);U("_setLocalGifPath",fb,46,0);U("_setLocalServerMode",gb,92,g,0);U("_setRemoteServerMode",
gb,63,g,1);U("_setLocalRemoteServerMode",gb,47,g,2);U("_setSampleRate",eb,45,1);U("_setCampaignTrack",Va,36,2);U("_setAllowAnchor",Ra,7,2);U("_setCampNameKey",Ya,41);U("_setCampContentKey",cb,38);U("_setCampIdKey",Xa,39);U("_setCampMediumKey",ab,40);U("_setCampNOKey",db,42);U("_setCampSourceKey",$a,43);U("_setCampTermKey",bb,44);U("_setCampCIdKey",Za,37);U("_setCookiePath",N,9,0);U("_setMaxCustomVariables",hb,0,1);U("_setVisitorCookieTimeout",Na,28,1);U("_setSessionCookieTimeout",Oa,26,1);U("_setCampaignCookieTimeout",
Pa,29,1);U("_setReferrerOverride",qb,49);U("_setSiteSpeedSampleRate",ic,132);a("_trackPageview",S[v].na,1);a("_trackEvent",S[v].v,4);a("_trackPageLoadTime",S[v].ma,100);a("_trackSocial",S[v].oa,104);a("_trackTrans",S[v].pa,18);a("_sendXEvent",S[v].u,78);a("_createEventTracker",S[v].V,74);a("_getVersion",S[v].$,60);a("_setDomainName",S[v].t,6);a("_setAllowHash",S[v].ea,8);a("_getLinkerUrl",S[v].Z,52);a("_link",S[v].link,101);a("_linkByPost",S[v].da,102);a("_setTrans",S[v].ha,20);a("_addTrans",S[v].O,
21);a("_addItem",S[v].M,19);a("_setTransactionDelim",S[v].ia,82);a("_setCustomVar",S[v].fa,10);a("_deleteCustomVar",S[v].X,35);a("_getVisitorCustomVar",S[v].aa,50);a("_setXKey",S[v].ka,83);a("_setXValue",S[v].la,84);a("_getXKey",S[v].ba,76);a("_getXValue",S[v].ca,77);a("_clearXKey",S[v].S,72);a("_clearXValue",S[v].T,73);a("_createXObj",S[v].W,75);a("_addIgnoredOrganic",S[v].K,15);a("_clearIgnoredOrganic",S[v].P,97);a("_addIgnoredRef",S[v].L,31);a("_clearIgnoredRef",S[v].Q,32);a("_addOrganic",S[v].N,
14);a("_clearOrganic",S[v].R,70);a("_cookiePathCopy",S[v].U,30);a("_get",S[v].Y,106);a("_set",S[v].ga,107);a("_addEventListener",S[v].addEventListener,108);a("_removeEventListener",S[v].removeEventListener,109);a("_initData",S[v].m,2);a("_setVar",S[v].ja,22);U("_setSessionTimeout",Oa,27,3);U("_setCookieTimeout",Pa,25,3);U("_setCookiePersistence",Na,24,1);a("_setAutoTrackOutbound",wa,79);a("_setTrackOutboundSubdomains",wa,81);a("_setHrefExamineLimit",wa,80)},R=function(a,b,c,d){a[b]=function(){try{return G(d),
c.apply(this,arguments)}catch(a){throw Fa("exc",b,a&&a[r]),a;}}},T=function(a,b,c,d){S[v][a]=function(){try{return G(c),sa(this.a.get(b),d)}catch(e){throw Fa("exc",a,e&&e[r]),e;}}},U=function(a,b,c,d,e){S[v][a]=function(f){try{G(c),e==g?this.a.set(b,sa(f,d)):this.a.set(b,e)}catch(l){throw Fa("exc",a,l&&l[r]),l;}}},nc=function(a,b){return{type:b,target:a,stopPropagation:function(){throw"aborted";}}};var oc=function(a,b){return b!=="/"?j:(a[p]("www.google.")==0||a[p](".google.")==0||a[p]("google.")==0)&&!(a[p]("google.org")>-1)?h:j},pc=function(a){var b=a.get(Ma),c=a[y](N,"/");oc(b,c)&&a[pa]()};var uc=function(){var a={},b={},c=new qc;this.g=function(a,b){c.add(a,b)};var d=new qc;this.d=function(a,b){d.add(a,b)};var e=j,f=j,l=h;this.J=function(){e=h};this.f=function(a){this[ja]();this.set(Wb,a,h);a=new rc(this);e=j;d.execute(this);e=h;b={};this.i();a.qa()};this.load=function(){e&&(e=j,this.sa(),sc(this),f||(f=h,c.execute(this),tc(this),sc(this)),e=h)};this.i=function(){if(e)if(f)e=j,tc(this),e=h;else this[ja]()};this.get=function(c){c&&c[n](0)=="_"&&this[ja]();return b[c]!==g?b[c]:a[c]};
this.set=function(c,d,e){c&&c[n](0)=="_"&&this[ja]();e?b[c]=d:a[c]=d;c&&c[n](0)=="_"&&this.i()};this.n=function(b){a[b]=this.b(b,0)+1};this.b=function(a,b){var c=this.get(a);return c==g||c===""?b:c*1};this.getString=function(a,b){var c=this.get(a);return c==g?b:c+""};this.sa=function(){if(l){var b=this[y](Ma,""),c=this[y](N,"/");oc(b,c)||(a[M]=a[Sa]&&b!=""?ua(b):1,l=j)}}};uc[v].stopPropagation=function(){throw"aborted";};
var rc=function(a){var b=this;this.j=0;var c=a.get(Xb);this.Aa=function(){b.j>0&&c&&(b.j--,b.j||c())};this.qa=function(){!b.j&&c&&da(c,0)};a.set(Yb,b,h)};function vc(a,b){for(var b=b||[],c=0;c

By the way, the current Google Analytics code (as of January 8, 2012) is from the link below, and since it’s compressed, you can read it if you restore it.

http://google-analytics.com/ga.js

This tool is recommended for restoring compressed JavaScript.

JsDecoder - javascript decoder - decode obfuscated script

That’s all from the Gemba.