Недавно в своём телеграм-канале Дмитрий Осиюк дал ссылку на статью Simo Ahava о том, как исключить дублирование транзакций в Google Analytics с помощью customTask. Мы решили перевести данное руководство, чтобы даже у тех, у кого нет времени разбираться с английским, была возможность решить данный вопрос.
Одной из наибольших проблем в модели данных Google Analytics является неизменность исторических данных. При записи информации в таблицу данных она остается там практически навсегда.
Это явление особенно раздражает в двух случаях: при спаме и фиктивных заказах электронной коммерции.
Первый случай является общепризнанной проблемой с открытым и общедоступным протоколом сбора данных. Во втором случае попросту возникает раздражение, которое может привести к полномасштабному саботажу (например, вы можете использовать Measurement Protocol для отправки сотен транзакций в Google Analytics вашего конкурента).
Проблема заключается в дублировании транзакций. На вашем сайте, как и на большинстве других, скорее всего есть страница оплаты, которую можно просмотреть через кеш или историю браузера. При повторном посещении страницы оплаты часто случается, что детали транзакции снова записываются в dataLayer
(или отправляются с помощью метода ga()
), что приводит к дублированию данных вашей электронной коммерции.
Исключение может быть в случаях, когда вы обновляете данные о транзакциях, например:
- удаляете тестовые транзакции;
- редактируете состав транзакций;
- удаляете отменённые заказы.
Я принял решение об использовании customTask, поскольку это позволяет избежать использования лишних триггеров или логической переменной. Мы выполним настройку с помощью Google Tag Manager, однако ничто не мешает вам сделать то же самое прямо в коде analytics.js.
Чтобы проверить есть ли в вашем аккаунте такая проблема:
1) перейдите в Google Query Explorer по этой ссылке;
2) авторизуйтесь в свой Google аккаунт;
3) выберите представление данных, которое хотите проверить;
4) нажмите кнопку Run Query.Если в полученном отчете будет 0 результатов — у вас не было замечено такой проблемы за последние 30 дней. Если же в отчете есть данные — у вас обнаружены дублирующиеся транзакции в выбранном представлении данных.
Оглавление
- Как это работает
- Переменная customTask
- Триггеры и переменные для стандартной электронной коммерции
- DataLayer-переменная для идентификатора транзакции
- 1st Party Cookie для списка идентификаторов транзакций
- Пользовательская переменная JavaScript для проверки наличия идентификатора в списке
- Триггер исключения
- Выводы
Как это работает
Когда вы добавляете переменную customTask
в свои теги, она активируется каждый раз, когда тег пытается выполнить отправку в Google Analytics.
Во время активации метод ищет ключ &ti
, соответствующий значению идентификатора транзакции.
Затем он ищет в вашем браузере уже отправленные идентификаторы транзакций.
- Если требуемый ID транзакций найден в хранилище браузера,
customTask
выполняет блокировку для предотвращения попадания дублирующейся информации в Google Analytics.
- Если требуемый идентификатор не найден в хранилище браузера, то
customTask
отправляет информацию в GA в обычном режиме, но сохраняет ID транзакции в списке уже записанных. Таким образом, в будущем он блокирует отправку любой информации с этим идентификатором.
Важно! Эта функция автоматической блокировки работает только с расширенной версией Электронной торговли. В стандартной электронной торговле customTask
обновляет только хранилище браузера, но при этом ничего не блокирует. В этом случае вам придется использовать дополнительные триггеры. О том, как их настроить, я расскажу дальше.
Переменная customTask
Скопируйте и вставьте приведенный ниже код в переменную Собственный код JavaScript (ниже приведена подробная инструкция). Переменная Собственный код JavaScript должна выглядеть следующим образом:
function() { // customTask Builder by Simo Ahava // // More information about customTask: https://www.simoahava.com/analytics/customtask-the-guide/ // // Change the default values for the settings below. // transactionDeduper: Configuration object for preventing duplicate transactions from being recorded. // https://bit.ly/2AvSZ2Y var transactionDeduper = { keyName: '_transaction_ids', cookieExpiresDays: 365 }; // DO NOT EDIT ANYTHING BELOW THIS LINE var readFromStorage = function(key) { if (!window.Storage) { // From: https://stackoverflow.com/a/15724300/2367037 var value = '; ' + document.cookie; var parts = value.split('; ' + key + '='); if (parts.length === 2) return parts.pop().split(';').shift(); } else { return window.localStorage.getItem(key); } }; var writeToStorage = function(key, value, expireDays) { if (!window.Storage) { var expiresDate = new Date(); expiresDate.setDate(expiresDate.getDate() + expireDays); document.cookie = key + '=' + value + ';expires=' + expiresDate.toUTCString(); } else { window.localStorage.setItem(key, value); } }; var globalSendHitTaskName = '_ga_originalSendHitTask'; return function(customTaskModel) { window[globalSendHitTaskName] = window[globalSendHitTaskName] || customTaskModel.get('sendHitTask'); var tempFieldObject, dimensionIndex, count, ga, tracker, decorateTimer, decorateIframe, iframe; customTaskModel.set('sendHitTask', function(sendHitTaskModel) { var originalSendHitTaskModel = sendHitTaskModel, originalSendHitTask = window[globalSendHitTaskName], canSendHit = true; var hitPayload, hitPayloadParts, param, val, regexI, trackingId, snowplowVendor, snowplowVersion, snowplowPath, request, originalTrackingId, hitType, nonInteraction, d, transactionId, storedIds; try { // transactionDeduper if (typeof transactionDeduper === 'object' && transactionDeduper.hasOwnProperty('keyName') && transactionDeduper.hasOwnProperty('cookieExpiresDays') && typeof sendHitTaskModel.get('&ti') !== 'undefined') { transactionId = sendHitTaskModel.get('&ti'); storedIds = JSON.parse(readFromStorage(transactionDeduper.keyName) || '[]'); if (storedIds.indexOf(transactionId) > -1 && ['transaction', 'item'].indexOf(sendHitTaskModel.get('hitType')) === -1) { canSendHit = false; } else if (storedIds.indexOf(transactionId) === -1) { storedIds.push(transactionId); writeToStorage(transactionDeduper.keyName, JSON.stringify(storedIds), transactionDeduper.cookieExpiresDays); } } // /transactionDeduper if (canSendHit) { originalSendHitTask(sendHitTaskModel); } } catch(e) { originalSendHitTask(originalSendHitTaskModel); } }); }; }
В переменной transactionDeduper
есть объект конфигурации, который при необходимости может быть изменен. Он должен иметь как keyName
, так и cookieExpiresDays кодом.
Задайте необходимое keyName
для файла cookie или ключа localStorage
. Значением по умолчанию является _transaction_ids
Установите для cookieExpiresDays кодом необходимое количество дней существования cookie.
- Файл cookie используется только в том случае, если браузер пользователя не поддерживает
localStorage
. - Если используется
localStorage
, срок действия не устанавливается.
Реализация основной логики происходит ближе к концу блока кода, где я поместил решение с помощью // transactionDeduper
и // /transactionDeduper
.
Все действительно довольно просто, и наблюдается определенное соответствие процессу, который я описал выше.
В случае использования расширенной электронной торговли, customTask
заботится обо всем за вас. Если ID транзакции будет найден в списке сохраненных идентификаторов, он просто заблокирует повторную отправку информации в Google Analytics.
При использовании стандартной электронной торговли customTask
код будет записывать в хранилище только идентификатор, и вам придется самостоятельно обрабатывать логику блокировки.
В любом случае вам нужно добавить эту переменную customTask
во все теги расширенной электронной коммерции и/или Теги транзакций, которые могут отправлять информацию о покупках в Google Analytics.
Как добавить customTask в ваши тэги электронной торговли?
Чтобы добавить customTask в Google Tag Manager вам необходимо создать пользовательскую переменную:
Тип переменной “Собственный код JavaScript”:
В появившееся поля ввода необходимо скопировать код, приведённый выше и дать переменной имя customTask.
Должно получиться так:
Сохраните переменную.
Теперь необходимо подключить во всех тэгах Электронной торговли данную переменную.
Перейдите в раздел “Тэги” и откройте тэг Электронной торговли:
В настройках необходимо проделать следующие операции:
1. Включить переопределение настроек
2. Раскрыть поля “Дополнительные настройки” и “Поля, которые необходимо задать”
3. Ввести название поля customTask
4. Дать ссылку на переменную customTask, которую мы создали ранее.
В нашем случае это {{customTask}}
Сохраните изменения в тэге.
Если код Universal Analytics (analytics.js) установлен непосредственно на сайте, то необходимо проделать следующие операции:
1. Определить функцию JavaScript _customTask — её код приведён выше.
Начало кода выглядит так:
function() { // customTask Builder by Simo Ahava ...
Необходимо в начале дописать:
var _customTask = function() { // customTask Builder by Simo Ahava ...
2. Установить customTask
ga('create', 'UA-XXXXX-Y'); ga('require', 'ec'); ga('ec:addProduct', { 'id': 'P12345', 'name': 'Android Warhol T-Shirt', 'category': 'Apparel', 'brand': 'Google', 'variant': 'black', 'price': '29.20', 'quantity': 1 }); ga('ec:setAction', 'purchase', { 'id': 'T12345', 'affiliation': 'Google Store - Online', 'revenue': '37.39', 'tax': '2.85', 'shipping': '5.34', 'coupon': 'SUMMER2013' }); ga('set', 'customTask', _customTask()); //С помощью данной функции запускаем customTask ga('send', 'pageview');
Триггеры и переменные для Стандартной электронной торговли
Т. к. в стандартной электронной торговле передача информации о покупке делится на хит транзакции и хит информации о товаре, логику блокировки было бы крайне сложно автоматизировать в customTask. Вот почему вам необходимо создать триггер исключения для вашего тега транзакции: он будет блокировать запуск тега, если ID транзакции найден в списке сохраненных идентификаторов.
Переменная уровня данных для идентификатора транзакции
Создайте переменную уровня данных для транзакции, например:
1st Party Cookie для списка идентификаторов транзакций
Создайте переменную 1st Party Cookie для списка ID транзакций, используя keyName
, которое вы указали в customTask
. Вот как будет выглядеть настройка по умолчанию:
Пользовательская переменная JavaScript для проверки наличия идентификатора в списке
Наконец, создайте переменную Собственный код JavaScript, которая возвращает true
, если идентификатор транзакции найден в списке.
function() { // Change this to match the keyName you added to customTask: var keyName = '_transaction_ids'; var ids = JSON.parse((!!window.Storage ? window.localStorage.getItem(keyName) : {{Cookie - _transaction_ids}}) || '[]'); return ids.indexOf({{DLV - transactionId}}) > -1; }
Назовите переменную. Например, {{JS — transactionId sent}}.
Триггер исключения
Последний шаг — создать триггер, который блокирует срабатывание тега транзакции. Триггер должен использовать то же событие, что и тег транзакции. Если тег транзакции срабатывает в триггере просмотра страницы, триггер исключения также должен являться триггером просмотра страницы (подробнее об исключениях читайте здесь).
В условиях триггера проверьте, является ли {{JS — transactionId sent}} равным значению true
. Таким образом, триггер исключения заблокирует тег, если ID транзакции найден в списке уже записанных идентификаторов.
Вот пример того, как выглядит исключение с триггером пользовательского события, и как оно добавляется в тег:
Выводы
Поиски по усовершенствованию качества данных Google Analytics с помощью customTask
продолжаются до сих пор.
Предотвращение отправки информации при возникновении определенных условий подходит для запуска через customTask
, так как в этом случае вам не нужно возиться со сложными триггерами, загромождающими интерфейс GTM.
Однако каждый дополнительный customTask
снижает прозрачность вашей настройки, что не позволит сказать с первого взгляда, какую задачу решает тот или иной тег.
Понравилась статья? Делитесь ей в соцсетях!
Оставляйте ваши вопросы на нашей странице в Facebook