Зачастую, для настройки электронной коммерции в 1С-Битрикс, советуют вставить в шаблон компонента sale.order.ajax код. Пойдем другим путём и напишем универсальный обработчик.

Плюс обработчика в том, что не надо лазить по шаблонам и искать куда вставить код. Подключил и он сам вызывается в нужный момент.

Код обработчика

Сохраняем код в файле /local/php_interface/classes/handlers/orderajaxcomponenthandler.php

<?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

Подвешиваемся на нужное и событие и добавляем класс обработчика в автозагрузку:

<?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))