Задача: определить какие события превышают 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 и в оригинальном теге (без создания копий), но тогда нельзя будет использовать customTask (его придется модифицировать интегрируя в него 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.
Если оптимизировать невозможно, то существует несколько способов обойти эти ограничения:
- Красивое решение проблемы с помощью customTask. Одним за одним удаляет из payload'a ненужные параметры пока тот не станет меньше 8192. Что конкретно выкидывать — можно настроить.
- Порезать хит на несколько частей и отправлять его кусками.
- GA 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) и url google analytics.
- В 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 и в оригинальном теге (без создания копий), но тогда нельзя будет использовать customTask (его придется модифицировать интегрируя в него 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 но разобраться в ней не смог, может кто пробовал/знает другие способы. Буду очень благодарен советам и помощи в этом вопросе.
