Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Jeroen Roscam 13 posts 113 karma points
    Nov 12, 2018 @ 14:15
    Jeroen Roscam
    0

    Usplit and Google Analytics: 'No experiment code found'

    Hi,

    I run into a problem with the integration of Usplit and Google Analytics.

    At first it seemed to work fine. Every experiment I set up in Umbraco, automatically shows up in G-A. But, the experiments don't show any results.

    G-A gives as reason: 'No experiment code found.' and 'No Google Analytics tracking code found.'

    Does anyone have any experience with this? Shouldn't G-A get the codes from Usplit automatically? The connections to the Google API and to the G-A account have been succesfully authorized.

    Thanks, Jeroen

  • Paul McCarthy 39 posts 160 karma points
    Jan 22, 2019 @ 16:50
    Paul McCarthy
    0

    I'm in the exact same situation. Did you ever get to the bottom of this Jeroen?

  • Paul McCarthy 39 posts 160 karma points
    Feb 11, 2019 @ 23:08
    Paul McCarthy
    0

    Going to answer this in case anyone else is stuck. So, from what I can tell, the Google script fragment that is supposed to be loaded into the page head is not being loaded. I'm running Umbraco 7.7.9, and uSplit isn't currently marked as tested for 7.7 so not sure if this an Umbraco issue or specific to our installation.

    Anyway, here's how I got around it. I'm aware this is one hell of a hack and there are probably more elegant ways of achieving it, but here goes...

    On your master page, add the following..

    // check if the page being loaded is running an experiment     
     @if (((Umbraco.Core.Models.PublishedContent.PublishedContentWrapped)Model.Content).Unwrap().GetType() == typeof(Endzone.uSplit.Models.VariedContent))
        {
            var myExperimentId = (((Umbraco.Core.Models.PublishedContent.PublishedContentWrapped)Model.Content).Unwrap() as Endzone.uSplit.Models.VariedContent).AppliedVariations.First().GoogleExperimentId;
            var myExperimentVariant = (((Umbraco.Core.Models.PublishedContent.PublishedContentWrapped)Model.Content).Unwrap() as Endzone.uSplit.Models.VariedContent).AppliedVariations.First().GoogleVariationId;
    
            // add this value to a cookie so you can get it on front end for javascript
            HttpCookie googleExp = new HttpCookie("googleExpId");
            googleExp.Value = myExperimentId;
            HttpContext.Current.Response.Cookies.Add(googleExp);
    
            HttpCookie googleExpVariant = new HttpCookie("expVar");
            googleExpVariant.Value = myExperimentVariant.ToString();
            HttpContext.Current.Response.Cookies.Add(googleExpVariant);
    }
    

    Then the fun starts. You need to do your own oauth dance with Google's API, and return the experiment's details. From this you can extract the script. As you can't make an asynchronous call from the razor template, I have made a plain old xmhttp call to my google api controller. Then...

    if (response.IsSuccessStatusCode)
    
                    {
                        var resJson = await response.Content.ReadAsStringAsync();
    
                      var values = JObject.Parse(resJson);
    
                        JArray items = (JArray)values["items"];
    
                        string value = items[0]["snippet"].ToString();
                        return value;
    
                    }
    

    'Snippet' is the name of the item in the json object that contains the Google Analytics script. It looks like this:

    <!-- Google Analytics Content Experiment code -->\n
    
    
    
    
    <script>
      function utmx_section(){}
    function utmx(){}(function(){
      var\nk='EXPERIMENT-KEY',
          d=document,l=d.location,c=d.cookie;\nif(l.search.indexOf(
            'utm_expid='+k)>0)return;\n
          function f(n){if(c){var i=c.indexOf(n+'=');
                              if(i>-1){var j=c.\nindexOf(';',i);
                              return escape(c.substring(i+n.length+1,j<0?c.\nlength:j))}}}
      var x=f('__utmx'),xx=f('__utmxx'),
          h=l.hash;
      d.write(\n'<sc'+'ript src=\"'+'http'+(l.protocol=='https:'?'s://ssl':\n'://www')+'.google-analytics.com/ga_exp.js?'
              +'utmxkey='+k+
              \n'&utmx='+(x?x:'')
        +'&utmxx='+(xx?xx:'')
        +'&utmxtime='+new Date().\nvalueOf()
        +(h?'&utmxhash='+escape(h.substr(1)):'')
        +\n'\" type=\"text/javascript\" charset=\"utf-8\"><\\/sc'+'ript>')})();\n
      </script>
    
    
    
    
    
    
    
    
    <script>utmx('url','A/B');</script>
    

    \n \n

    Back on the front end, a lot of javascript debugging to clean up the script... (this could probably be a lot neater, I'm not a js expert!)

    This bit is tricky. Essentially we're trying to recreate the script but because we're loading it now from the template we need to do it in two parts.

    var baseContent = xmlhttp.responseText.replace(/\r?\n|\r/g, ' ');
                                var scriptContent = baseContent.replace(/<script>/g, "");
                                var untaggedScript = scriptContent.replace(/<\/script>/g, "");
    

    // take everything in the the d.write method out of this script, we will load it later // otherwise it will crash your browser

                                var scriptSubstring1 = untaggedScript.split("h=l.hash;")[1].split("})();")[0];
                                var unbuggedScript = untaggedScript.replace(scriptSubstring1, "");
    
                                // k is the value of the experiment key, get it from the script
                                var k = unbuggedScript.split("{var k='")[1].split("',d=document")[0];
    

    You can now add the first bit of your script to the head tag

    var scriptNode = document.createElement("script");
    var scriptText = document.createTextNode(unbuggedScript);
    scriptNode.appendChild(scriptText);
    

    We can now clean up the second bit of script which was inside the d.write method. Again, apologies for my inelegant javascript!

     var scriptNode2 = document.createElement("script");
     var scriptSubstring2 = scriptSubstring1.replace("d.write", "");
     var scriptSubstring3 = scriptSubstring2.replace("'<sc'+'ript src=\"'+", "");
     var scriptSubstring4 = scriptSubstring3.replace("><\\/sc'+'ript>'", "");
    

    We next need to recreate some of the functionality of the script:

    var d = document;
    var l = d.location;
    var c = d.cookie;
    
                            // pass these to function f as they haven't been generated yet
                            var x = f('__utmx');
                            var xx = f('__utmxx');
                            var h = l.hash;
    
                            function f(n) {
                                if (c) {
                                    var i = c.indexOf(n + '=');
                                    if (i > -1) {
                                        var j = c.indexOf(';', i);
                                        return escape(c.substring(i + n.length + 1, j < 0 ? c.length : j))
                                    }
                                }
                            }
                            // we now have all the values for the script
    

    // you can set these parameters and add the script to your head

    scriptNode2.setAttribute('src', 'http' + (l.protocol == 'https:' ? 's://ssl' : '://www') + '.google-analytics.com/ga_exp.js?' + 'utmxkey=' + k + '&utmx=' + (x || "") + '&utmxx=' + (xx || "") + '&utmxtime=' + new Date().valueOf() + (h ? '&utmxhash=' + escape(h.substr(1)) : ''));
    
     document.head.appendChild(scriptNode2);
    

    That done, grab your experiment id and variant from cookies

      // get the value of the experiment id
      var expId = getCookie("googleExpId");
    
     // get the value of the experiment variant
     var expVar = getCookie("expVar");
    
     function getCookie(cname) {
                var name = cname + "=";
                var decodedCookie = decodeURIComponent(document.cookie);
                var ca = decodedCookie.split(';');
                for (var i = 0; i < ca.length; i++) {
                    var c = ca[i];
                    while (c.charAt(0) == ' ') {
                        c = c.substring(1);
                    }
                    if (c.indexOf(name) == 0) {
                        return c.substring(name.length, c.length);
                    }
                }
            }
    

    Then, load your Google Analytics script as normal, and finally include the experiment id and variant in your call to ga

       ga('create', 'your account id', 'auto');
      ga('set', 'expId', expId);
       ga('set', 'expVar', expVar);
      ga('send', 'pageview'); // or whatever you're measuring
    

    That's it. You can set up the experiments in Umbraco and see the results in your analytics console. I hope someone finds this useful at some point. I've left out some of the code (and all of the Google Api Controller) for security reasons.

  • Jeroen Roscam 13 posts 113 karma points
    Feb 18, 2019 @ 07:34
    Jeroen Roscam
    0

    Wow. Thanks for researching this. I have to admit this is above my skill level. But I'll foreward this to somenone who should be able to use it.

  • Paul McCarthy 39 posts 160 karma points
    Feb 18, 2019 @ 20:16
    Paul McCarthy
    0

    No problem. As I say there's probably lots of ways around it; mine is definitely ugly! The code in the first segment is good though. That's how you identify that an experiment is running. After that might depend on your individual setup.

Please Sign in or register to post replies

Write your reply to:

Draft