Задача: определить какие события превышают payload size Google Analytics
Решение: логирование хитов Google Analytics (включая payload size) в Google Sheets при помощи Google Tag Manager, без участия разработчиков
Если вам доводилось имплементировать Enhanced Ecommerce для Google Analytics (GA) через Google Tag Manager (GTM) и затем дебажить это дело с помощью Google Analytics debugger, то вероятно вы сталкивались с тем, что некоторые события «почему-то» не доходят в GA и появляется ошибка: Payload size is to large (9000). Max allowed is 8192
Дело в том, что библиотека analytics.js не принимает хиты более 8192 байт. Если размер хита больше, то в GA он не дойдет и в отчетах по событиям будет пусто.
Пример ситуации:
Веб аналитик просит разработчика запихинуть (или сам запихивает) все product impressions в один хит. В результате хит не доходит т.к. в листинге на одной странице более 50 товаров. Или в корзину добавляется 50+ различных товаров, в результате возникают проблемы с событиями checkout step и transaction.
Старайтесь всегда оптимизировать структуру данных хита (т.е. например, отправлять хиты по мере появления товара в поле зрения юзера, не пихать в хит ненужные переменные (variant, category, brand), не использовать длинных названий товаров и т.п.) — это, во-первых, увеличит скорость отправки хита; во-вторых, позволит избежать проблем с payload size.
Если оптимизировать невозможно, то существует несколькокостылей способов обойти эти ограничения:
Но прежде чем приступить к нарезке хитов и оптимизации контента, определим, какие именно события превышают payload size. Данный материал посвящен решению этой задачи.
Создаем новую таблицу.
В хедер (1 строка), записываем имена параметров, которые хотим извлечь из хита (будьте внимательны, названия указываете в точности такие же, которые затем будете использовать в JS скрипте в GTM). В качестве примера извлечем такие данные:
Пример мапинга колонок для логирования payload в Google Sheet
Порядок параметров в колонках неважен (кроме timestamp — она должен быть первым). Колонки с параметрами cid и ti отформатируйте как Plain text (Format > Number > Plain text), во избежание ошибок с автоформатированием.
При желании можете добавить/убрать необходимые параметры, (не забудьте затем изменить список переменных в JS скрипте в GTM). Список возможных полей и параметров analytics.js
Далее, открываем script editor и добавляем код (оригинал скрипта принадлежит Martin Hawksey https://gist.github.com/mhawksey/1276293):
Разворачиваем скрипт как веб приложение (Publish > Deploy as web app...). Права доступа — anyone, even anonymous. Публикуем.
Настройки Google Script editor
В дальнейшем нам будет нужен URL нашего веб приложения (Current web app URL), поэтому вкладку пока не закрывайте.
Создадим 2 custom JavaScript variables:
Пример JavaScript variable в GTM
Первая JS variable, для определения времени отправки хита (timestamp). Эта переменная будет использоваться во второй JS variable.
Вторая JS variable, для отлова нужных хитов и передачи их в Google Sheet (за основу взят код из этого материала).
Что необходимо настроить:
Теперь, находим в своем контейнере тег(теги) отвечающие за отправку событий Enhanced Ecommerce в GA и создаем их копию с привязкой к соответствующим триггерам.
В копии тегов изменяем GA ID на любой (тестовый/фейковый) и добавляем в Fields to Set поле sendHitTask и название JS variable (v_EE_mimic GA payload).
Поле sendHitTask, в данном случае, модифицируется т.е. мы отправляем данные о хите в тестовый GA (можно и не отправлять, для этого удалите в коде значение 'https://www.google-analytics.com/collect',) и в Google Sheet (если он превышает заданный payload size).
Копия тегов с тестовым GA ID нужна для подстраховки, чтобы не трогать оригинальный Enhanced Ecommerce тег. Можно модифицировать sendHitTask и в оригинальном теге (без создания копий), но тогда появляется риск, что хит не дойдет в GA (у меня такого не встречалось, но на всякий случай лучше подстраховаться).
Настройки тега Enhanced Ecommerce в GTM
Сохраняем тег, публикуем новую версию GTM контейнера.
Теперь, при срабатывании тега Enhance Ecommerce, также будет отрабатывать скрипт v_EE_mimic GA payload. Если при заданных настройках payload превышает свои значения, произойдет запись этого хита в Google Sheet.
Собирая логи по хитам, можно определить какое конкретно событие не дошло в GA, где это произошло, в каком браузере и т.д. (см. список возможных полей и параметров analytics.js).
Спасибо за внимание!
Надеюсь, данный материал вам пригодится и облегчит жизнь с дебагом Google Analytics.
P.S. Кто умеет/знает как автоматизировать проверку GTM тегов (автотесты для тегов), пожалуйста отзовитесь! Когда-то давно Симо написал статью про это www.simoahava.com/analytics/automated-tests-for-google-tag-managers-datalayer но разобраться в ней не смог, может кто пробовал/знает другие способы. Буду очень благодарен советам и помощи в этом вопросе.
Решение: логирование хитов Google Analytics (включая payload size) в Google Sheets при помощи Google Tag Manager, без участия разработчиков
Суть проблемы
Если вам доводилось имплементировать Enhanced Ecommerce для Google Analytics (GA) через Google Tag Manager (GTM) и затем дебажить это дело с помощью Google Analytics debugger, то вероятно вы сталкивались с тем, что некоторые события «почему-то» не доходят в GA и появляется ошибка: Payload size is to large (9000). Max allowed is 8192
Почему так происходит?
Дело в том, что библиотека analytics.js не принимает хиты более 8192 байт. Если размер хита больше, то в GA он не дойдет и в отчетах по событиям будет пусто.
Пример ситуации:
Веб аналитик просит разработчика запихинуть (или сам запихивает) все product impressions в один хит. В результате хит не доходит т.к. в листинге на одной странице более 50 товаров. Или в корзину добавляется 50+ различных товаров, в результате возникают проблемы с событиями checkout step и transaction.
Что нужно делать
Старайтесь всегда оптимизировать структуру данных хита (т.е. например, отправлять хиты по мере появления товара в поле зрения юзера, не пихать в хит ненужные переменные (variant, category, brand), не использовать длинных названий товаров и т.п.) — это, во-первых, увеличит скорость отправки хита; во-вторых, позволит избежать проблем с payload size.
Если оптимизировать невозможно, то существует несколько
- порезать хит на несколько частей и отправлять его кусками
- data import (пушим в хит только id товара, остальное подгружаем в виде базы данных через data import)
Подготовка к действиям
Но прежде чем приступить к нарезке хитов и оптимизации контента, определим, какие именно события превышают payload size. Данный материал посвящен решению этой задачи.
Шаг 1. Настройка Google Sheets
Создаем новую таблицу.
В хедер (1 строка), записываем имена параметров, которые хотим извлечь из хита (будьте внимательны, названия указываете в точности такие же, которые затем будете использовать в JS скрипте в GTM). В качестве примера извлечем такие данные:
- timestamp
- payLoadLength
- tid (tracking id)
- cid (client id)
- uid (user id)
- t (type of hit)
- pa (product action)
- ni (non interaction)
- dl (document location)
- dp (document path)
- dt (document title)
- ec (event category)
- ea (event action)
- el (event label)
- ti (transaction id)
- tr (transaction revenue)
Пример мапинга колонок для логирования payload в Google Sheet
Порядок параметров в колонках неважен (кроме timestamp — она должен быть первым). Колонки с параметрами cid и ti отформатируйте как Plain text (Format > Number > Plain text), во избежание ошибок с автоформатированием.
При желании можете добавить/убрать необходимые параметры, (не забудьте затем изменить список переменных в JS скрипте в GTM). Список возможных полей и параметров analytics.js
Далее, открываем script editor и добавляем код (оригинал скрипта принадлежит Martin Hawksey https://gist.github.com/mhawksey/1276293):
function doGet(e){
return handleResponse(e);
}
function doPost(e){
return handleResponse(e);
}
function handleResponse(e) {
var lock = LockService.getPublicLock();
lock.waitLock(30000); // wait 30 seconds before conceding defeat.
try {
// next set where we write the data - you could write to multiple/alternate destinations
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
// we'll assume header is in row 1 but you can override with header_row in GET/POST data
var headRow = e.parameter.header_row || 1;
var headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0];
var nextRow = sheet.getLastRow()+1; // get next row
var row = [];
// loop through the header columns
for (i in headers){
if (headers[i] == "timestamp"){ // special case if you include a 'timestamp' column
row.push(Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "MMM d yyyy HH:mm:ss"));
} else { // else use header name to get data
row.push(e.parameter[headers[i]]);
}
}
// more efficient to set values as [][] array than individually
sheet.getRange(nextRow, 1, 1, row.length).setValues([row]);
// return json success results
return ContentService
.createTextOutput(JSON.stringify({"result":"success", "row": nextRow}))
.setMimeType(ContentService.MimeType.JSON);
} catch(e){
// if error return this
return ContentService
.createTextOutput(JSON.stringify({"result":"error", "error": e}))
.setMimeType(ContentService.MimeType.JSON);
} finally { //release lock
lock.releaseLock();
}
}
Разворачиваем скрипт как веб приложение (Publish > Deploy as web app...). Права доступа — anyone, even anonymous. Публикуем.
Настройки Google Script editor
В дальнейшем нам будет нужен URL нашего веб приложения (Current web app URL), поэтому вкладку пока не закрывайте.
Шаг 2. Настройка GTM
Создадим 2 custom JavaScript variables:
- v_EE_timestamp
- v_EE_mimic GA payload
Пример JavaScript variable в GTM
Первая JS variable, для определения времени отправки хита (timestamp). Эта переменная будет использоваться во второй JS variable.
function() {
// Get local time as ISO string with offset at the end
var now = new Date();
var tzo = -now.getTimezoneOffset();
var dif = tzo >= 0 ? ' Timezone: +' : ' Timezone: -';
var pad = function(num) {
var norm = Math.abs(Math.floor(num));
return (norm < 10 ? '0' : '') + norm;
};
return now.getFullYear()
+ '-' + pad(now.getMonth()+1)
+ '-' + pad(now.getDate())
+ ' Time' + pad(now.getHours())
+ ':' + pad(now.getMinutes())
+ ':' + pad(now.getSeconds())
+ dif + pad(tzo / 60)
+ ':' + pad(tzo % 60);
}
Вторая JS variable, для отлова нужных хитов и передачи их в Google Sheet (за основу взят код из этого материала).
function sendHitTask(){
return function(model) {
var payLoad = model.get('hitPayload');
var trackingBaseUrls = ['https://www.google-analytics.com/collect', 'https://script.google.com/macros/s/AKfycbxJLy3eYBLpPu_S_eNccxzn_GwHXkZWr-93feMuBaAZelk3fj01yB/exec'];
for (i = 0; i < trackingBaseUrls.length; i++) { var baseUrl = trackingBaseUrls[i]; if (trackingBaseUrls[i].indexOf('collect') > -1) {
var req = new XMLHttpRequest();
req.open('POST', baseUrl, true);
req.send(payLoad);
} else if (payLoad.length > 7500){
var payLoadExtract = payLoad.split('&');
var payLoadArray = {};
// Push values to array for later access
for (i = 0; i < payLoadExtract.length; i++){
var splitArray = payLoadExtract[i].split('=');
payLoadArray[splitArray[0].trim()] = splitArray[1].trim();
}
// Specify values to be sent to Google Sheets from array
var tid = 'tid=' + payLoadArray.tid,
cid = '&cid=' + payLoadArray.cid,
uid = '&uid=' + payLoadArray.uid,
t = '&t=' + payLoadArray.t,
pa = '&pa=' + payLoadArray.pa,
ni = '&ni=' + payLoadArray.ni,
dl = '&dl=' + payLoadArray.dl,
dp = '&dp=' + payLoadArray.dp,
dt = '&dt=' + payLoadArray.dt,
ec = '&ec=' + payLoadArray.ec,
ea = '&ea=' + payLoadArray.ea,
el = '&el=' + payLoadArray.el,
ti = '&ti=' + payLoadArray.ti,
tr = '&tr=' + payLoadArray.tr,
timestamp = '×tamp=' + {{v_EE_timestamp}},
payLoadLength = '&payLoadLength=' + payLoad.length;
var collectPayLoad = tid + cid + uid + t + pa + ni + dl + dp + dt + ec + ea + el + ti + tr + timestamp + payLoadLength;
// Send Values to Google Sheets
var collectUrl = baseUrl +'?'+ collectPayLoad;
var myImage = new Image();
myImage.src = collectUrl;
}
}
}
}
Что необходимо настроить:
- В переменную trackingBaseUrls вставляем URL вашего веб приложения (созданного в шаге 1).
- В payLoad.length определяем размер хита, который необходимо ловить. В примере установлено >7500 т.е. ловим всё что потенциально может превысить порог 8192 байт. Можно поставить меньше, если интересен весь лог.
- В req.open определяется метод отправки хита (может быть POST или GET, в зависимости от размера хита; Google рекомендует использовать POST т.к. это позволяет отправлять более крупный payload). По умолчанию события в GA отправляются через GET. Для Enhanced Ecommerce рекомендую изменить способ отправки на POST (делается путем добавления в тег Enhance Ecommerce в Fields to set: transport — beakon)
Теперь, находим в своем контейнере тег(теги) отвечающие за отправку событий Enhanced Ecommerce в GA и создаем их копию с привязкой к соответствующим триггерам.
В копии тегов изменяем GA ID на любой (тестовый/фейковый) и добавляем в Fields to Set поле sendHitTask и название JS variable (v_EE_mimic GA payload).
Поле sendHitTask, в данном случае, модифицируется т.е. мы отправляем данные о хите в тестовый GA (можно и не отправлять, для этого удалите в коде значение 'https://www.google-analytics.com/collect',) и в Google Sheet (если он превышает заданный payload size).
Копия тегов с тестовым GA ID нужна для подстраховки, чтобы не трогать оригинальный Enhanced Ecommerce тег. Можно модифицировать sendHitTask и в оригинальном теге (без создания копий), но тогда появляется риск, что хит не дойдет в GA (у меня такого не встречалось, но на всякий случай лучше подстраховаться).
Настройки тега Enhanced Ecommerce в GTM
Сохраняем тег, публикуем новую версию GTM контейнера.
Итог
Теперь, при срабатывании тега Enhance Ecommerce, также будет отрабатывать скрипт v_EE_mimic GA payload. Если при заданных настройках payload превышает свои значения, произойдет запись этого хита в Google Sheet.
Собирая логи по хитам, можно определить какое конкретно событие не дошло в GA, где это произошло, в каком браузере и т.д. (см. список возможных полей и параметров analytics.js).
Спасибо за внимание!
Надеюсь, данный материал вам пригодится и облегчит жизнь с дебагом Google Analytics.
P.S. Кто умеет/знает как автоматизировать проверку GTM тегов (автотесты для тегов), пожалуйста отзовитесь! Когда-то давно Симо написал статью про это www.simoahava.com/analytics/automated-tests-for-google-tag-managers-datalayer но разобраться в ней не смог, может кто пробовал/знает другие способы. Буду очень благодарен советам и помощи в этом вопросе.
dkomarovskiy
payload — это все параметры, которые уходят запросом в GA.
почему тогда в таблицу не собирать их все?
Я тут habr.com/post/353836 описывал упрощенный скрипт по отправке всех параметров.
Не хватает только if (payLoad.length > 7500) под ваше решение.
alunet Автор
Спасибо за дополнение, интересный опыт. При проблеме с семплированием пробовал выгружать в BigQuery через OWOX, но вот через GTM не доводилось такое проделывать. Хороший вариант если есть свое хранилище и отдавать деньги в BigQuery, OWOX не хочется.
В данном случае, хотел сконцентрироваться конкретно на дебаге Enhance Ecommerce т.е. выгружать все параметры не вижу смысла.