Недавно в своём телеграм-канале Дмитрий Осиюк дал ссылку на статью 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










