Blog

  • #proTip – Proactively Cookies Auditing with Google Tag Manager and Google Analytics

    Since GDPR was announced and more even with the rise of Safari’s ITP and the other upcoming protection feature by the other major browsers, the concers about users privacy was grown which is really nice.

    But despite browsers taking some actions to prevent the abuses, it’s difficult to follow up the current cookies being used in our sites because we may end finding new ones that has been added by the developers, or some new pixel added by someone into our TMS.

    For helping on this task, some weeks I launched Cookies.Report which is a online tool for checking the cookies generated by a site. It has some special features that will make the report more useful than just looking the cookies tab in our browser:

    • Report it’s run within a fully clean browser state. This is we won’t be targetting personal cookies that we may have because we’re logged somewhere else, or old cookies that we may have in place since time immemorial
    • The report will split the first and third parties cookies, so you can easily identify them
    • The report will tell you which cookies are set within a TMS ( currently Google Tag Manager and Tealium are supported ), or which ones are set in some other way ( hardcoded tags )
    • You will be able to export the cookies in xls, csv or pdf to share it with anyone else

    Proactively Tracking Cookies

    This is going to be a easy code, we’ll just to use the following snippet to pass a list of current cookies names into the user browsers into a variable and then we could pass it as a custom dimension in our pageview/event hits!.

    function(){
        document.cookie.split(';').map(function(c) {
            return c.split('=')[0].replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
        }).join("|");    
    }

    There’s a point to have in mind, if it’s the first time the user gets into the page it may happen that our pageview fires before our other javascripts are loaded and therefore we may be missing that data just on the landing pages.

    You could use a non-interactianal event that fires on DomReady of Window.load if this is a issue for you.

    Having the code needed to get the cookies list, we may think in some other more explicit workaround that may save hits. For example: We may generate a hash of the current cookies list, and just send an event each time that it changes, this way we’ll only be sending the data once each time a new cookie is added.

    After we start receiving the data, we will be able to do/know a lot of interesting things.

    • When a new cookies was added to the site
    • Which are the most set cookies
    • In which pages are the cookies being set
    • Setting an alert if dimension hold some forbidden cookie name

    Hope someone find this useful in some way. Happy to listen to any comment you may have about this approach 🙂

  • Setting GA Cookies Server Side with PHP – ITP Workaround

    Yeah, I know, this has been done before by others, but since I had this piece of code around, I decided to publish it.

    It’s not going to be usual, method since we’ll be relying on sending a duplicate hit to our tracking subdomain. That way we’ll be able to have our stuff tracked server-side in a secondary dimension while those hits will take care of setting the cookie expiring time on the main. isn’t it cool?

    What we’ll need

    1. A subdomain for our domain, for example collect.domain.com ( it’s better if we don’t make it that obvious )
    2. A customTask added in our tags, in order to send a hit copy to our subdomain.
    3. We’ll need some PHP code that will receive the hit details ( payload, cookie name, etc ), will have the job of writting the cookie back and also will be taking care of the CORS headers.

    Working Flow

    2. Let’s Start: Setting up our customTask

    The first thing we need to do is to create a custom Variable with our customTask code. You can find the code below.


    Copy the code

    function() {
        var gaProxyEndpoint = 'https://sub.domain.com/collect/';
        return function(customTaskModel) {
            customTaskModel.set('cookieUpdate', false);
            var originalSendHitTask = customTaskModel.get('sendHitTask');
            customTaskModel.set('sendHitTask', function(model) {
                originalSendHitTask(model);
                try {
                    var gaCookieName = model.get('cookieName');
                    var base64encodedPayload = btoa(model.get('hitPayload')+'&ckn='+gaCookieName);             
                    var xhr = new XMLHttpRequest;
                    xhr.withCredentials = true;
                    xhr.open("POST", gaProxyEndpoint, false);
                    xhr.send(base64encodedPayload);
                } catch (err) {
                    originalSendHitTask(model);
                }
            });
        }
        ;
    }

    After we have the variable, we’ll need to tell the tags to use it a customTask, if you’re already using a customTask you’ll need to sort it out yourself mergin this piece of code with your current code.

    As you may see on the following screenshot, there’s an extra field set. It’s name “cookieUpdate”, and we’ll need that set to false because otherways analytics.js will keep updating the cookie expire time after we did the same, therefore the cookie time will be reset to 7 days on Safari.

    3. Let’s finish: Setting up the PHP files

    We’ll need to upload the php files to our subdomain

    Files: https://github.com/david-vallejo-com/ga-proxy-itp

    We are all set now!

    After we publish everything, for each hit send via GTM, a request will be also be sent to our endpoint, which will take care of everything so cookies are written from the server.

    There’re some tweaks you may want to add to the customTask, for example you may want to check if it’s a Safari browser, and just run the custom task if the check is true. Just give a try to “Detect Safari JavaScript” search on Google 🙂

    Extra

    As you may have read, we could also set the PHP file to send a copy of the hits. For enabling this feature, just open the index.php and uncomment the following line

    // private $propertyId = 'UA-XXXXXXX-UU';

    The good thing about this is that the payload goes encoded using BASE64, so it won’t be detectable by adblockers at all. So you may end finding some better sessions info on the secondary property?.

    ok, I know, most adblockers will likely block the analytics.js file so, none of this will make a difference, but, even if it’s not a good idea you may plan to server the file locally with a different name, do you follow me? 🙂

    If someone gives it a try just let me know!

  • #tip – Grabbing current dataLayer variable name within GTM

    This is going to be a quick #tip post. and it’s coming from a post on Measure Slack.

    Let’s learn how to grab the current dataLayer variable name within GTM. We’ll need to create a variable with the following code:

    function() {
        return Object.values(window.google_tag_manager).find(function(e) {
            if (e.dataLayer) return true;
        }).dataLayer.name;
    }

    Now our variable should hold the dataLayer name 🙂

  • Send APP+WEB Hits to any remote endpoint

    Google released APP+WEB Properties some weeks ago now, and one of the most missed features looking back to Universal Analytics, is the chance to work with a customTask ( Hi Simo!!! ).

    In this post I’ll cover how to send a copy of the hits to anywhere we want, in case we want to hold a copy of them, or processing them in some other place (like snowplow)

    First, we need to take in mind that APP+WEB hits, may contain +1 hits into their payload, therefore we’ll splitting the hits in single hits before sending them to our endpoint. If you want to learn more about how APP+WEB Protocol works you can take a look to this post

    APP+WEB API makes use of navigator.sendBeacon to send the hits, so we’ll writting a proxy pattern to listing to sendBeacon calls in order to be able to grab the payloads and sending them back to our own endpoint. In the middle of this process we’ll be splitting the hits in single hits.

    On this specific example we’re sending the data via POST, but it can be easily be send as a QS payload. Just feel free to modify the code at your needs ).

    In order to have this working, we’ll need create a new TAG in Google Tag Manager ( or just add this code into your site in some other way ) with the following code. ( feel free to modify the endpoint variable at the end. Let’s call it: “TOOL – APP + WEB Remote Logger”

    <script>
    "use strict";
    (function() {
        try {
            var proxied = window.navigator.sendBeacon;
            window.navigator.sendBeacon = function() {
                var parse = function getQueryParameters(str) {
                    return (str || document.location.search).replace(/(^\?)/, "").split("&").map(function(n) {
                        return (n = n.split("=")),
                        (this[n[0]] = n[1]),
                        this;
                    }
                    .bind({}))[0];
                };
                // Check if it's a APP+WEB hit
                if (arguments && arguments[0].match(/google-analytics\.com.*v\=2\&/)) {
    
                    var payloads = [];
                    var qs = arguments[0].split("?")[1];
                    // APP+WEB Can hold more than 1 hit on the same payload, we'll send separete this, let's split them
                    if (arguments[1] && !qs.en) {
                        arguments[1].split("\n").forEach(function(e) {
                            var tmp = Object.assign(parse(qs), parse(e));
                            payloads.push(tmp);
                        });
                    } else {
                        payloads.push(qs);
                    }
                    var data = {
                        records: payloads
                    };
                    var endpoint = "https://myownendpoint/g/collect";
                    fetch(endpoint, {
                        method: "POST",
                        body: JSON.stringify(data)
                    });
                }
    
                return proxied.apply(this, arguments);
            }
            ;
        } catch (e) {}
    }
    )();
    </script>

    After we have that tag in place we’ll need to use the tag secuencien with our pageview tag ( this needs to run just one, so don’t add it to other hits ).

    And now we’ll only need to publish our container, and a copy of the hits will be sent to the endpoint we’ve defined on the code! Easy!

  • Release: Client-Side dataLayer validation Library

    If you’re a web analyst, you SHOULD be worried about data quality, we want to have data, but we need this data to be correct, there’s no point of having tons of corrupted data that we won’t be able to sue and for this we need to monitor our implementations regularly to be sure our data is always being reported properly.

    Since We all are web analyst I’m pretty sure we are relying a flawless dataLayer ( are we? 🙂 ). But I’m sure that at least once in the past our precious data holding variable ( aka “datalayer” ) ended messed up for whatever reason ( a refactor task that messed up some keys, some JS code that overrided a value ).

    It’s true there are out there plenty of solutions to monitor our implementations setups like Observe Point , Hub Scan , which do a real great job, but that maybe have too many features that we won’t be use at all.

    On this post we’ll talking about build a dataLayer model monitoring tool, ( yep, Simo and I already published an automatated testing tool some time ago: https://www.simoahava.com/analytics/automated-tests-for-google-tag-managers-datalayer/ ) , but that implies having some IT infraestructure, the checks are going to be done each day, it will only be tested under just one JS engine.

    So this time my proposal is doing the monitoring client-side. This will allow us to have a full sampling from almost any browser/connection/location on how the dataLayer is being reported for users!.

    The advantages are:

    • We’ll get alerts in real time
    • No need for any extra servers, infrastructure ( we’ll be able to use GA )
    • We’ll have data for all kind of browsers and users
    • Easy setup

    For this we’ll be using a little validation library that I wrote some years ago, that will be take care of validatin the current dataLayer model against a predefined dataLayer Schema rules.

    Let’s start adding a tag with the library on GTM, we’ll just need to copy and paste the following snippet, there’s not need to change any on it

    /* Code Moved to GitHub*/
    Get the snippet from the following URL: 
    https://raw.githubusercontent.com/david-vallejo-com/cs-datalayer-monitor/master/build/bundle.min.js

    Next thing to do is defining our dataLayer validation Schema, which is defined this way:

    var mySchema = { "page": {
                           "author": "required",
                   },
    		       "user": {
    				        "id": "integer",
    				        "name": "contains:David"
       		      }
    };

    We’ll need to define each key we want to monitor, and the validation rule we want to apply.

    Right now the following rules are available:

    • present ( this checks if a key is present, despite it’s set as null, undefined, empty string )
    • required ( this requires the key to have a value )
    • contains ( case sensitive )
    • notcontains ( case sensitive )
    • regex ( case insensitive )
    • integer
    • float
    • string
    • object

    If the post gets enough attention I’m planning on adding support for “contains”, “regex”, comparisions ( <=> ), and chained checks.

    Then we’ll need to call the validation library:

    var validationResults = window._validateDataLayer(myDatalayer , mySchema ,false);

    The dataLayer validation library will return an array of errors found in the datalayer if any are found. From that on we could for example fire an event to GA, or notifing any other tool we want.

    I’m attaching a small snippets that take care of grabbing the current Google Tag Manager dataLayer model and then it pushes the data to the dataLayer, from that point we can do whatever we want with the info.

    // This goes after the library code above.
    <script>
    /* 
    [REPLACE WITH THE CODE FROM GITHUB]
    */
    
    var myDatalayer = { user :{ id: 1, name:'david' }};
    var mySchema = { "page": {
                           "author": "required",
                   },
    		       "user": {
    				        "id": "integer",
    				        "name": "contains:David"
       		      }
    };
    var validationResults = window._validateDataLayer(myDatalayer , mySchema ,false);
    
    if(validationResults && validationResults.length>0){     
            dataLayer.push({
                event: 'dataLayer-validation-errors',
                errors: validationResults
            });
    }
    </script>

    You may be thinking that this may led on hundreds of pushed being send to GTM, but the library has a throttling cookie, which will just send 1 event per browser session, that way we’ll be only notified once per user/day.

    This should work for any other TMS rather than GTM, but for GTM we need to have an extra thing in mind, and it’s WHEN we fire the validation tool.
    We need to defined at which execution/event time we want to check the data. I suggest to fire the validation on Window.Load event ( gtm.load ) , since in almost most time the dataLayer model will be totally loaded, but if our setup is relying on All Pages (gtm.js) and we expect the data to be available on that event ( or any other custom one ), we’ll be able to set the triggers for our monitoring tag for that same event! )

    The new version includes a dataLayer grabing help, so you would only need to do the following.

    <script>
    /* 
    [REPLACE WITH THE CODE FROM GITHUB]
    */
    
    var mySchema = { "page": {"author": "required"},
    	       "user": {
                           "id": "integer",
    		       "name": "contains:David"
       	       }
    };
    var validationResults = window._validateDataLayer('gtm', mySchema ,false);
    if(validationResults && validationResults.length>0){     
            dataLayer.push({
                event: 'dataLayer-validation-errors',
                errors: validationResults
            });
    }
    </script>

    Let me know your thoughs and improvement ideas!

    Official Library Repository: https://github.com/david-vallejo-com/cs-datalayer-monitor

  • Technical Guide to Global Site Tag ( gtag.js )

    Global Site Tag was introduced by Google back in October 2017. As the name suggests it was launched in order to unify all the different tracking libraries that we can use for Google Products, Adwords, Google Analytics, DoubleClick, etc.

    In my opinion the launch of APP+WEB Properties has set an inflexion point about the gtag.js use, since it’s now when it is really coming into the scene, and it’s just for a simple reason: before APP+WEB it was just a duplicate library not offering anything extra from the legacy libraries, meaning that there wasn’t a real reason to move on into Global Site Tag tracking. But now Google launched the first product’s JS library 100% based on GTAG.js, it makes the perfect moment to explain how it works 🙂

    What’s the Global Site Tag?

    It’s an API and a tagging platform for all Google Products ( Google Analytics, Google Ads, Google Marketing Platform, APP+WEB ), which will help us to have an standarized implementation that will be able to work with any products.

    It’s based on a list of predefined events ( “purchase”, “page_view”, “add_to_cart” , etc ),

    This means that we’ll just need to setup a “purchase” event and all the transactional data could be sent to Adwords Conversion Pixel, to Google Analytics or to other any supported tool.

    For this task Google has pre-defined a list of events, each of them supported a predefined parameters, and GTAG.js will take care of mapping this event data to any of the supported products by Global Site Tag at our convenience.

    How do I Add GTAG to my site

    It will be as simple as adding the following snippet to our site, preferible before closing the </head> tag.

    <script async src = "https://www.googletagmanager.com/gtag/js?id={{TRACK_ID}}"></script>
    <script>
      window.dataLayer = window.dataLayer || [];
      function gtag() {
        dataLayer.push(arguments);
      }
    gtag('js', new Date());
    gtag('config', '{{TRACK_ID}}');
    </script>

    Of course we gonna need to update the {{TRACK_ID}} with the proper value.

    How does GTAG know where to send the data?

    GTAG.js will now where it needs to fire the data because of the {{TRACK_ID}} value. Each of the Google Products “TrackID”s start with a prefix will tells google server with code to provide.

    For example if we’re setting up a Google Analytics tracking, the {{TRACK_ID}} will start with a “UA-” prefix.

    I’m attaching a table with the current possible values

    PrefixTool NameTrack ID Name
    AW-AdWordsConversion ID
    DC-Double ClickAdvertiser ID
    UA-Universal AnalyticsProperty ID
    G-APP+WEBMeasurement ID

    Then we’ll have the ‘config’ events where we’ll sending the initializacion and extra parameters.

    For example if we want to enable the cross-tracking for our Universal Analytics setups we’ll be using the following

    gtag('config', 'UA-XXXXXXX-Y', {
      'linker': {
        'domains': ['domain.com']
      }
    });

    Then if we want to setup a Universal Analytics pageview tracking + Adwords Remarketing ( both firing for all pages ) >

        window.dataLayer = window.dataLayer || [];
        function gtag(){dataLayer.push(arguments);}
        gtag('js', new Date());
    
        gtag('config', 'UA-XXXXXXX-Y');
        gtag('config', 'AW-1231231231');

    GTAG will know that we want to send the information to Adwords and Google Analytics and will take the stuff from here and fire everything for us. For example if we send a purchase event, it will send a transaction to Google Analytics and a conversion to Adwords

    How does it internally works

    GTAG.js is backed up using Google Tag Manager, maybe it’s not an exact definition of what GTAG.js is, but I really feel that we could mostly think on it as a “predefined” container that supports all Google Products tags and that takes care of mapping the data to all of them in an automatic way. ( NOTE: this may be a way to simplistic way to define it, but hope you get the idea )

    Since it relies on GTM code, and henceit has a dataLayer ( which will be shared with GTM if the site is using it also ), and that’s why you find sites not using Google Tag Manager and still having a dataLayer variable and even some of the default events like the gtm.dom and gtm.load.

    Let’s take a look to the window.gtag function:

    function gtag() {
     // Takes all Arguments and push them back to the dataLayer
     dataLayer.push(arguments);
    }

    Yep, it’s just a proxy, any parameters you send to gtag are pushed back to the dataLayer as an Arguments variable.,

    Arguments Type Object is an Array like variable that is only avaiable within the function internal scope and that holds a list of all parameters being pass to the function.

    Despite all these technical definitions, and just get the point all the data passed to gtag() function it’s forwarded to the dataLayer as an Array

    Let’s check the following flow to understand how it works

    GTAG.JS WORKING FLOW

    Did you know that you can tell GTAG.js to use an specific dataLayer name instead of the default one? , just ad a “l” (it’s a lowerCase “L”) parameter to you loading script

    <script async src = "https://www.googletagmanager.com/gtag/js?id={{TRACK_ID}}?dl=myOwnDataLayerVariableName"></script>

    Which events are currently supported by GTAG.js

    I tried to build a list with all the events I was able to ( as 15th Auh 2019 ), but please take in mind that this list may be missing some of them, and that Google is likely going to add new ones in the future. Refer to official documentation for more curated data.

    EventCategoryEEC DataNon-InteractionalParameters
    add_payment_infoecommerceNoNo
    add_to_cartecommerceYesNovalue
    currency
    items
    add_to_wishlistecommerceNoNovalue
    currency
    items
    begin_checkoutecommerceYesNovalue
    currency
    items
    coupon
    checkout_progressecommerceYesNovalue
    currency
    items
    coupon
    checkout_step
    checkout_option
    exceptionerrorsNoNodescription
    fatal
    purchaseecommerceYesNotransaction_id
    value
    currency
    tax
    shipping
    items
    coupon
    refundecommerceYesNotransaction_id
    value
    currency
    tax
    shipping
    items
    remove_from_cartecommerceYesNovalue
    currency
    items
    set_checkout_optionecommerceYesNocheckout_step
    checkout_option
    generate_leadengagementNoNovalue
    currency
    transaction_id
    loginengagementNoNomethod
    searchengagementNoNosearch_term
    select_contentengagementYesNoitems
    promotions
    content_type
    content_id
    shareengagementNoNomethod
    content_type
    content_id
    sign_upengagementNoNomethod
    view_itemengagementYesYesitems
    view_item_listengagementYesYesitems
    view_promotionengagementYesYespromotions
    view_search_resultsengagementNoYessearch_term
    page_viewenhanced measurementNoNopage_title
    page_location
    page_path
    screen_viewenhanced measurementNoNoscreen_name
    app_name
    app_id
    app_version
    app_installer_id
    scrollenhanced measurementNoNopercent_scrolled
    clickenhanced measurementNoNo
    timing_completetimingNoYesname
    value
    event_category
    event_label

    Hope this post helps you to lose some fear to the GTAG.js and helps you understand how face your upcoming APP+WEB implementations with some more background about how things work 🙂

  • Technical overview of new APP+WEB Properties

    Some days ago, Google announced a new upcoming property type for Google Analytics, they called them “APP + WEB”. And yes, the name says it all, finally we’re going to be able to measure our apps and websites at the same time. This has been for years one of the biggest handicaps of Google Analytics, and not only that, when Firebase came into the scene, we had ended having two platforms to measure apps, double the SDK’s and despite having all this tools we were not able to measure users accross platforms properly.

    But Google finally took the right step and they’re going to merge everything within the same platform, and also they are moving away from a “session” based tracking model to a events” based tracking model. Yes, you’ve heard it right, sessions as we do know them now will be gone ( don’t worry we’ll have sessions anyway, continue reading ..)

    This post won’t be covering the basic details about this new properties details, how the reports work since that’s all is covered by other authors in the blogs: New App + Web Properties in Google Analytics by Krista Seiden or A new way to unify app and website measurement in Google Analytics on Google Blog , or a google all-in introduction by Simo Ahava HERE .

    The star feature of the new properties is that they offer a way to unify our measurement strategy across different devices in one single place. Yay! ,
    On this post we’ll be learning how the new properties work, from a technical/implementation point of view and which are the most important changes compared to the current Google Analytics tracking.

    The main change on the tracking side and that from now on ALL is an “event” . The new platform is based on GA4F ( Google Analytics for Firebase ) , so we need to define everything ourselves.

    We need to start sending events and then based on these we’ll build the reports. In any case Google is including a default web tracking model within the APP+WEB properties which will allow us to have the most web relevant events in place and will be also offering some in-built parameters reporting ( same way we previously had dimensions and metrics based on events, returning visitors, etc ).

    Events

    event: {
            param1,
            param2,
            param3,
            paramN,
            user_parameters: {
             	         userParam1,
                             userParam2,
                             userParamN
            }
     }

    In the Schema above we can see the kind of data we can send along with an event to a APP+WEB property. Note that there’s a reserver parameter key called “user_parameters” that will hold and object with a list of the parameters related to the user. ( By the way we’ll need to define these in the UI first ).
    As you may noticied, there’s no longer any custom dimensions or metrics, so there are not cdX or cdN keys on our hits. Now we have Event Parameters and User Parameters instead.

    Measurement Protocol v2

    Along with the new APP+WEB properties, Google released a new protocol ( it’s more a v1 protocol version improvement rather than a new version ).

    If you usually work on debugging Google Analytics implementations you’ll be recognize most of th e parameters that you’ll see in the hits

    As an example, check the image below for how a simple page_view event hit looks like. I’m pretty sure you’ll feel familiar with most of keys.

    New Parameters List

    I tried to document the most import new keys that are part of the new Measurement Protocol. Here is a list of them:

    enEvent Name
    _fvFirst Visit
    _ssSession Start
    sidSession ID
    segSession Engaged
    sctSession Count
    _pCache Buster?
    _etEvent Time ( time since start for this event )
    ep.[a-z]Event Paramter ( String )
    epn.[a-z] Event Parameter ( Number )
    up.[a-z] User Parameter ( String )
    upn.[a-z] User Parameter ( Number )

    DISCLAIMER: APP+WEB is currently in beta and it’s likely adding new parameters in the upcoming months to cover all the current Google Analytics functionality / data points.

    Transport details

    Actually in Universal Analytics, the hits may use 3 different transport types:

    new Image() ( used for GET hits )
    XMLHttpRequest ( used for POST hits )
    sendBeacon ( Optional transport )

    It looks like the new library just uses sendBeacon for sending the hits, which looks like a good choice looking to the current functionality adoption by browsers:

    We also can find a new endpoint: Now the hits will be send to the following URL ( note the “g” )

    https://www.google-analytics.com/g/collect

    So, you said that we’ll have to look at the Request Payload in order to get the current hits data, is this correct?

    Not at all, what we said is that now hits are sent using the POST method (sendBeacon uses POST method to work). But still we can POST data to an URL that have a querystring.


    This means that on the new measure protocol the data is sent to the endpoint using and hybrid approach, a mix of a QueryString and Request Payload are used for sending the data. Some data is sent in the Query String and some details “may” be sent in the Request Payload ( POST Data ). In overall common hit details like the clientId, the language, the screen resolution ( all this data will be shared by all the events ) will be sent using the Query String, and the events details will be send in the Request Payload. Anyway we’ll see that this won’t be this way in all cases, since there will be differences on how the hit payload it send depending if the hit has one event, or more than just one.

    Continue reading to learn how to identify the different hit formats you’ll find.

    Multi Event Hits

    In the newly released protocol, we can send multiple events within one single hit request ( beware this is not the same as the previous “batches” in Universal Analytics ).

    This is a nice feature because it will help us reducing the number of requests that our site will be loading.

    But, wait a second…

    In the previous table you showed there was only one slot key for the event name, how is it supposed to work if we can send more than 1 event?.

    We already learnt that the new protocol uses a mix of QueryString and Request Payload in order to send the data to the endpoint. And we also briefly mentioned that depending on the number of events travelling within the hit the behaviour could be differents.

    Let’s take a deeper look to how it works:

    So, events details may go into the Query String or within the Post Data, depending on the events count in the hit. This helps on reducing the number of request send to Google Analytics servers and also helps reducing the payload size, since the details shared by the events are only send once. Double Win!.

    Events Queing

    This is not directly related to the measurement protocol itself, but it’s one of the first things that I saw when I started playing around with APP+WEB and it made me think I was doing something wrong.

    You may have noticed that when you push an event using the official GTAG API the data its not flowing to the endpoint as soon as you push it, There’s a small delay between the time you push the event and the hit shows up in the network tab. DON’T WORRY, this is normal, the new GTAG library, queues the events and dispatch them altogether each 5 seconds ( +/- ), remember that the new protocol allowed to send multiple events on each hit?, this take advantage of that feature.

    Debugging

    With all the previous details, you should be able to understand and read most of the details from the hit requests, but you can make your life easier using some extension that will parse the requests details properly and show you the details in a more friendly way.

    If you want you can take a look to my GTM/GA Debug Extension which actually support GA4F ( Google Analytics for Firebase ) hits.

    Cookies and Sessions

    The APP+WEB properties use not 1 but 2 cookies in order to perform the tracking on a website. The first one is an old friend of all us:

    “_ga” cookie, nothing changed on it, it will be taking care of holding the current user ClientID.

    “_ga_XXXXXX” cookies We’ll be find a new cookie for each of the Measurement ID’s we’re using on our site. Meaning that if we have a dual or triple tracking setup we’ll have the same amount of cookies, since they keep they own namespace and cookie.

    Let’s review all the technical details about this new cookie

    Cookie Name

    _ga_MEASUREMENT_ID

    Cookie Domain and Path

    The cookie is set to the nearest root domain name and it uses ‘/’ path by default

    Cookie Duration

    2 years

    Cookie USe and Format

    Do you remember back in Urchin or legacy analytics (ga.js) days when the session data was calculated via user cookies?, Then we switched to Universal Analytics and everything was being calculated server-side on Google side.

    Now with the new APP+WEB properties we’re back to the roots ( almost ) since it uses a similar approach as the first Gooogle Analytics versions ( remember the UTMA and UTMB cookies? ), but with one small difference, the visits attribution will be still calculated on Google side ( no UTMZ cookie ). So that’s the main use for this cookie, keeping track of total sessions and current session state.

    Check the following image for a full cookie definition ( I have not found the use of the last cookie value yet )

    WEB MODEL

    Google is offering a pre-built reports and events model for websites tracking. So we don’t need to start from scratch. Therefore we’ll be able to send page_views, and APP+WEB will take care of collections some extra data for these events without us needing to define any extra parameters ( like the page_titles, sources, mediums, browser details, geographical details ,etc )

    If you take a look to any APP+WEB Property you’ll notice that you have at least 4 different events, despite you may be only sending a “page_view” event:

    I’m sure that you may be thinking, What kind of magic is this?, I didn’t setup any ‘user_engagement‘ , ‘session_start‘ or “first_visit” events on my setup, just the “page_view” one.

    The same way that APP+WEB has some in-built parameters for the “page_view” events like the source, medium, title, browser, etc . Google will use generate some auto-events based on some parameters from the hits.

    user_engagementFrom hits including the key “seg” in the payload.
    session_startFrom hits including the key “_ss” in the payload.
    first_visitFrom hits including the key “_fv” in the payload.

    HEY WAIT! Remember that almost everyone around is mentioning that sessions won’t be longer available on GA, that’s not a 100% true statement, it’s true that we’re moving to an event-tracked model instead of a sessions-based mode, but that doesn’t necesarilly mean that we won’t have sessions count at all. Now we’ll have some events to calculate our old sessions metrics along with some other ones. Based on the the current auto-events on App+Web, we’ll have:

    user_engagementCan be used to calculate the bounce rate
    session_startCan be used to calculate the total sessions
    first_visitCan be used to calculate new VS returning visitors

    Enhanced Measurement

    The “page_view” is the core event for web tracking, this didn’t change on this new version, but APP+WEB offers something called “Enhanced Measurement” which will help us setting some tracking in our sites without even needing to do anything else but turning on a checkbox.

    • Youtube Video Tracking
    • Outbound clicks ( Click Listeners )
    • File Downloads ( Click Listeners )
    • Scroll Tracking ( 90% event )
    • Pageviews ( on page load or history changes )
    • Site Search Events
  • Google Tag Manager Custom Template – BrainSINS

    Today’s custom template ifs for: BrainSINS , a personalization platform based in Spain.

    Just import the template into your container and set the Token that you’ll find in your user corner.

    Downloadhttps://github.com/thyngster/gtmtemplates/tree/master/BrainSINS

  • Detecting if Google Analytics is being blocked using a Google Tag Manager Custom Template Tag

    Today I’m releasing a small Custom Template for Google Tag Manager that will take care of notifying the dataLayer about if Google Analytics is currently being blocked by the browser.

    Some days ago, I published the following tweet, to get some user’s feedback on Twitter. The approach not really bad, but having to deal with code is not the best solution for most people.

    I decided today to build a quick Custom Template to take care of checking if Google Analytics is being blocked. We’ll simply using the sendPixel library from Custom Templates. If you didn’t know if sendPixel library allows you to fire an onSuccess or onFailure callback functions.

    Then based on these callbacks the template will be push the data accordinlty to the dataLayer. And from there you may do whatever your want, like notifying an external application with an event, or showing the user any alerts ( this was just a dummy idea, please don’t annoy the users on this ).

    sendPixel(url, onSuccess, onFailure)

    The Custom Template has some configurations available to fine-tune que current behaviour of the tracking.

    • You can decide if sending an event if GA is being blocked or if GA is NOT being blocked
    • You can individualy define the event names for each of the previous pushes
    • You can set how often you want to the template to check if GA is being blocked. On each pageview, once per session ( 30 min ) or a personalized time period.

    If you’re insterested on trying it, you can DOWNLOAD it from my github repo:
    https://github.com/thyngster/gtmtemplates/tree/master/Google%20Analytics%20Block%20Checker

  • Release: Yandex Metrica Debug Extension

    About one month ago I started to work on a Google Tag Manager Custom Template for Yandex Metrica, I must say it was my first contact with it apart from installing the default snippet some years ago on this same blog.

    In order to ease my testings for the template I ended building a Browser Extension which I’m releasing today for Chrome, Firefox and Opera.

    I tried to cover all the differents hits that Yandex may send, but of course I may be missing some of them ( more likely to be on the beta JS library ). The extension currently support the following hit types:

    • Hit (Fields Reported: URL, Title, Referrer, full payload details)
    • reachGoal (Fields Reported: Goal ID, Currency, Value, , full payload details)
    • setUserID (Fields Reported: UserID, full payload details )
    • params (Fields Reported: Key,Value Up to 5 levels , full payload details )
    • userParams (Fields Reported: Key,Values Object , full payload details )
    • notBounce(Fields Reported: none , full payload details )
    • webvisor (Fields Reported: All Post Payload for webvisor is reported in a beautified way, full payload details )
    • ecommerceDetail (Fields Reported: Product Details , full payload details )
    • ecommerceAdd (Fields Reported: Product Details , full payload details )
    • ecommerceRemove (Fields Reported: Product Details , full payload details )
    • ecommercePurchase (Fields Reported: Purchase Details+ Product Details, full payload details )

    It may happen that the extension is not able to detect the hit data type, and it will be shown as undetected row:

    Don’t worry about this kind of rows in the reports they will be gone gradually as long I continue learning about Yandex Metrica Protocol and API.

    I’d define the current extension status somewhere between Alpha and Beta. So have in mind that you may find bugs while using it in your sites. Please don’t hesitate to contact me so that way I can improve the extension functionality. 🙂

    CHROME WEB STORE ( INSTALL LINK ) : https://chrome.google.com/webstore/detail/yandex-metrica-debugger/ehppjfimmbekmmponndiiiofmmdmgjlp