Установка и настройка контейнера Google Optimize. Сравнение вариантов.

Давно вы залезали в доки гугла? Иногда мне кажется, что разночтений у них больше, чем у Библии, и они точно так же плодятся с добавлением новых глав и не слишком качественными переводами с языка оригинала. Сегодня попробуем разобраться в некоторых статьях, а заодно замутим ролевую игру с собаками и Павловым.  

Как создать эксперимент в Google Optimize

Сперва конечно же нужно в нем зарегистрироваться. После простановки всех галочек вы попадете на страницу контейнера

Контейнер Google Optimize

Здесь справа написано, что нужно потыкать в интерфейсе, и лучше я объяснить не в силах, а вот что мы рассмотрим подробно, так это установку на сайт. Есть две категории людей два варианта:

  1. Подключить контейнер Optimize в коде сниппета установки Google Analytics
  2. Создать тег в Google Tag Manager (но в код сайта придется лезть все равно)

Установка Optimize через Tag Manager

Страница в доках https://support.google.com/tagmanager/answer/7164339?hl=ru
Возьмите идентификатор контейнера Optimize, который скрывается под первым пунктом на предыдущем скрине, и создайте вот такой тег:

Подключение Google Optimize через Google Tag Manager

  Теперь идем в настройки тега Google Analytics и указываем, что перед ним нужно активировать тег Optimize:

Подключение Google Optimize через Google Tag Manager

  Если ваш эксперимент каким-то образом переделывает внешний вид сайта, то скорее всего пользователь при загрузке увидит скачущие элементы, и это может повлиять на результат. Чтобы подобного не произошло, Google предлагает вот такой костыль:  

1234567
<!-- Page-hiding snippet (recommended)  -->
<style>.async-hide { opacity: 0 !important} </style>
<script>(function(a,s,y,n,c,h,i,d,e){s.className+=' '+y;h.start=1*new Date;
h.end=i=function(){s.className=s.className.replace(RegExp(' ?'+y),'')};
(a[n]=a[n]||[]).hide=h;setTimeout(function(){i();h.end=null},c);h.timeout=c;
})(window,document.documentElement,'async-hide','dataLayer',4000,
{'GTM-XXXXXX':true});</script> // здесь мог быть id именно вашего контейнера GTM

  Он скрывает страницу на время внесения изменений. Обратите внимание, что в коде указывается id контейнера GTM, а не Optimize, если Optimize вы подключаете через GTM. Этот код рекомендуется вставлять сразу после meta тегов на сайте. Если изменение страницы занимает слишком много времени, то оно прерывается, пользователю показывается исходный вариант, и его участие в эксперименте отменяется.

Установка Optimize через сниппет Analytics

Страница в доках  https://support.google.com/360suite/optimize/answer/6262084?hl=ru
В этом случае просто подключите свой контейнер, добавив строку между созданием счетчика и отправкой pageview:

 1 2 3 4 5 6 7 8 910
<script>
(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','https://www.google-analytics.com/analytics.js','ga');

ga('create', 'UA-XXXXXXXX-X', 'auto');
ga('require', 'GTM-XXXXXX'); // код контейнера Optimize
ga('send', 'pageview');
</script>

  Код, делающий хорошо, в этом случае такой же, только вместо id GTM, в нем нужно указать идентификатор контейнера Optimize.

1234567
<!-- Page hiding snippet (recommended)  -->
<style>.async-hide { opacity: 0 !important} </style>
<script>(function(a,s,y,n,c,h,i,d,e){s.className+=' '+y;h.start=1*new Date;
h.end=i=function(){s.className=s.className.replace(RegExp(' ?'+y),'')};
(a[n]=a[n]||[]).hide=h;setTimeout(function(){i();h.end=null},c);h.timeout=c;
})(window,document.documentElement,'async-hide','dataLayer',4000,
{'GTM-XXXXXX':true});</script> // идентификатор контейнера Optimize

 

Сравнение скорости загрузки

Конечно все эти эксперименты на клиентской стороне по большей части полная ерунда, но если уж пришлось строить из говна и палок,  то давайте хотя бы выберем сорта получше. Чтобы отвлечься от тонны отчетов на работе определить оптимальный вариант, я написал скрипт для автоматического тестирования, сделал несколько сотен прогонов и вот результаты:

GA GTM
Тестов 165 162
Среднее время (мс) 414 753

Таблица с результатами

Хотя вариант с GTM и грузится в два раза дольше, в реальности разница составляет всего 0,3 секунды, так что можно спокойно забить. Тем не менее вот инструкция, как повторить тест в домашних условиях:

  1. создаем две страницы с установкой через сниппет GA и через контейнер GTM
  2. рассчитываем время от начальной загрузки страницы до отработки изменения в контейнере Optimize
  3. собираем результаты в Google Spreadsheet
  4. зацикливаем, чтобы было весело, запускаем и смотрим

Код страницы с GTM

 1 2 3 4 5 6 7 8 910111213141516171819202122232425262728
<html>
<head>
<script>
  window.a = new Date().getTime();
</script>
<style>.async-hide { opacity: 0 !important} </style>
<script>(function(a,s,y,n,c,h,i,d,e){s.className+=' '+y;h.start=1*new Date;
h.end=i=function(){s.className=s.className.replace(RegExp(' ?'+y),'')};
(a[n]=a[n]||[]).hide=h;setTimeout(function(){i();h.end=null},c);h.timeout=c;
})(window,document.documentElement,'async-hide','dataLayer',4000,
{'GTM-XXXXXXXX':true});</script> // укажите свой id GTM, не Optimize
  
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXXXXXX');</script> // укажите свой id GTM
<!-- End Google Tag Manager -->
  
</head>
<body>
  <!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXXXXX"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
</body>
</html>

Код страницы c GA

 1 2 3 4 5 6 7 8 9101112131415161718192021222324252627
<html>
<head>
<script>
  window.a = new Date().getTime();
</script>
<style>.async-hide { opacity: 0 !important} </style>
<script>(function(a,s,y,n,c,h,i,d,e){s.className+=' '+y;h.start=1*new Date;
h.end=i=function(){s.className=s.className.replace(RegExp(' ?'+y),'')};
(a[n]=a[n]||[]).hide=h;setTimeout(function(){i();h.end=null},c);h.timeout=c;
})(window,document.documentElement,'async-hide','dataLayer',4000,
{'GTM-XXXXXXX':true});</script>  // id контейнера Optimize
  
<script>
  (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','https://www.google-analytics.com/analytics.js','ga');
  ga('create', 'UA-AAAAAAAA', 'auto'); // id счетчика GA
  ga('require', 'GTM-YYYYYYY'); // id контейнера Optimize
  ga('send', 'pageview');
</script>

</head>
<body>
Hello, test!
</body>
</html>

  В настройках эксперимента в Optimize нужно выставить распределение 99,9% трафика на измененный вариант, чтобы скрипт всегда отрабатывал. Вот сам скрипт:

 1 2 3 4 5 6 7 8 910
const b = new Date().getTime() - window.a;
const c = ~document.location.href.indexOf('gtm') ? 'GTM' : 'Site';
const s = ('GTM'===c) ? 'site' : 'gtm';
const t = !!~document.location.href.indexOf('test');

var promise = new Promise(function(resolve,reject){var img = new Image();
img.src = 'https://script.google.com/macros/s/AKfycbzSWcVj6kDobWCEK0qzljfNsfqCrpqpjBBVvd2GHyzohRp9N7W0/exec?s='+c+'&Time='+ b;resolve()});
promise.then(()=>{
  if(!t) location.replace('https://burgerdata.com/exp/'+s+'/')
})

  В этом куске я беру глобальную переменную window.a, которая определяется при создании самих страниц и содержит время в миллисекундах  на тот момент, и вычитаю из него текущее время. Результат отправляется в созданное приложение в Apps Script, который записывает его в таблицы Spreadsheet. Обратите внимание, что я использую вкладки GTM и Site, куда направляются результаты со страницы /gtm/ и /site/. Присутствует одна колонка с заголовком Time. Если захотите сравнить что-то еще, добавьте новую колонке и новый параметр в вызове скрипта.

Код приложения Apps Script:

 1 2 3 4 5 6 7 8 910111213141516171819202122232425
var SHEET_KEY = "16FnXWKhtvGHyfqMjWy-PqIWpbm83M7VxGloAUNlrv2M"; // идентификатор таблицы, берется из url

function doGet(e){
  SHEET_NAME = e.parameter.s;
  var lock = LockService.getDocumentLock();
  lock.waitLock(3000);
  try {
    var doc = SpreadsheetApp.openById(SHEET_KEY);
    var sheet = doc.getSheetByName(SHEET_NAME);
    var headRow = e.parameter.header || 1; //параметр header определяет ряд заголовков, по умолчанию первая строка
    var headers = sheet.getRange(headRow, 1, 1, sheet.getLastColumn()).getValues()[0];
    var row = [];
    for (i in headers){
      var l = e.parameter[headers[i]];
      row.push(l);
    }
    sheet.getRange(sheet.getLastRow() + 1, 1, 1, row.length).setValues(\[row\]);
  } catch(e){
    return ContentService
          .createTextOutput(JSON.stringify({"result":"error", "error": e}))
          .setMimeType(ContentService.MimeType.JSON);
  } finally {
    lock.releaseLock();
  }
}

В заключение

Все это ерунда, читайте про серверный вариант https://developers.google.com/analytics/solutions/experiments-server-side

comments powered by Disqus