Чем разметка e-commerce отличается от «обычной» веб-аналитики
Веб-аналитика умеет отправлять события про страницы, скроллы и клики по любым элементам. Это полезно, но денег не считает, даже если задать ценность цели, всё равно это компромиссный вариант. E-commerce разметка добавляет «денежную физику» и бизнес-контекст:
- Деньги и уникальные заказы:
transaction_id
,value
, налоги, доставка, скидки. - Товарный уровень:
item_id
,item_name
, категория/бренд/вариант, количество, цена за единицу. - Поведенческая воронка: просмотры списков → карточек → добавления в корзину → оформление→ покупка.
- Атрибуция дохода: доход раскладывается по источникам, кампаниям, каналам, UTM — не только клики, но и выручка.
Проще говоря, «обычная» аналитика говорит, что делали, e-commerce — сколько это принесло и где теряем деньги.
Зачем разметка e-commerce нужна бизнесу
С e-commerce разметкой видна реальная экономика сайта. Причем вам становятся доступны новые продуктовые метрики и ключевые KPI в аналитических системах:
- Выручка (Revenue) — сколько заработали.
- Средний чек (AOV) = Выручка ÷ Количество заказов. Показывает, сколько в среднем тратит покупатель за заказ и как работают апсейлы/кросс-сейлы.
- Конверсия в покупку (CR) = Заказы ÷ Сессии × 100%. Видно, где «текут» шаги оформления заказа.
- Источник/канал дохода — какой трафик дает деньги, а не просто посещения.
- ROAS = Доход от рекламного канала ÷ Расход на него. Быстрый способ выяснить «окупается / не окупается».
- ROI (базовый) = (Доход − Затраты) ÷ Затраты. Если добавите себестоимость и маржу — получите маржинальный ROI для здравого медиамикса.
- Брошенные корзины — где и почему отваливаются, на каких товарах и сегментах.
- Эффективность промо — купоны, скидки, баннеры и их вклад в выручку.
- Товарная аналитика — лидеры/аутсайдеры, эластичность цены, каннибализация, ассортиментные дыры.
Бонус-уровень (если смотреть в будущее): корректно размеченные события питают value-based bidding в рекламных сетях, серверные конверсии (CAPI), персональные рекомендации, LTV-модели и антифрод. Без разметки бизнес «летит вслепую», с разметкой появляется возможность более крутых рекламных стратегий.
Кто разработал стандарт
Изначально стандарт электронной коммерции предложил Google (еще в Universal Analytics), а внедряется он через Google Tag Manager. Позже схема адаптировалась под GA4, но логика осталась: события с товарными объектами летят в dataLayer
. Сегодня поддержка есть не только у Google, но и у большинства других популярных систем аналитики: OWOX BI, Adobe Analytics, Mixpanel, Amplitute.
dataLayer
— это глобальный JavaScript-массив, в который через методpush()
добавляются объекты (события или параметры). Он служит «очередью событий и данных» для систем веб-аналитики.- Каждый объект обычно содержит:
- ключ
event
— название события ("purchase"
,"view_item"
,"add_to_cart"
); - объект
ecommerce
— описание товаров/корзины/покупки.
Бэкенд и фронт не должны думать, как данные попадают в аналитику. Задача — прокинуть данные в установленной структуре в dataLayer
. Дальше маркетолог/аналитик сам настроит правила в GTM.
2 версии e-commerce
Standard e-commerce (простая)
Фиксирует только базовые точки: просмотр товара, добавление/удаление из корзины, заказ и покупку. Это «минимальный набор», который позволяет видеть продажи и понимать, что трафик приносит деньги.
Базовая версия отвечает на вопрос «Сколько заказов и денег мы получили?».
Enhanced e-commerce (расширенная)
Дает полный путь пользователя: просмотр списка товаров и промобаннеров, клики по карточкам, шаги оформления заказа, возвраты. Эта версия нужна, если бизнес хочет видеть воронку поведения, анализировать брошенные корзины и эффективность промо.
Расширенная версия добавляет к базовой «Где теряем людей и почему?», «Какие промо реально работают?», «Что мешает оформить заказ?».
Какие события нужно отслеживать в стандартной (простой) e-commerce
1. Просмотр товара (view_item)
Фиксирует, когда пользователь открыл карточку товара. Позволяет понять, какие товары реально интересуют покупателей, и сравнить CTR карточек с продажами.
2. Добавление в корзину (add_to_cart)
Фиксируется, когда товар положили в корзину. Измеряем, какие товары чаще всего «хотят» и где дальше «сдувается» воронка.
3. Удаление из корзины (remove_from_cart)
Когда пользователь убирает товар из корзины. Помогает понять, какие товары «разочаровывают» на этапе принятия решения (слишком дорогие, неудобные условия доставки, есть лучшие альтернативы).
4. Оформление заказа (begin_checkout)
Фиксируется, когда пользователь переходит к оформлению заказа (чекаут). Можно анализировать, сколько людей реально начинают покупать и где они останавливаются (адрес доставки, оплата и т. п.).
5. Покупка (purchase)
Фиксируется, когда заказ успешно оформлен и оплачен (или подтвержден). Финальная точка воронки. На этом событии строится реальная бизнес-аналитика: выручка, ROI, источники дохода.

Примечание для разработчиков:
- item_id → лучше использовать внутренний ID товара или SKU, а не название.
- price → всегда как число, без форматирования (
19990
, не"19 990 руб."
). - currency → всегда трехбуквенный ISO-код (
"RUB"
,"USD"
,"EUR"
). - transaction_id → должен быть уникальным, совпадать с ID заказа в CRM/базе.
- items[ ] → это массив объектов, и каждый объект обязан содержать хотя бы
item_id
иitem_name
.
Примеры кода простой e-commerce для интернет-магазина
А теперь переходим к подробному описанию каждого события с примерами и кодом.
Просмотр карточки товара (view_item)
Пользователь зашел на сайт интернет-магазина и кликнул по карточке товара «Смартфон Samsung Galaxy A34», после чего открыл страницу с подробным описанием. В этот момент нужно отправить событие в dataLayer
, чтобы аналитика зафиксировала просмотр товара.
Стандартный код для передачи события в dataLayer
<script>
// Проверяем, что dataLayer инициализирован
window.dataLayer = window.dataLayer || [];
// Отправляем событие просмотра товара
window.dataLayer.push({
"event": "view_item", // название события, по нему триггерится тег в GTM
"ecommerce": {
"items": [{
"item_id": "12345", // уникальный ID товара (SKU или внутренний ID)
"item_name": "Смартфон Samsung Galaxy A34", // название товара
"price": 19990, // цена за единицу, числом
"currency": "RUB" // валюта по ISO 4217
}]
}
});
</script>
event: "view_item"
→ стандартное имя события GA4 / Standard Ecommerce.ecommerce.items[]
→ массив объектов, так как теоретически можно смотреть сразу несколько товаров (например, в quick view).item_id
→ должен совпадать с ID в базе/CRM, чтобы потом можно было маппить данные о продажах.
Реальная ситуация
Здесь и далее все реальные ситуации опишу для случаев на PHP, так как сам им владею и мне в нем проще ориентироваться. Пользователь заходит на страницу товара «Смартфон Samsung Galaxy A34».
Бэкенд в цепочке e-commerce разметки нужен там, где данные важнее «декораций» — он поставляет правильные ID, цены, заказы, а фронт/JS только пушит это в аналитику. Бэкенд (PHP) уже сделал запрос к БД и знает:
- ID товара →
12345
; - Название →
Samsung Galaxy A34
; - Цену →
19990
; - Валюту →
RUB
.
Вместо того чтобы фронт руками собирал эти данные (с HTML), мы генерируем JS-код прямо в шаблоне.
Пример PHP-кода для события view_item
<?php
// Данные о товаре получены на бэке (например, из БД)
$product = [
"id" => 12345,
"name" => "Смартфон Samsung Galaxy A34",
"price" => 19990,
"currency" => "RUB"
];
?>
<!-- Встраиваем JS прямо в шаблон -->
<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
"event": "view_item",
"ecommerce": {
"items": [{
"item_id": "<?php echo $product['id']; ?>", // ID товара
"item_name": "<?php echo htmlspecialchars($product['name'], ENT_QUOTES, 'UTF-8'); ?>", // Название товара
"price": <?php echo $product['price']; ?>, // Цена числом
"currency": "<?php echo $product['currency']; ?>" // Валюта
}]
}
});
</script>
PHP достал данные о товаре → $product
из базы. Эти данные мы подставляем в JavaScript и пушим событие view_item
в dataLayer
. GTM «увидит» событие и передаст его в аналитику.
Когда это нужно:
- Когда фронт не знает цену/ID
На фронте есть только текст и верстка, но настоящая цена и ID приходят из базы. Если их вручную парсить из HTML — будет боль. Проще сразу с бэка вставить вdataLayer
. - При динамических товарах
Если сайт на CMS или e-commerce платформе (например, OpenCart, WooCommerce, 1C-Битрикс) — бэкенд рендерит карточку, и именно он лучше всех знает цену, скидку, ID.
Далее по тексту не буду уже дублировать это примечание, так как оно справедливо для всех типов событий и в реальной жизни используется именно такой подход.
В аналитической системе появится событие view_item
. Аналитик увидит:
- какие товары просматривают чаще всего;
- как часто просмотры товара конвертируются в добавление в корзину и покупку (CTR карточки → add-to-cart rate);
- какие категории/бренды вызывают интерес, но плохо конвертируются.
На основе этого можно сделать следующие выводы:
- Оптимизировать карточки товаров (улучшить фото, описание, цену).
- Найти «магниты трафика» — товары, которые много смотрят, но не покупают.
- Строить товарные воронки: просмотр → корзина → чекаут → покупка.
В итоге это событие — первый кирпичик в воронке электронной коммерции, без которого нельзя понять, какие товары действительно интересуют пользователей.
Добавление в корзину (add_to_cart)
Пользователь на карточке товара нажимает кнопку «Добавить в корзину», или, что важно, но часто забывают об этом сценарии, пользователь, находясь уже в корзине, добавляет еще одну копию товара.
Стандартный код для передачи события в dataLayer
<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
"event": "add_to_cart",
"ecommerce": {
"items": [{
"item_id": "12345", // ID товара
"item_name": "Смартфон Samsung Galaxy A34", // Название
"price": 19990, // Цена числом
"quantity": 1, // Количество добавленных единиц
"currency": "RUB" // Валюта по ISO 4217
}]
}
});
</script>
event: "add_to_cart"
— фиксирует именно добавление.quantity
— обязательно, аналитика считает количество единиц, а не только факт добавления.item_id
иitem_name
— должны совпадать с теми, что использовались вview_item
, иначе товары не будут связаны в отчетах.
Реальная ситуация
Представьте, что кнопка «Добавить в корзину» — обычный HTML. Цена, название и валюта не переданы в верстку в атрибуты, они, конечно, есть, но, чтобы найти их на фронте, придется сильно усложнять код.
Пример бэкенд-кода на PHP для add_to_cart
<?php
// Допустим, в контроллере корзины на сервере мы обработали запрос "добавить товар"
// Получаем данные о товаре из БД
$product = [
"id" => 12345,
"name" => "Смартфон Samsung Galaxy A34",
"price" => 19990,
"currency" => "RUB"
];
// Количество товара, которое пользователь добавил
$quantity = 1;
?>
<!-- PHP выводит JS прямо в ответ -->
<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
"event": "add_to_cart",
"ecommerce": {
"items": [{
"item_id": "<?php echo $product['id']; ?>",
"item_name": "<?php echo htmlspecialchars($product['name'], ENT_QUOTES, 'UTF-8'); ?>",
"price": <?php echo $product['price']; ?>,
"quantity": <?php echo $quantity; ?>,
"currency": "<?php echo $product['currency']; ?>"
}]
}
});
</script>
Здесь фронт знает только ID товара, всё остальное подставил сервер. Такой подход надежнее: цена, скидка, название всегда актуальны и совпадают с базой/CRM. Аналитика получает 100% точные данные о товарах в корзине.
Что это даст аналитикам:
- Понимание, какие товары реально «идут в корзину» (а не только смотрятся).
- Конверсию из просмотра в добавление (add-to-cart rate).
- Возможность анализировать «воронку»: Просмотр → Добавление в корзину → Оформление → Покупка.
- Поиск проблемных товаров — которые часто кладут в корзину, но редко покупают.
Удаление из корзины (remove_from_cart)
Пользователь открыл корзину и решил удалить товар «Смартфон Samsung Galaxy A34». Нужно зафиксировать событие удаления. Важно также не забывать, что если пользователь удаляет из корзины не всю товарную позицию, а только один экземпляр, например, нажатием кнопки -, то это тоже событие удаления, и его необходимо обработать.
Стандартный код для передачи события в dataLayer
<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
"event": "remove_from_cart",
"ecommerce": {
"items": [{
"item_id": "12345", // ID товара
"item_name": "Смартфон Samsung Galaxy A34", // Название
"price": 19990, // Цена числом
"quantity": 1, // Количество удаленных единиц
"currency": "RUB" // Валюта по ISO 4217
}]
}
});
</script>
event: "remove_from_cart"
— стандартное имя события.quantity
— важно, чтобы аналитика знала, сколько единиц товара было убрано.item_id
иitem_name
должны совпадать с теми, что передавались при добавлении в корзину (add_to_cart
).
Реальная ситуация
Фронт может знать только data-id
товара в корзине, но не цену, название или валюту. Тогда фронт не сможет корректно передать полные данные в dataLayer
, их лучше подтянуть с сервера.
Пример бэкенд-кода на PHP для remove_from_cart
<?php
// Допустим, пользователь удаляет товар из корзины
$product = [
"id" => 12345,
"name" => "Смартфон Samsung Galaxy A34",
"price" => 19990,
"currency" => "RUB"
];
// Количество удаляемых единиц
$quantity = 1;
?>
<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
"event": "remove_from_cart",
"ecommerce": {
"items": [{
"item_id": "<?php echo $product['id']; ?>",
"item_name": "<?php echo htmlspecialchars($product['name'], ENT_QUOTES, 'UTF-8'); ?>",
"price": <?php echo $product['price']; ?>,
"quantity": <?php echo $quantity; ?>,
"currency": "<?php echo $product['currency']; ?>"
}]
}
});
</script>
Сервер знает все актуальные данные о товаре: ID, название, цену, валюту. Фронт передает только ID или пользовательский клик. Такой подход гарантирует, что аналитика получает правильные и полные данные, и потом их можно корректно сопоставлять с add_to_cart
и purchase
.
Что это даст аналитикам:
- Понимание, какие товары чаще всего удаляются из корзины.
- Анализ воронки продаж: просмотр → добавление → удаление → покупка.
- Поиск проблемных товаров (дорогие, плохо описанные, неактуальные).
- Возможность оптимизировать интерфейс корзины и предложения апсейлов/кросс-сейлов.
Оформление заказа (begin_checkout)
Пользователь добавил товары в корзину и нажал кнопку «Оформить заказ». На этом этапе важно зафиксировать состав корзины и общую сумму заказа, которые ушли в CRM.
Стандартный код для передачи события в dataLayer
<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
"event": "begin_checkout",
"ecommerce": {
"currency": "RUB", // Валюта корзины
"value": 39980, // Общая сумма корзины
"items": [ // Список товаров в корзине
{
"item_id": "12345",
"item_name": "Смартфон Samsung Galaxy A34",
"price": 19990,
"quantity": 1
},
{
"item_id": "67890",
"item_name": "Чехол для Samsung Galaxy A34",
"price": 1990,
"quantity": 1
}
]
}
});
</script>
event: "begin_checkout"
— стандартное событие GA4 / Standard Ecommerce.currency
иvalue
— помогают аналитике сразу видеть сумму корзины и валюту.items[]
— массив объектов, где каждый объект описывает товар (ID, название, цену, количество).- Аналитика связывает эти товары с событиями
view_item
иadd_to_cart
, чтобы видеть конверсию по воронке.
Реальная ситуация
Фронт в курсе только ID товаров в корзине, но не цены, названия или валюты. Здесь сервер лучше знает актуальные данные о товарах в корзине, чтобы сформировать корректное событие begin_checkout
.
Пример бэкенд-кода на PHP для begin_checkout
<?php
// На сервере получаем содержимое корзины пользователя
$cart = [
[
"id" => 12345,
"name" => "Смартфон Samsung Galaxy A34",
"price" => 19990,
"quantity" => 1
],
[
"id" => 67890,
"name" => "Чехол для Samsung Galaxy A34",
"price" => 1990,
"quantity" => 1
]
];
// Общая сумма корзины
$totalValue = array_sum(array_map(function($item){
return $item['price'] * $item['quantity'];
}, $cart));
$currency = "RUB";
?>
<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
"event": "begin_checkout",
"ecommerce": {
"currency": "<?php echo $currency; ?>",
"value": <?php echo $totalValue; ?>,
"items": [
<?php foreach($cart as $item): ?>
{
"item_id": "<?php echo $item['id']; ?>",
"item_name": "<?php echo htmlspecialchars($item['name'], ENT_QUOTES, 'UTF-8'); ?>",
"price": <?php echo $item['price']; ?>,
"quantity": <?php echo $item['quantity']; ?>
}<?php if (next($cart)) echo ','; ?>
<?php endforeach; ?>
]
}
});
</script>
В итоге мы можем узнать, сколько людей реально хотят купить. Появляется возможность построить воронку продаж: просмотр → добавление → начало чекаута → покупка.
Дополнительно можно анализировать состав корзин на этапе чекаута: какие товары часто уходят вместе, какие дополняются аксессуарами. Поиск проблемных этапов оформления заказа (например, пользователи заходят, но не завершают).
Покупка (purchase)
Пользователь успешно завершил покупку: оплатил заказ и попал на страницу подтверждения (Thank You / Order Confirmation). Важно зафиксировать: номер заказа, сумму и валюту, какие товары были куплены, в каком количестве и по какой цене.
Стандартный код для передачи события в dataLayer
<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
"event": "purchase",
"ecommerce": {
"transaction_id": "78910", // Уникальный ID заказа
"value": 39980, // Сумма заказа
"currency": "RUB", // Валюта по ISO 4217
"items": [ // Список купленных товаров
{
"item_id": "12345",
"item_name": "Смартфон Samsung Galaxy A34",
"price": 19990,
"quantity": 1
},
{
"item_id": "67890",
"item_name": "Чехол для Samsung Galaxy A34",
"price": 1990,
"quantity": 1
}
]
}
});
</script>
transaction_id
— уникальный номер заказа, связывает событие с CRM/базой.value
— полная сумма заказа, включая все товары и их количество.items[]
— массив объектов с купленными товарами.- Совпадение
item_id
с предыдущими событиями (view_item
,add_to_cart
) позволяет строить воронку конверсий.
Реальная ситуация
Фронт может получить только ID заказа или статус оплаты от платежного шлюза, но не знает деталей: какие товары и в каком количестве, актуальные цены и скидки. В таких случаях бэкенд формирует событие purchase на основе данных из базы и передает их в dataLayer
.
Пример бэкенд-кода на PHP для purchase
<?php
// Данные о заказе получены на сервере
$order = [
"id" => 78910,
"currency" => "RUB",
"items" => [
[
"id" => 12345,
"name" => "Смартфон Samsung Galaxy A34",
"price" => 19990,
"quantity" => 1
],
[
"id" => 67890,
"name" => "Чехол для Samsung Galaxy A34",
"price" => 1990,
"quantity" => 1
]
]
];
// Общая сумма заказа
$totalValue = array_sum(array_map(function($item){
return $item['price'] * $item['quantity'];
}, $order['items']));
?>
<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
"event": "purchase",
"ecommerce": {
"transaction_id": "<?php echo $order['id']; ?>",
"value": <?php echo $totalValue; ?>,
"currency": "<?php echo $order['currency']; ?>",
"items": [
<?php foreach($order['items'] as $item): ?>
{
"item_id": "<?php echo $item['id']; ?>",
"item_name": "<?php echo htmlspecialchars($item['name'], ENT_QUOTES, 'UTF-8'); ?>",
"price": <?php echo $item['price']; ?>,
"quantity": <?php echo $item['quantity']; ?>
}<?php if (next($order['items'])) echo ','; ?>
<?php endforeach; ?>
]
}
});
</script>
Всё это даст аналитикам возможность формировать отчеты о реальных продажах и доходе, строить ROI по каналам трафика, источникам и рекламным кампаниям, анализировать эффективности карточек товаров и акций, выявлять брошенные корзины, если товар был добавлен, но не куплен.
Проверка и отладка
Чтобы убедиться, что события e-commerce корректно отправляются и фиксируются в аналитике, используют несколько инструментов:
GTM Preview (режим предварительного просмотра Google Tag Manager)
- Позволяет увидеть все события, которые пушатся в
dataLayer
. - Можно отследить последовательность событий, проверить наличие всех параметров (
item_id
,price
,quantity
,currency
). - Удобно для тестирования перед публикацией изменений.
GA4 DebugView
- В GA4 есть специальный режим DebugView для проверки приходящих событий.
- Позволяет увидеть реальное событие, его параметры и timestamp.
- Можно проверить соответствие событий с фронта или бэка реальной структуре, ожидаемой в аналитике.
Расширения браузера
- Например: DataLayer Checker, Google Tag Assistant, GA Debugger.
- Позволяют быстро видеть содержимое
dataLayer
и проверять, что данные корректно передаются в аналитические системы.
Ну и, конечно же, традиционный способ с консолью браузера: прописываем переменную dataLayer
после каждого шага. Это, наверное, самый надежный и классический способ, но самый долгий.
Типичные ошибки при реализации e-commerce разметки
1. Не совпадают item_id
у товара и в CRM/фиде:
- Из-за этого невозможно корректно связывать просмотры, добавления в корзину и покупки с реальными товарами.
- Решение: использовать один источник истины для
item_id
(SKU или внутренний ID товара).
2. Не передается value
(сумма заказа / цена): аналитика не сможет считать общую выручку, конверсию по источникам и ROI кампаний.
3. Забывают currency
: в международных магазинах это приводит к некорректным отчетам и суммированию разных валют.
4. Дублируются события: часто возникает, если JS-код срабатывает несколько раз на одной странице или при повторных кликах.
Выводы
Корректная реализация событий e-commerce и тщательная проверка всей системы — это основа грамотной аналитики, позволяющая бизнесу принимать обоснованные решения на основе данных. Без нее компания работает «вслепую». Без корректной разметки невозможно понять, какие товары реально интересуют пользователей, и трудно оценить эффективность рекламных кампаний.
Простая e-commerce позволяет отслеживать базовые метрики продаж, такие как просмотры товаров, добавления в корзину и покупки. Она подходит для маленьких магазинов или MVP, когда важна базовая статистика и нет необходимости в глубокой аналитике поведения пользователей.
Расширенная e-commerce дает полную картину поведения покупателей. С ее помощью можно анализировать воронку продаж, брошенные корзины, популярные категории товаров, CTR карточек и эффективность маркетинговых кампаний. Этот подход необходим для профессиональной оптимизации продаж и точной оценки ROI.
А в следующих статьях рассмотрим с примерами, как разметить расширенную электронную торговлю. Затем перейдем к ситуациям, когда нам по каким-то причинам недоступен бэкенд, и приходится строить разметку только с фронтенда. Напоследок поговорим о разметке e-commerce в мобильных приложениях.