1С-Битрикс. Добавление кода Google Analytics для отслеживания заказов
Зачастую, для настройки электронной коммерции в 1С-Битрикс, советуют вставить в шаблон компонента sale.order.ajax код. Пойдем другим путём и напишем универсальный обработчик.
Плюс обработчика в том, что не надо лазить по шаблонам и искать куда вставить код. Подключил и он сам вызывается в нужный момент.
Код обработчика
Сохраняем код в файле /local/php_interface/classes/handlers/orderajaxcomponenthandler.php
namespace Olegpro\Handlers\Sale; class OrderAjaxComponentHandler { /** * @param int $orderId * @param $arOrder * @param $arParams */ function AddGoogleAnalyticsEcommerceCode($orderId, $arOrder, $arParams) { global $APPLICATION; if (isset($_SESSION['GA_ORDER_ID']) && $_SESSION['GA_ORDER_ID'] == $orderId) { return; } if (!($order = \CSaleOrder::GetByID($orderId))) { return; } $output = array(); $site = \CSite::GetByID($order['LID'])->Fetch(); $output[] = "ga('require', 'ecommerce', 'ecommerce.js');"; $output[] = sprintf("ga('ecommerce:addTransaction', %s);", \CUtil::PhpToJSObject( array( 'id' => (int)$orderId, 'affiliation' => (string)$site['NAME'], 'revenue' => (float)$order['PRICE'], 'shipping' => (float)$order['PRICE_DELIVERY'], 'tax' => '', ), false, true, true ) ); $basketIterator = \CSaleBasket::GetList( array( 'NAME' => 'ASC', ), array( 'ORDER_ID' => $orderId, ), false, false, array( 'PRODUCT_ID', 'NAME', 'PRICE', 'QUANTITY', ) ); $basketItems = array(); $productsIds = array(); $productsData = array(); while ($basketItem = $basketIterator->fetch()) { $basketItems[] = $basketItem; $productsIds[] = $basketItem['PRODUCT_ID']; } unset($basketItem); $resProducts = \CIBlockElement::GetList( array(), array( 'ID' => array_unique($productsIds) ), false, false, array( 'ID', 'IBLOCK_ID', 'IBLOCK_SECTION_ID', ) ); while ($arProduct = $resProducts->Fetch()) { $arProduct['SECTION_NAME'] = ''; if (intval($arProduct['IBLOCK_SECTION_ID']) > 0) { $sectionIterator = \CIBlockSection::GetList( array(), array( 'ID' => $arProduct['IBLOCK_SECTION_ID'], ), false, array( 'NAME', ) ); if ($arSection = $sectionIterator->Fetch()) { $arProduct['SECTION_NAME'] = $arSection['NAME']; } } $productsData[$arProduct['ID']] = $arProduct; } foreach ($basketItems as $basketItem) { $output[] = sprintf( "ga('ecommerce:addItem', %s);", \CUtil::PhpToJSObject( array( 'id' => (int)$orderId, 'name' => (string)$basketItem['NAME'], 'sku' => (string)$basketItem['PRODUCT_ID'], 'category' => (string)(isset($productsData[$basketItem['PRODUCT_ID']]) ? $productsData[$basketItem['PRODUCT_ID']]['SECTION_NAME'] : ''), 'price' => (float)$basketItem['PRICE'], 'quantity' => (int)$basketItem['QUANTITY'], ), false, true, true ) ); } $output[] = "ga('ecommerce:send');"; \Bitrix\Main\Page\Asset::getInstance()->addString( '<script>' . implode("\n", $output) . '</script>', true ); $_SESSION['GA_ORDER_ID'] = $orderId; } }
Добавить в /local/php_interface/init.php
Подвешиваемся на нужное и событие и добавляем класс обработчика в автозагрузку:
\Bitrix\Main\EventManager::getInstance()->addEventHandler('sale', 'OnSaleComponentOrderOneStepFinal', array('\Olegpro\Handlers\Sale\OrderAjaxComponentHandler', 'AddGoogleAnalyticsEcommerceCode') ); \Bitrix\Main\Loader::registerAutoLoadClasses(null, array( '\Olegpro\Handlers\Sale\OrderAjaxComponentHandler' => '/local/php_interface/classes/handlers/orderajaxcomponenthandler.php', ));
Событие OnSaleComponentOrderOneStepFinal вызывается перед выводом страницы об успешно созданном заказе.
Примечание
Если вызов функции:
$APPLICATION->ShowHead()
идет в шаблоне выше, чем код гугл аналитики, то строку:
\Bitrix\Main\Page\Asset::getInstance()->addString( sprintf('<script>%s</script>', implode("\n", $output)), true );
следует заменить на:
echo sprintf('<script>%s</script>', implode("\n", $output))
28 комментариев
Большое спасибо за ваш пример! Пытаюсь его внедрить, но, наверное, где-то есть ошибка. У меня такой вопрос: после срабатывания обработчика и успешного выполнения функций результат в виде скрипта GA должен быть выведен на странице с сообщением об успешно созданном заказе?
Да, всё верно. этот код будет добавлен всего один раз на страницу для каждого вновь созданного заказа.
Есть один нюанс. Обновил заметку, добавил блок «Примечание».
Здравствуйте, Скажите пожалуйста, куда вносится данный код? Немного не понимаю, что такое универсальный обработчик. Можно ли добавить в этот код передачу «параметров интернет-магазинов» в Яндекс.Метрику
Денис, этот код добавляется в init.php.
Для Яндекс.Метрики нужно написать новый. На основе моего не составит особого труда.
Попытался переделать под расширенную электронную коммерцию, но не выходит. 1. На сайт установлен модуль Univirsal Analytics (который подгружает библиотеки расширенной электронной коммерции). 2. Сайт полностью обновлен до последней версии. 2. В init.php вставлен код:
Данные о покупке не приходят.
Для интеграции и отладки нужны базовые знания 1С-Битрикс и PHP.
Базовые знания есть, код ваш понятен, просто не пойму почему данные не уходят. Можете все-таки глянуть код выше, может ошибку найдете?
У меня сработало только событие OnSaleComponentOrderOneStepComplete. Прогоняется ли гугловый скрипт - ещё не удалось посмотреть. To ЯН: просмотрите все массивы - формируется ли что вообще.
Странно, что у вас сработало событие OnSaleComponentOrderOneStepComplete. Оно вызывается перед редиректом на страницу «Спасибо за заказ». То есть страница «Спасибо», куда и нужно вставить код для электронной торговли, вызывается уже без этого события.
Ладно, хоть что-то сработало. Мне кажется ваш вариант интеграции наиболее правильным. И главный вопрос: почему echo не выводит скрипт? Или куда он выводится и почему не выполняется?? Пробовал alert'ы - тишина...
Вообщем строку
$arSite['NAME']
замнил на 'мойсайт.ru' - и заработало.OnSaleComponentOrderOneStepComplete вызывается при выполнении условия if ($USER->IsAuthorized() || $arParams["ALLOW_AUTO_REGISTER"] == "Y" ), OnSaleComponentOrderOneStepFinal - при невыполнении. Прошу надоумить, как отследить, отрабатывается ли script, который, как я сказал, формируется правильно?? Пробовал и AddHeadString и просто echo.
Из документации:
OnSaleComponentOrderOneStepComplete — Вызывается в компоненте bitrix:sale.order.ajax после создания заказа и всех его параметров, после отправки письма, но до редиректа на страницу с информацией о созданном заказе и оплате заказа.
OnSaleComponentOrderOneStepFinal — Вызывается в компоненте bitrix:sale.order.ajax после создания заказа и всех его параметров, после отправки письма, перед выводом страницы об успешно созданном заказе и оплате заказа.
http://dev.1c-bitrix.ru/api_help/sale/events/events_components.php
Отследить отрабатываемый скрипт можно посмотрев в панели разработчика в браузере или в файербаге.
Извиняюсь, но буду признателен, если поможете добить этот скрипт. Похоже, у меня OnSaleComponentOrderOneStepFinal, при котором у кого-то ваш способ работает, не срабатывает из-за отсутствия оплаты (способ оплаты - наличные курьеру). Т.е., товар неоплачен. Можно как-то в моём случае его все таки запустить?
Спасибо за статью, Олег! Вы показали 2-ва куска кода. Куда добавлять первый: \Bitrix\Main\EventManager::getInstance()->addEventHandler('sale', 'OnSaleComponentOrderOneStepFinal', array('\Olegpro\Handlers\Sale\OrderAjaxComponent', 'AddGoogleAnalyticsEcommerceCode') );
Владимир в init.php
Олег, если код просто вставить в init.php, сайт перестает работать
Владимир, какая версия битрикса?
Тут нужны базовые знания PHP. Есть ли открывающий тег <?php и т.п.
Олег, 15.0. Вы можете сбросить мне на почту pleo@i.ua код, что надо вставить в init.php. Может я не совсем верно понял, что вставлять надо. Спасибо.
Владимир, код за вас я писать не буду :)
Но обновил текст заметки, теперь должно быть понятнее.
Олег, спасибо. Мне и так - супер.
Круто только такого файла по адресу нет. Вообще вся папка local пустая
Значит local в путях замените на bitrix.
Привет! А если этот код прописать в самом init.php и повесить его на событие OnSaleOrderSaved, который вызывается после сохранения заказа не зависимо с какого места (админка, фронт), такая схема сработает?
Сработает, если немного изменить код (событие OnSaleOrderSaved вызывается с другими параметрами).
Вывел все в init.php, но данные не отправляются. У меня ecommerce настроен через dataLayer.push, может в этом проблема? А так-же есть сомнения по поводу того где должен быть расположен сам код GTM и соответственно аналитикс. Вывожу его тоже в init.php, но ничего не происходит. Остальные действия по этому события работают корректно, данные с заказа также выгружаются корректно. Есть какие-то мысли по этому поводу? Спасибо!
Если у вас гугл аналитика подключена через GTM - этот код не сработает.
Там нужен другой формат js. По-моему, как тут https://www.olegpro.ru/post/elektronnaya_kommerciya_yandeksmetriki_v_1s_bitriks_s_podderzhkoy_google_tag_maganer_gtm.html