31

I have created an A/B-test using Google Optimize. Now I would like to read the current experimentId and variationId in Javascript. My goal is to run different javascript based on the given variation.

I can't seem to find any info on this in the documentation. Is it possible?

Øyvind Holmstad
  • 1,379
  • 2
  • 13
  • 22

5 Answers5

20

Now there is also the Google Optimize javascript API available that is a better option:

The experimentId is now available in the Optimize UI, as soon as the experiment is created (before start).

The API is already available in the page and you can use it like this:

google_optimize.get('<experimentId>');

(note: this will work only after the Optimize container script has been loaded)

You can also register a callback to run the javascript that you want at any time (even before the Optimize script has been loaded) using:

function gtag() {dataLayer.push(arguments)}

function implementExperimentA(value) {
  if (value ==  '0') {
    // Provide code for visitors in the original.
  } else if (value == '1') {
    // Provide code for visitors in first variant.
  }

gtag('event', 'optimize.callback', {
    name: '<experiment_id_A>',
    callback: implementExperimentA
 });

If you want to find both the experimentId and variation you can register a callback for any experiment:

function implementManyExperiments(value, name) {
  if (name == '<experiment_id_A>') {
    // Provide implementation for experiment A
    if (value ==  '0') {
      // Provide code for visitors in the original.
    } else if (value == '1') {
      // Provide code for visitors in first variant.
    ...
  } else if (name == '<experiment_id_B>') {
    // Provide implementation for experiment B
    ...
}

gtag('event', 'optimize.callback', {
    callback: implementManyExperiments
 });

For more details

https://support.google.com/optimize/answer/9059383

Optimize Team
  • 216
  • 2
  • 3
  • 2
    Hi, I have implemented Optimize Server Side experiments with GTM. I'm currently seeing the data in my Optimize dashboard so I can confirm the experiments are working. However when trying the code snippets mentioned in this answer I keep getting undefined. I'm wondering if this Optimize Javascript API got deprecated or if the issue I'm experiencing is due to my implementation (just using gtm.js, not gtag.js as mentioned in the Google support documentation linked above). Do you have a working example of optimize callbacks working with GTM? – Agustin Haller Apr 18 '19 at 18:53
  • 2
    Same issue here. – FlorianTopf May 01 '19 at 18:45
19

EDIT: Nevermind my cookie-based answer below, I found a better solution.

Just do this:

var propertyId = "UA-1234567-33";
var experimentId = Object.keys(gaData[propertyId].experiments)[0];
var variationId = gaData[propertyId].experiments[experimentId];

Old answer:

(Don't do this.. keeping it here for reference)

Maximes answer is working but was not exactly what I was looking for. I wanted to be able to find the experimentId and variationId without adding code through the visual editor. I finally found a way.

The values are actually stored in the _gaexp cookie. The cookie is present when an experiment is running. You can inspect it in Chrome by opening Developer tools, going to the Application tab and clicking Cookies in the left pane. It looks something like this:

GAX1.2.S1SJOWxJTVO9tM2QKV3NcP.17723.1

The experiment id is the part after the second number:

S0SJOWxJTVO1tM2QKD2NcQ

The variation id is the last number:

1

I wrote this code to extract it from the cookie:

function getCookieValue(cookieName) {
    var result = document.cookie.match('(^|;)\\s*' + cookieName + '\\s*=\\s*([^;]+)');
    return result ? result.pop() : '';
}

function getExperimentId() {
    var cookie = getCookieValue('_gaexp');
    if (cookie == undefined) {
        return undefined;
    } else {
        var fields = cookie.split('.');
        return fields[2];
    }
}

function getVariationId() {
    var cookie = getCookieValue('_gaexp');
    if (cookie == undefined) {
        return undefined;
    } else {
        var fields = cookie.split('.');
        return fields[4];
    }
}

var experimentId = getExperimentId();
var variationId = getVariationId();

WARNING: Fetching the experiment ID and variationId from the cookie is not a good idea. For two reasons.

  1. When the experiment is finished, the cookie is still present. The cookie is cached, so you will find an experimentId and variationId that does not apply, and you can not know if the experiment is running or not.
  2. If you stop experiment A, and start experiment B, the old value for A will still be part of the cookie. So it will look something like this:

GAX1.2.S1SJOWxJTVO9tM2QKV3NcP.17723.1!vr1mB2L2RX6kSI1ZnUDTzT.18721.0

which is the same as how it would look if you were running to experiments at once. It makes it hard to reason about what experimentId to use.

Øyvind Holmstad
  • 1,379
  • 2
  • 13
  • 22
  • Are you sure this cookie is for Google Optimize, not for the Google Analytics Content Experiments? I can't see this cookie being set on my Google Optimize test page. – Georg M. Sorst Jul 20 '17 at 09:28
  • @GeorgM.Sorst Yeah, I'm pretty sure. As far as I remember from testing the Content Experiments-feature, you need to initialize the Content Experiment javascript with an experiment id, and I am not doing that on my test page, and I find an experiment id matching the id from the optimize gui in the cookie. However, I was testing out ContetExperiments on that page earlier, so I can't be 100% sure without looking at the code again. – Øyvind Holmstad Jul 21 '17 at 07:21
  • 2
    `gaData` with my property ID exists, but it only contains the key `hitCount`; no `experiments` key even though my experiment is currently running. Can anyone else see this? – Georg M. Sorst Aug 04 '17 at 12:26
  • 1
    RE: updated answer. Great workaround for what Google should be providing to devs anyway. As a heads up, I noticed it *only works on the page(s) where the experiment is running*. If a user has seen the experiment and then goes to another page then this code won't return the experiment id or variation *on that subsequent page*. This is important, as it means you may want to get the experiment and variation and set a cookie as a record that the user saw that experiment/variation for use on subsequent pages (e.g. form submission). I suppose this is where the "old answer" comes in. – theyetiman Jan 31 '18 at 12:10
  • 2
    @ØyvindHolmstad I have the same problem as Georg where my `gaData` doesn't contain the `experiments` property but only a `hitcount` property instead. Any idea on how to fix this ? – RPDeshaies Feb 02 '18 at 15:27
  • @RPDeshaies The experiments-variable is only populated if there is an active experiment on the given page. And the variable is async, so you have to wait some time for it to be populated. We wait for a callback that GA is done loading before checking experiments. – Øyvind Holmstad Feb 05 '18 at 14:15
  • How can I use the variable gaData? I have been following the documentation of Google Optimize and nowhere do they mention this variable. Do I need to load some additional javascript? – crico_aven Feb 17 '18 at 00:04
  • @crico_aven Maybe you need to load Google Analytics? I don't even know if it's possible to use Optimize without GA, as it has never been an option for us. – Øyvind Holmstad Feb 20 '18 at 10:15
6

Google Optimize allow you to run arbitrary JS on a per DOM element basis.

This feature is meant to modify the DOM elements, but there's nothing stopping you from using it to call a JS function or define some variables.

How to set up the script

  1. Edit your experiment variant in the Visual Editor.
  2. Click on the Select elements icon (the rectangle in the top left corner)
  3. In the Element Selector field, type in body.
  4. Click the Add change button and select Javascript. This will bring up a dialog that allows you to input a JS function that will be called for the body.
  5. Put in the code you want to run in there.

What code to run

Assuming you have a doSomething() method define on your page, you can have your Google Optimized function look something like this:

doSomething("Experiment #1", "Variant A");

Alternatively, you can try defining your variables globally.

// We need to use `windows` here, because if we define a variable 
// with `var`, it will be limited to the scope of the Google Optimize
// function.
window["google_optimize_exp_id"] = "Experiment #1";
window["google_optimize_exp_var_id"] = "Variant A";

If you use the second method, keep in mind that you need to wait until the Google Optimized function has run before running your own logic.

Maxime Rainville
  • 2,019
  • 23
  • 29
4

There are a 3 ways you could do this:

1) Depending on your Google Analytics setup, you can access the following object via Chrome console and pass in your GA property ID:

Object.keys(window.gaData["YOUR-GA-PROPERTY ID"].experiments).forEach(function(key, index){

var value = window.gaData["YOUR-GA-PROPERTY ID"].experiments[key];
console.log("Info", key, value, index);

 });

2) As someone has already pointed out, you can access the _gaexp cookie, which stores your experiment ID and variant number.

    //READ THE COOKIE
    function readCookie(name) {
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');

    for(var i=0;i < ca.length;i++) {
       var c = ca[i];
       while (c.charAt(0)==' ') c = c.substring(1,c.length);
       if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
   }
   return null;
   };

   // GET THE COOKIE
   let getCookie = readCookie("_gaexp");
   console.log('getCookie', getCookie);
   // WILL RETURN A STRING IN THIS FORMAT
   // GAX1.2.YOUREXPERIMENTID.18803.0
   // The long number in the middle is your experiment ID
   // The number at the end is your variant number (0)

   // SPLIT THE COOKIE
   let splitCookie = readCookie("_gaexp").split("!");
   // SPLIT THE COOKIE SO YOU CAN ACCESS THE EXPERIMENT ID AND VARIANT NUMBER

3) And lastly, you could use your dataLayer.
A bit more of a clunky way to do it, but in Optimize 360, you could add JavaScript in each variant, (when you go edit your AB Test/variants). And send your experiment ID to your dataLayer, as well as other information.

EG:

function returnDate() {
  var today = new Date();
  var dd = String(today.getDate()).padStart(2, '0');
  var mm = String(today.getMonth() + 1).padStart(2, '0'); //January is 0!
  var yyyy = today.getFullYear();
  
  today = mm + '/' + dd + '/' + yyyy;
  return today;
}

var dateToday = returnDate();

var ABTest = {

      id: 'YOUREXPERIMENTID',
      name: 'Title of your test',
      description:  'Test description',
      date: dateToday, //The launch date of AB Test.
      variant: 1,
      totalVariants: 5
  };

// AND THEN PUSH ALL THAT INFORMATION INTO THE DATALAYER 
dataLayer.Tests.push(ABTest);

Then to access all that information, all you need to do is access the window.dataLayer object.

Now how I've used google tag manager, add the "Test" key, in dataLayer.Tests. But of course you don't need that, but I just like to organise my object :)

Reena Verma
  • 1,617
  • 2
  • 20
  • 47
2

I've found that the variant number can be obtained running a code like:

gaData["UA-XXXXXXXX-X"].experiments['ZYkOuNLKEoeLytt-dLWw3x']

The result should be "0"for the original, "1" for the first variant...

You can get the experiments with:

gaData["UA-XXXXXXXX-X"].experiments

Of course you have to replace UA-XXXXXXXX-X for the Google Analytics ID and ZYkOuNLKEoeLytt-dLWw3x for your experiment id.

Osvaldo
  • 270
  • 1
  • 11