Author: David Vallejo

  • Track alert() pop ups automatically in Google Tag Manager

    Did you ever faced a site that still used the old-fashined alert popups for example for showing a form validation messages? and you were wondering how to track that form alert popups without needing to change anything on the site (as it is likely going to be an old one). And yep,they still exist. Hopefully if we are already using Google Tag Manager (or we can tell the client to add some little piece of code to their pages) we could track them easily using what is called a Proxy Pattern.

    Sadly this won’t be supported by IE8 for the alerts as it seems it’s not a function but an object, therefore we’re adding a check for pre IE9 browsers.

    In essence, we’re saving the current window[“alert”] function in a new variable, and the redefining the same function, but returning the passed arguments to our original saved function, preserving the original function behaviour.

    We’ll just need to create a Custom Html Tag that will fire either in all pages or just for the ones that we want to track alerts on.

    // Let's check if the browser is <=IE8
    if(!(document.all && !document.addEventListener))
    { 
     // Just in case check, to avoid loops
     if(!window.proxied_alert)
     {
       window.proxied_alert = window.alert; // Preserve the original function
       window.alert = function() { 
         var message = (!arguments[0]) ? 'null': arguments[0];
         dataLayer.push({'event': 'alert_showed','alert_message': message});
         return proxied_alert.apply(this, arguments);
       }
     }
    }

    In this example we’re pushing the info to the dataLayer, but we could directly do anything like firing an event using the native ga/_gaq functions or pushing the info to any other tool we want.

    As we’re modifying the original window.alert function, I suggest  to deeply debug/test the site functionality after implementing this code, as it may happen that other script is doing the same thing to the alert function. (some modals scripts plays with this to automatically convert the alert calls to a nicer popups).

  • Tips to track an ajax based website using GTM and Universal Analytics

    I’ve been dealing with some Ajax based website tracking these past months (mostly AngularJS based ones), and I’ve learn a lot of stuff , mostly some important points about how Google Tag Manager does work.

    Usually tracking an Ajax based website is a PITA, since mostly we don’t have page reloads as all the content is loaded asynchronously. So either you ask the developers to push you the content loaded info into the dataLayer or you play with the history location.

    Still we need to have some points in mind while tracking those sites with Google Tag Manager (and maybe natively or using any other tag management system).

    1. Use a fixed tracker name

    The way Google Tag Manager works, everytime a Google Analytics tags is fired it creates a new tracker with a name (“GTM”+Current timeStamp ). This is not a problem for most tracking implementations, but we need to take in mind that websites based in Ajax usually changes the current URI without even needing to reload the page, so it may happen that if we’re using the campaign tagging we may ending having a lots of unneeded visit respawn and referrals.

    Let me explain this with a simple example:

    https://www.domainlinkingtous.com has a link to our site and it’s using the campaign tagging to allow us to track their visits to us.

    http://www.ourdomain.com?utm_source=test_source&utm_medium=test_medium&utm_campaign=test_campaign

    So the visit will end in our page with the following values:

    URL: http://www.ourdomain.com?utm_source=test_source&utm_medium=test_medium&utm_campaign=test_campaign
    Referrer: http://www.domainlinkingtous.com

    Let’s map this to Universal Analytics parameters:

    dl: http://www.ourdomain.com?utm_source=test_source&utm_medium=test_medium&utm_campaign=test_campaign
    dr: http://www.domainlinkingtous.com

    Universal Analytics uses the “dl” parameter  (document.location) and dr(document.referrer), to calculate the visit attribution. It will search for gclid, utm_ parameters in the “dl” parameter value (in that order of preference) and if it doesn’t find them it will try to calculate the attribution from the “dr” string.

    As we have the the utm parameters in our landing page, the referrer won’t be taken in mind to calculate the visit attribution, so we’re ok at this point.

    source: test_source
    medium: test_medium
    campaign: test_campaign

    But if the visitor decides to go to another page, and like we said in this case there will be no page reload  Google Tag Manager will spawn a new tracker and we’ll end having those values.

    dl: http://www.ourdomain.com/secondPage.html
    dr: http://www.domainlinkingtous.com

    As we said before if there’re no utm or gclid parameters in the document.location Google analytics in going to look to the document.referral string and it will find a different domain than the current loading one, so it will track a new visit:

    source: domainlinkingtous.com
    medium: referral
    campaign: /

    D’oh. This is wrong, we’ll miss the original visit attribution, plus we’ll have some extra ghost sessions in our data.

    Best way to do this (even if it’s not recommended) to set a fixed tracker name in our tags.

    ajax_sites-01

    This way, the same tracker instance will be used everytime and the original dl parameter will be kept.

    2. Force the Non-Interaction Flag to false in your pageviews

    This is another important point to have in mind. Google Tag Manager uses the set command to set the values instead of setting them directly to hit. So if we fire and non-interactive event tag, the subsecuent hits will inherit that flag making the subsecuente pageviews to have the “ni” parameter attached to them.

    Let’s how Google Tag Manager is going to translate a single Event tag:

    ga("create", "UA-40180485-1", {"cookieDomain": "auto","name": "myTracker"});
    ga("myTracker.set", "&gtm", "GTM-MW3DNR");
    ga("myTracker.set", "nonInteraction", true);
    ga("myTracker.send", {"eventAction": "test","eventCategory": "test", "eventLabel": "test","eventValue": undefined,"hitType": "event"});

    As you can see the nonInteraction is globaly for the tracker, and this will affect our next pageviews (remember that we don’t have any page reload so the nonInteraction flag will be kept till we disable it.

    An easy going fix for this without needing to deal with hitCallback/eventCallback is to automatically remove the “ni” parameter for all pageviews as it’s not likely going to need it (ever used a non-interactional pageview?).

    Let’s see how can we achive this. We can’t use undefined string on GTM input boxes as it will be treated as a string, therefore we’re going to create a new Variable that is going to return us the real undefined value.

    ajax_sites-02


    N
    ow we can safely force the “ni” parameter to undefined in our pageview tags this way:

    ajax_sites-03

    Did you fance any other problems when tracking ajax based sites?, share them in a comment 🙂

    Greets: Thanks fly one more time to Yehoshua Coren from Analytics Ninja, for reviewing these points with me.

  • Pushing custom commands to Universal Analytics before Pageview tag execution

    Since I wrote the post about how to send a local copy of Universal Analytics hits I’ve been looking for a way to get this working within Google Tag Manager. But there’s no way to send anything between the tracker creating and the hit firing on GTM.

    Some time ago there was a discussion thread on Twitter commenting this problem:

    And even Simo Ahava wrote a post about it afterwards: http://www.simoahava.com/analytics/access-the-tracker-object-in-your-page-view-tag/

    Today I had some free time after lunch and I decided to get this working in my own way so and I’m showing a way to achive this in a pretty standard way, with multi-tracker support, with just one single HTML tag (affecting all hits sent by GTM) and still not needing to initialize the tracker within a Custom HTML tag, so you will just continue using the predefined Universal Analytics tags on Google Tag Manager. you remember I wrote about how Universal Analytics snippet works some time ago, and we’re going to use the stuff learned there on this post.
    Universal Analytics creates a global ‘ga’ object, and then a queue (‘q’ parameter) to process it later on(when analytics.js has been fully loaded) , this way:

    window['ga']=window['ga']||function(){
      (window['ga'].q=window['ga'].q||[]).push(arguments);
    }
    

    Google Tag Manager does nothing else but using the analytics.js API to track things then we’re going to hook our needed code right after the create command has been pushed to the queue:
    The following tag will us to set the current tracker clientID as the custom dimension 10:

    window['ga']=window['ga']||function(){
      (window['ga'].q=window['ga'].q||[]).push(arguments);
      if(arguments[0]=="create")
      {
      // Code that is going to be added to the queue after the create command
      ga(function() {
      tracker = ga.getAll()[ga.getAll().length-1];
      tracker.set('dimension10', tracker.get('clientId'));
      });
    }
    

    Yeah, that’s all , as easy as that, we won’t need to deal with dataLayer pushes, wait for something to be executed and better of all it will work for any Universal Analytics tags being fired from GTM.

    There’s just one more thing we will need to do, and it’s set the firing priority for this tag to a high value (100 or so) and firing trigger to “All Pages” so it gets executed as soon as possible and before any other tag  firing at “all pages” time by Google Tag Manager.

    tracker_create_hook_1

    Let’s take a look about how the queue would look without our code, and how it will end being after we hooked our code into it:

    tracker_create_hook_3


    When analytics.js starts to proccess the current commands queue, it will be process the new pushes we added right after the tracker has been created and before it sends the hit.

    This will not just allow to set custom dimensions on GA, we could use to work with the Universal Analytics Tasks , or we could use it to grab our testing values before Universal Pageview has been sent, or anything you ever wanted to do before the first hit was being fired and you never were able to control due to the asynchronously loaded tags by Google Tag Manager.
    To finish, let’s take a look to how would our tag look if we would like to send a local copy of universal hits:

    tracker_create_hook_4

    Find the code below:

    Thanks go to @AnalyticsNinja for helping me to test it.

  • JWPlayer video tracking using Google Tag Manager

    JWPlayer is one the most known video players (if not the most one) and today we’re going to learn how to track it using GTM (Google Tag Manager). This time we’re going to use an agnostic dataLayer pushes instead of the ones that we usually use for Google Analytics. 

    We’ll be using one tag, one trigger and one variable, and in the next list we’re resuming all the events that our code will be able to track:

    • Video Plays
    • Video Pauses
    • Video Completions
    • Video Progress (Percentages to be tracked can be easily defined in the first line of the code)
    • Video Mute and UnMute
    • Video FullScreen On and FullScreen Off
    • Video Errors

    As we said before we’re going to use a tool agnostic dataLayer pushes instead of focusing in the almost standard event tracking model from Google Analytics. The following object will be our video tracking data model:

    {
        "event": "video",
        "player_id": {{VIDEO_ID}},
        "interaction": {{VIDEO_ACTION}},
        "video_url": {{VIDEO_URL}},
        "duration": {{VIDEO_DURATION}},
        "width": {{PLAYER_WIDTH}},
        "height": {{PLAYER_HEIGHT}},
        "position": {{VIDEO_CURRENT_POSITION}},
        "resolutions": {{AVAILABLE_VIDEO_QUALITIES}}, // an array
        "volume": {{PLAYER_VOLUME}},
        "player_type": {{PLAYER_TYPE}} // html5 or flash
    }
    

    Most important data is the event, the interacction and the video_url (as used of the most video tracking scripts), but this time we’ll be adding some extra to the dataLayer pushes to be able to track more details info if we want to.

    Let’s start creating our needed configuration on Google Tag Manager. First thing that we’re going to need is to have a variable that is going to tell us if there’s any jwplayer available in the current page. We don’t want our tracking code to be injected in the page if we don’t have any video on it, do we?.

    jwplayer_tracking_variable

    Now it’s time to configure the trigger that is going to fire our tracking tag, so we’ll be using the previously created variable, and a second condition to trigger the tracking tag after the DOMReady event:

    jwplayer_tracking_trigger

    Let’s configure the tracking tag, after the screenshoot you’ll find the full code so you can copy & paste it:

    jwplayer_tracking_tag

    Tag Code

    Now all the video interactions info will be pushes to the dataLayer so you’ll have all that info available to send your events to Google Analytics or any other tool you like.
    Any suggestion, new tracking idea, feedback will be welcome, just leave a comment.

  • Yet another way/try to stop referrals/events spam on Google Analytics

    The spam referrals problem in Google Analytics is turning into the new “not provided”. Almost everyone I follow has posted/retweeted/said something about it in the past month. I didn’t want to miss this oportunity to bring back some of the scripts I did in the past year for myself and share it with everyone. So in this post I’m going to try to address the Spam problem from another perspective that is not based on using referrals lists and filters.

    As almost all of you may know, this problem is related to the Google Analytics Measurement Protocol not using any authentication mechanism, and being Websites tracked client-side it’s almost imposible to hide any protection mechanism if we don’t force user’s to be logged in some way to some service, what is not possible as we’ll need some way to track anonymous users. They’re using the Measurement Protocol to spam us? ok, so let’s play that game too and use the Measurement Protocol to protect our data from being spammed =)

    Some years ago I wrote some PHP scripts to track the ecommerce transactions server-side to avoid any client-side problem like: users blocking GA, JavaScript errors forcing ga to fail, users network problems, etc.

    So I updated that code to work with Universal to achieve the following goals:

    • Our real UA Number will be totally hidden for others, ie: there will be no way for anyone to guess our real Property number.
    • We’ll attach some string to our hostname parameters (&dh), and we’ll use that to filter our new view to prevent any spammers looping around al UA-XXXXX-Y to send hits.
    • As we’re going to proxy all our ga hits through our server-side script, it may allow other people to directly load that php file, so we’re using PHP sessions to avoid anyone to query that file if isn’t there any open session for that user.

    For Google Analytics Classic or the first Google Analytics Measurement Protocol releases, tracking every hit from server-side was a problem because we weren’t able to send the real users ip addreses (missing all GEO location related data), or their user-agents (this was possible forcing the request user-agent header anyway). But since some months ago this is no longer a problem as we can now send those values as parameters within our hits payload.

    First thing we need to do is to tell Google Analytics to send a copy of the hits to our own PHP tracking file (the one that is going to take care of proxing the hits to the real UA), this can be achived using the “Tasks”, so our Universal Analytics tag will look similar to:

    ga('create', 'UA-XXXXXX-Y', 'auto');
    ga(function(tracker) {
      var originalSendHitTask = tracker.get('sendHitTask');
      tracker.set('sendHitTask', function(model) {
      var payLoad =model.get('hitPayload');
      originalSendHitTask(model);
      var i=new Image(1,1);
      i.src="/collect.php"+"?"+payLoad;
      i.onload=function() { return; }
      });
    });
    ga('send', 'pageview');
    

    If you are interested on knowing how this piece of code works, you can take a read to this other post (it’s in spanish sorry …)

    Now we’ll need to install our server-side tracking code. It just has 2 files. gaproxy.class.php and collect.php . Just take care of uploading the collect.php file to accesible path on your site and then matching the code above with the right path for the file.

    You can grab the files from the following GitHub Repo: https://github.com/thyngster/ga-proxy

    So now that we have everything on place, let’s configure everything. In first place, let’s configure your own variables in the class file, it should be pretty straightforward:

        // Configuration Start
        // Set your real Property Nmber where you want to redirect the data
        private $property_id = 'UA-AAAAAAA-B';
        // This will be attached to the hostname value, so we can then filter any hit not coming from this script
        private $filterHash = 'dontspamme';
        // set this to true, if you want to remove the last Ip's Octet
        private $anonymizeIp = true;
        // Configuration End
    

    Now we’ll need to add this code to all our pages (into the header), so it creates the session, that will be used to avoid the collect.php to be called directly.

    <?php
    include_once('gaproxy.class.php');
    $ga = new GaProxy();
    $ga->setupProxy();
    ?>

    We’re finish!, Now if collect.php is called directly without any previously loaded page, or by a script that doesn’t allow and keep cookies, the session will not be active and our file won’t be sending those requests to Google Analytics endpoint.

    Let’s resume what we did:

    1. We told analytics.js to fordward a copy of the hits to our local collect.php
    2. We added 3 lines of php into our pages, so a session is started and a tracking token is set.
    3. We’ve configured the gaproxy.class.php file with our real UA Number, plus we added a little hash to be able to filter the real hits to our property.

    Now we’ll need to configure 2 filters in our views:

    1. One excluding all hits where the field hostname does not include our filterHash.
    2. One replacing our filterHash by an empty string.
    spamfilter_1
    spamfilter_2

    As you may see in the code there’s a reserved function that will be used to check the requesting IP’s against blacklists, maybe using some throttling mechanism, checking the referrers against a blacklisted list that can be automatically updated,  etc. This is actually in progress as I need to think about the best way to achieve these feature, so any suggestion will be really welcomed. I’m planning to port it to other languages as Python or Ruby too, but I’d like to have a more polished PHP version before that.

    I know this workaround will not be accesible to everyone, or it may take some extra efforts to get it running but using a plain filter, but it has more benefits and you won’t need to keep your filters updated for each new spammer that starts to mess around with your account.

  • Handy dataLayer debugging tool for Chrome

    One of those posts that were laying around on my drafts and that I’ve decided to publish. I know there’re out there some good and well stablished tools that helps you to debug your Google Tag Manager implementation like the dataSlayer extension. But in the previous months I’ve been using a little JavaScript snippet that allows me to view in easy way the pushes that are being sent to Google Analytics in real-time in a nice way:

    This is how the debugging will looks like:

    tool

    It works for Chrome +36, and it’s based on a few lines of code, to start using it you’ll just need to paste those lines into your browser console, and you’ll start seeing any new dataLayer pushes that are sent for the current loaded page:

    Object.observe(dataLayer, function(c) {
        for(i=0;i<c.length;i++)
        {
    	if(c[i].type=="add")
    	{
                console.log("%cNew dataLayer Push\n", "color: blue; font-size:15px;");
    	    console.log(JSON.stringify(c[i].object[c[i].name], null, '\t'));
    	}
        }
    });
    

    You can grab the code too from this gitHub repository: https://github.com/thyngster/universalanalytics/blob/master/datalayer_monitor.js

    A nice way to have this little debugger at hand is to add a new bookmark in Chrome and set the URL to this piece of code. From then on, clicking on the bookmark will enable the debugging for the current loaded page

    javascript: (function() {
        Object.observe(dataLayer, function(c) {
            for (i = 0; i < c.length; i++) {
                if (c[i].type == "add") {
                    console.log("%cNew dataLayer Push\n", "color: blue; font-size:15px;");
                    console.log(JSON.stringify(c[i].object[c[i].name], null, '\t'));
                }
            }
        });
    })();
    
    bookmark

    Not the best debugging tool, but pretty handy, hope someone finds it useful at some point.

  • How to track an intranet or an hybrid app

    As we all know (do we?) Google Analytics uses cookies in order to work. This is, if for some reason the cookie can’t be set it won’t give any error but hits won’t be fired at all. A cookie is usually set for a FQHN (Fully Qualified Host Name). So if for example we’re going to track our intranet and we access it using an URL like : http://intranet/ Google Analytics is likely not going to work (it will depend on the browser that is accessing the page.

    There’s another situation where we may have problems using the official analytics.js. For example when using a different protocol than http/https, an example of this if when we load an html file from the local file system ( file://index.html ). You may think this is not a usual way to access a webpage, but it’s the way the most Hybrid Apps work.
    A native app for a mobile is usually build using some wellknown web technologies like: HTML5, JavaScript and CSS, and uses a browser engine (not the browser itself) to load the main content locally (using the file:// protocol), and here we’ll hit the second issue, Universal Analytics has an internal task named checkProtocolTask, it basically aborts the request if the current protocol does match http/https.

    Another example of devices using html files loaded from the local filesystem will be the SmartTV’s  for example.

    Fortunately Universal Analytics gives us the possibility to change those behaviours in order to manage those situations.

    Tracking a non FQHN domain name

    Even if it may work for some domains we better assure that it will run for all browsers, for this we need to set cookie’s domain to ‘none’ ,

    ga('create', 'UA-XXXXXXX-YYY','none'});
    

    or

    ga('create', 'UA-XXXXXXX-YYY', {'cookieDomain': 'none'});

    Tracking a locally loaded page

    In this case we’ll need to set the storage engine to none, and disabling the protocol check:

       ga('create', 'UA-123123123-123',{
          'storage': 'none', 
          'clientId':'{{UUIDv4}}'
      });
      ga('set', 'checkProtocolTask', null);
      ga('set', 'appName', 'MyApp Name');
      ga('set', 'appVersion', '1.2.2');
      ga('send', 'appview', {
            'screenName': 'My Home Screen'
      });
    

    Let’s take to the 2 important line in the code above;

    'storage': 'none'

    This line disables the default cookie storage system, and set’s it to none.

     'clientId':'{{UUIDv4}}'

    As we have disabled the storage engine, we’ll need to manually set the clientId (the cid parameter within our hits) , usually most devices offers a way to gan Unique Identifier, or we could grab the mac address and convert it to a UUIDv4 value 🙂

      ga('set', 'checkProtocolTask', null);

    This last line disables the protocol checking task, so the requests are not aborted because it doesn’t match the http/https protocols.

  • Learn how does Universal Analytics Cross Domain work

    Univeral Analytics tracking is based on cookies and on a randomly generated clientId. Yep, that’s it. Each time you visit a site using Google Analytics for the first time a new cookie is set in your browser with a randomly generated hash (clientId), that will be used by Google Analytics servers to identificate you in the subsecuent visits.

    Let’s see how the cookie looks:

    crossdomain_universal

    Any of those values can be modified using the JavaScript API, and they need to be set within the tracker creation. In a 99.99999% of cases you won’t need to deal with this, but it’s always good to know that we have the possibility to define our own vales. Let’s see how a default tag would work if we were setting it manually:

    ga('create', 'UA-XXXXXXX-YYY', {
      'cookieName': '_ga',
      'cookieDomain': 'thyngster.com',
      'cookieExpires': 60 * 60 * 24 * 730  // 2 years expiration date
    });>

    As we can see in the previous screenshot Google Analytics does not just use the randomly generated hash to track the user (device), as it only is a 10 digits number, so in a high traffic site or even if not having good luck it could end in generaeting clientIds collitions.  To reduce the chance of having a duplicated clientId under our property. To address this problem Google Analytics add the cookie creation timestamp value to the clientId value instead of only the random hash. If our “_ga” cookie value is: “GA1.2.2055842233.1422407281” , the clientId would be: “2055842233.1422407281” and not just “2055842233”.

    Going back to the crossdomain tracking,  Google Analytics uses the clientId (cid parameter on the hits) to identify the users (devices), and it will make sense to think that when the user goes to a different domain the same clientId should be used on the destination domain. In order to be able to have the same clientId in 2 different domains we’ll need to pass the clientId value to the  destination domain, that way analytics.js will be able to use that clientId value for the destination domain instead of generating a new one (remember that ga cookies uses 1st party cookies).

    The JavaScript tracking API does provide some in-build methods to grab the linker parameters, or even to “decorate” the links to the “external” domain we define.

    ga(function(tracker) {
    var linkerParams = tracker.get('linkerParam');
    });
    
    crossdomain_universal_2

    You can see that all info returned by the linker makes sense, but there’s a new value that is not in our origin domain. What it is?. It’s a value that Universal Analytics uses to assure the cookie data integrity and to prevent in some way to have our cookie info hijacked. Using the linker parameter into a domain name using Universal Analytics with the allow linker option enabled will force the cookie override with the cookie values specified in the url, and we don’t to have anything sharing a link to our site in some social network and therefore messing up all our data because all users coming from that link have the same clientId do we?

    In the previous Google Analytics versions, the only not randomly generated hash that was being used was the domainhash ( first value in the __utma cookie). It was generated by a pretty simple  algorithm (click here to see a PHP port for the domainhash algo) .

    This time Google Analytics want further and uses al algorithm that take some more variables in mind, and most of them are not fixed values as it was the hostname.

    The current checksum hash uses the following infos:
    • The current clientId value
    • The current browser user agent
    • The current browsers timezoneoffset ( the difference in minutes with the UTC time )
    • All the descriptions from the available plugins within the current user’s browser (taken from window.navigator.plugins)
    • Current year, day hour and minute

    Below you can see the values used to generate the checksum for the crossdomain linking on my Firefox Browser:

    crossdomain_universal_3
    So at this point we’ll have an array with all those values, Next step analytics.js takes it to join all those array values using a dot, forming the following string/hash:
    crossdomain_universal_4
    Universal Analytics uses then this hashing algorithm (taken from analytics.js code) to convert the previous string into a numeric value (yep, you guessed it right, the one that was in our linker parameters value)
        function La(a) {
            var b = 1,
                c = 0,
                d;
            if (a)
                for (b = 0, d = a[y] - 1; 0 <= d; d--) c = a.charCodeAt(d), b = (b << 6 & 268435455) + c + (c << 14), c = b & 266338304, b = 0 != c ? b ^ c >> 21 : b;
            return b
        };
    

    When implemeting a crossdomain tracking the generated hash on the destion domain NEEDS to match with the current one generated when creating the tracker with the clientId data in the URL If they don’t match the cookie value won’t be overrided, and therefore crossdomain linking will fail and the cookie value will be created with a newly random clientId.

    Those are the points we need to take in mind when thinking in the crossdomain tracking:

    • The linker value is only valid when using the same navigator version and using the same plugins (same browser needs to visit the origin and destination domain).
    • The crossdomain tracking won’t work if we land on the destination domain later than 2 minutes after the linker value has been generated. ie: the linker value has to be generated on the fly when the user clicks on the destination domain, if we update the links on the page load and an user clicks on the destionation domain after the default time limit it won’t work. According to Google’s documentation, there’s a grace period of 2 minutes for the linker value. And that’s why Universal Analytics provides the decorate function, this function generates the linker value when user clicks on a link or either when a form is submitted, without the need of coding any javascript listeners to update the links value in real time when the user clicks on them.
    • The clientId used when generating the hash needs to match the one on the linker parameters, so even if having a valid hash for the linking, changing the clientId values won’t be possible.
    • User’s may not change the computer’s timezone configured while going to the destination domain.

    This is how the crossdomain linking works on Universal Analytics and how Universal analytics tries to keep the cookie data integrity and prevent in some way the Universal Analytics cookie hijacking.

  • How does the Universal Analytics snippet work

      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
    
      ga('create', 'UA-123123123', 'auto');
      ga('send', 'pageview');
    
    

    The first thing that may attract your attention is the function parameters, they look like a real word. Let start talking about what an “isogram” is, according to the wikipedia:

    An isogram (also known as a “nonpattern word”) is a logological term for a word or phrase without a repeating letter.

    i,s,o,g,r,a,m are the variables names being used in the Universal Analytics Tracking Code, and we don’t want to pass a duplicate variable name to it. So actually this is just a pun from the Google guys since any other word with not repeated letters could have been used.

    You may wondering what values are being passed to the function, and to know that we’ll need to look to the bottom of the Universal Analytics Tracking Code:

    (function(i,s,o,g,r,a,m){ ... }
    )(window,document,'script','//www.google-analytics.com/analytics.js','ga');
    

    This means “window” variable is being passed as the “i” parameter, “document” as the “s” parameter and so on.

    At his point we could translate the Universal Analytics Tracking Code as:

          window['GoogleAnalyticsObject'] = 'ga';
          window['ga'] = window['ga'] || function() {
              (window['ga'].q = window['ga'].q || []).push(arguments)
          }, 
          window['ga'].l = 1 * new Date();
          a = document.createElement('script'),
          m = document.getElementsByTagName('script')[0];
          a.async = 1;
          a.src = '//www.google-analytics.com/analytics.js';
          m.parentNode.insertBefore(a, m)
    

    Let’s look to the code line by line to see what it does:

    window['GoogleAnalyticsObject'] = 'ga';

    It creates a new global variable named “GoogleAnalyticsObject” that holds the main Universal Analytics object name.

    window['ga'] = window['ga'] || function() {
              (window['ga'].q = window['ga'].q || []).push(arguments)
    }
    

    Here the main ga object is created. If it is already defined then nothing happens, otherwise it will be declared as a function.
    This function will create a temporary window[‘ga’].q array and then push all the arguments that we pass to the function to that temporary array ( ga(‘value’,value’); ). It’s done this way as it may  happen that the very first ga(); calls may come before UATC has been executed. It saves them in that array and after the code has been executed it will process them. From this point on, subsecuent calls will be directly processed.

    window['ga'].l = 1 * new Date();

    This sets a new object property with the current timestamp value. Yes, multipling a javaScript Date object by 1 returns the current Date variable timestamp value.

    a = document.createElement('script')

    A new a new script element is created and saved into a variable named ‘a’ . This is what what will be injected into the page’s DOM, but not before some other things are set.

    m = document.getElementsByTagName('script')[0]

    Here the code looks for the first ‘script’ tag available on the DOM at the runtime, This will be used to attach the Universal Analytics tag before it.

    a.async = 1

    Sets the asynchronous attribute to our script tag, this will ensure the script will be run at the first opportunity after the script source is downloaded and before the window.load event without blocking the page parsing. Some browsers support the “defer” attribute which is the same as “async” but it will comply with the scripts order, again without blocking the page load.

    a.src = '//www.google-analytics.com/analytics.js'

    Now the src attribute is set for the script tag. This is from where the UATC is loaded. As you may have noticed the Schema is not specified, so it will be loaded from the current loading page schema, that is, if the page is loaded from https, the script will loaded from https://www.google-analytics.com and if the page is not under https, it will be loaded from http://www.google-analytics.com

    m.parentNode.insertBefore(a, m)

    Here is where the Universal Analytics Tracking Script is being injected into the page’s DOM, The first ‘script’ found on the page is being passed, looking for its parentNode, and then injecting the Tracking Code right before it.

    So this is basically how the UATC code works. I’m aware that my english on this post may not be the best, so any improvement over my explanations will be welcomed.

    Note: Simo-san just adviced me about this post that talks exactly about the same topic: http://code.stephenmorley.org/javascript/understanding-the-google-analytics-tracking-code/ , so you may want to check it too 🙂

    Thanks to Ranyere Rodrigues for helping me to improve the post with some english corrections 🙂

  • Pushing data to the right Google Tag Manager dataLayer namespace

    It may happen that the site we’re tracking is using a custom dataLayer name, or that it’s using more than one Google Tag Manager accounts at the same time and therefore (it should) using 2 different dataLayer namespaces.  Most of people just push the info to window.dataLayer variable, but it could be window.myOwnDataLayerNS . So we’d need to adapt our dataLayer pushes to that variable name.

    So we’re going to setup a Macro that is going to take care of returning the right dataLayer namespace name for our current container. This way we’ll not messing around with other’s containers namespaces and our scripts will work in any container even if we’re using a custom dataLayer name.

    First, we’ll need to enable the “Container IDbuilt-in Variable within our container:

    Now we’re adding a new variable, that will take care of reading the current “Container ID” and looking for it’s right dataLayer namespace. ( Remember, you’ll be able to find this macro code at the bottom of this post )

    So, we should have now a new variable name {{getDataLayerNameSpace}} available in Google Tag Manager, that would be allow us to send the pushes to the right dataLayer variable for our current container, without the need to taking care of the variable name defined on the gtm snippet.

    Then, we’ll be able to send the pushes to the dataLayer this way:

        window[{{getDataLayerNameSpace}}].push(
                                 {'event':'someEventName',
                                  'eventValue','Some Event Value'
                                 });
    

    Did you have found this post useful ?, then go ahead and leave us a comment 🙂

     Macro Source Code

    function() 
    {    
        var gtm_objects = [];    
        var gtm_counter = 0;    
        for (var i in window.google_tag_manager) 
        {
            if (typeof(google_tag_manager[i]) == "object" && i.match(/^GTM-/)) {
                gtm_objects.push({'accountId': i});
            }
            if (typeof(google_tag_manager[i]) == "object" && !i.match(/^GTM-/)) {
                gtm_objects[gtm_counter].dataLayer = i;
                gtm_counter++;
            }
        }
        for (var i in gtm_objects) 
           if (gtm_objects[i].accountId == "{{Container ID}}")
                return gtm_objects[i].dataLayer;
    }