Электронная торговля в аналитике - события, покупка, сверка
Настраиваем передачу покупок во внешнюю аналитику: события воронки, покупка без дублей и сверка с тем, что действительно лежит в базе заказов.
Механика
Внешняя аналитика видит не заказы, а события браузера. Покупка для неё - это сообщение, отправленное со страницы благодарности, а не запись в базе. Отсюда все её особенности: пропущенное сообщение означает пропущенную покупку, а отправленное дважды - две покупки на один заказ.
События образуют воронку. Просмотр карточки, добавление в корзину, начало оформления и покупка - разные сообщения с общим набором полей: номер товара, цена, количество, категория. Именно совпадение этих полей позволяет отчёту связать шаги между собой.
Кэш и композит вмешиваются в эту цепочку. Событие, встроенное в кэшируемую часть страницы, отправляется ровно один раз - при сборке копии, а не при показе. Всё, что должно срабатывать у каждого посетителя, живёт в динамической части.
Отдельно стоит вопрос доверия к числам. Блокировщики, отключённые скрипты и уход со страницы до отправки дают в аналитике меньше покупок, чем в базе. Расхождение в проценты - норма, в разы - повод разбираться.
Наконец, персональные данные. Телефон, почта и адрес покупателя во внешнюю аналитику не отправляются: там достаточно номера заказа и состава корзины, а всё остальное превращает удобный отчёт в утечку.
Стоит заранее договориться, чьи это числа. Отчёт аналитики нужен маркетологу, а бухгалтерии нужна база заказов, и попытка свести их до копейки заканчивается неделей выяснений и выводом, что расхождение объясняется блокировщиками. Полезнее следить за динамикой: сегодняшнее расхождение сравнивают со вчерашним, а не с нулём.
Шаги
- Завести счётчик и цели в кабинете сервиса аналитики.
- Поставить код счётчика в шаблон сайта, вне кэшируемых блоков.
- Отправлять события просмотра и корзины из соответствующих мест витрины.
- Отдать покупку один раз на странице благодарности, с защитой от повтора.
- Исключить из отчётов свои визиты и тестовые заказы.
- Завести ежедневную сверку числа покупок с числом заказов в базе.
Код
Ставим счётчик в шаблон сайта:
// footer.php шаблона сайта, вне кэшируемых областей$APPLICATION->AddBufferContent(function () { return '<script>/* код счётчика из кабинета сервиса */</script>';});// в кэшируемой части он отработает один раз - при сборке копии страницыСчётчик живёт в шаблоне сайта, а не в каждом шаблоне компонента. Отложенный вывод здесь важнее удобства: он гарантирует, что код попадёт на страницу и при включённом композите.
Отправляем событие просмотра товара:
// шаблон карточки товара$event = ['event' => 'view_item', 'items' => [[ 'item_id' => $arResult['ID'], 'item_name' => $arResult['NAME'], 'price' => (float)$arResult['PRICE']['DISCOUNT_VALUE'], 'item_category' => $sectionName,]]];echo '<script>window.dataLayer=window.dataLayer||[];dataLayer.push(' . \Bitrix\Main\Web\Json::encode($event) . ');</script>';Просмотр, корзина и оформление - разные события одной воронки. Набор полей у них общий, и именно по номеру товара отчёт связывает просмотр с последующей покупкой.
Отправляем добавление в корзину:
// в обработчике ответа на добавление товараBX.addCustomEvent('OnBasketChange', () => { dataLayer.push({ event: 'add_to_cart', items: [{ item_id: id, price, quantity }] });});// событие отправляют после успешного ответа сервера, а не по кликуСобытие отправляют после успешного ответа сервера, а не по нажатию кнопки. Клик без ответа означает, что товар в корзину не попал, а в отчёте он уже посчитан.
Отдаём покупку на странице благодарности:
// шаблон sale.order.ajax, шаг подтверждения заказа$orderId = (int)$arResult['ORDER_ID'];if ($orderId && !isset($_SESSION['ECOM_SENT'][$orderId])) { $_SESSION['ECOM_SENT'][$orderId] = true; // защита от повторной отправки echo '<script>dataLayer.push(' . Json::encode($purchase) . ');</script>';}// без этой отметки обновление страницы даёт вторую покупку на тот же заказПокупку отправляют один раз. Отметка об отправке в сеансе - самая дешёвая защита: без неё каждое обновление страницы благодарности добавляет в отчёт ещё одну покупку с той же суммой.
Собираем состав покупки из заказа:
$order = \Bitrix\Sale\Order::load($orderId);$items = [];foreach ($order->getBasket() as $item) { $items[] = ['item_id' => $item->getProductId(), 'price' => (float)$item->getPrice(), 'quantity' => (float)$item->getQuantity()];}$purchase = ['event' => 'purchase', 'transaction_id' => $order->getField('ACCOUNT_NUMBER'), 'value' => (float)$order->getPrice(), 'items' => $items];Состав покупки берут из заказа, а не из параметров адреса. Данные из адресной строки теряются при переходах и подделываются вручную, а заказ в базе - источник, которому можно верить.
Сверяем отчёт с базой:
$cnt = \Bitrix\Sale\Internals\OrderTable::getList([ 'select' => ['CNT' => new \Bitrix\Main\Entity\ExpressionField('CNT', 'COUNT(%s)', 'ID')], 'filter' => ['>=DATE_INSERT' => $dayStart, '!=STATUS_ID' => 'TEST'],])->fetch();printf("заказов за сутки: %s\n", $cnt['CNT']);// это число сравнивают с числом покупок в отчёте сервисаЧисло покупок в отчёте сверяют с числом заказов. Расхождение в несколько процентов объясняется блокировщиками, а в разы - сломанной отправкой, и заметить это стоит в тот же день.
Исключаем свои визиты и тестовые заказы:
// служебные заказы помечают статусом или свойством и не отдают в аналитикуif ($order->getField('STATUS_ID') === 'TEST' || $USER->IsAdmin()) { return; // событие покупки не отправляем вовсе}// визиты сотрудников отсекают настройками счётчика в кабинете сервисаСвои визиты и тестовые заказы искажают отчёт сильнее всего на небольшом магазине. Десяток проверочных заказов в день при полусотне настоящих превращает конверсию в выдумку, и решают это одновременно с двух сторон: кодом и настройками кабинета.
Ограничения
Настройка живёт не в коде, а между кодом и кабинетом сервиса. Половина неработающих отчётов объясняется не ошибкой в скрипте, а тем, что цель в кабинете названа иначе или вовсе не создана. Проверять стоит обе стороны сразу, иначе разбор уходит в чтение своего кода, где всё в порядке.
Часть посетителей не отдаст событий никогда: блокировщики, отключённые скрипты, закрытая вкладка до отправки. Аналитика по устройству показывает меньше, чем есть на самом деле, и строить на её числах бухгалтерию нельзя.
Отчёты сервисов обновляются с задержкой, иногда до суток. Проверять свежую настройку по вчерашнему отчёту бессмысленно: для проверки есть режим отладки в самом кабинете и консоль браузера.
Названия событий и состав их полей задаёт сам сервис аналитики, а не платформа. Они меняются от сервиса к сервису и время от времени обновляются, поэтому конкретный набор берут из его документации, а не из чужой статьи трёхлетней давности. Общей остаётся только механика: событие с полями товара, отправленное в нужный момент.
Оплата на стороне банка уводит покупателя с сайта. Если он не вернётся на страницу благодарности, покупка не отправится вовсе, и такие случаи закрывают отправкой с сервера при отметке оплаты - отдельной задачей.
Типичные проблемы
В отчёте покупок вдвое больше, чем заказов.
Событие покупки отправляется при каждом показе страницы благодарности. Отметка об отправке покупки в сеансе посетителя закрывает этот повтор.
Покупки не приходят вовсе.
Код события попал в кэшируемую часть страницы и отработал один раз. Всё, что должно срабатывать у каждого, живёт в динамической части.
Суммы в отчёте не сходятся с заказами.
Состав покупки собран из параметров адресной строки, а не из заказа. Источником должен быть сам заказ в базе.
В отчёте есть заказы менеджеров.
Тестовые заказы и визиты сотрудников не исключены из учёта. Их отсекают статусом самого заказа и настройками счётчика в кабинете.
В аналитику уехали телефоны покупателей.
В событие попал весь массив свойств заказа целиком. В событиях оставляют только номер заказа и состав его корзины.
Частые вопросы
Почему в аналитике меньше покупок, чем в базе?
Часть посетителей не отдаёт событий из-за блокировщиков и закрытых вкладок. Расхождение в проценты - это норма.
Как проверить отправку сразу?
Режимом отладки в кабинете сервиса и консолью браузера. Ждать отчёта следующего дня не нужно.
Что делать, если покупатель не вернулся с оплаты?
Отправлять покупку с сервера при отметке оплаты. Это отдельная задача со своими сложностями.
Можно ли отправлять почту покупателя?
Не стоит: это персональные данные во внешнем сервисе. Номера заказа и состава корзины достаточно.
Нужны ли события просмотра и корзины?
Без них отчёт покажет покупки, но не покажет, где теряются посетители. Воронка и есть главная польза.
Смежное
- Оформление заказа - оглавление подтемы
- Источник заказа: метки в адресе, хранение, отчёт - свои данные об источнике рядом с аналитикой
- События оформления заказа: свои проверки, запрет и допданные - где заказ действительно создаётся
- Композитный сайт: включение, динамические области, сброс - почему событие не срабатывает
- A/B-тест на витрине: варианты, доли, цели, результаты - как проверить гипотезу по этим целям
- Отчёты по заказам: агрегаты, группировка, выгрузка - числа, с которыми сверяют отчёт
- Каталог и продажи - устройство магазина целиком