WooCommerce

События jQuery в WooCommerce: полный список и примеры

M
Markabus
·11 мая 2023 г.
Фотореалистичный макрокадр экрана под углом: в браузере сверху страница товара интернет-магазина с кнопкой покупки, снизу открытая консоль разработчика со строками журнала; на стекле пыль и тёплый отблеск лампы, внизу край механической клавиатуры

WooCommerce многое делает без перезагрузки страницы: товар уходит в корзину по Ajax, мини-корзина обновляется сама, итоги чекаута пересчитываются при смене способа доставки. Из-за этого привычный подход «навесил обработчик на кнопку при загрузке страницы» ломается — после Ajax-обновления DOM подменяется, и обработчик перестаёт срабатывать.

Решение WooCommerce предлагает своё: набор собственных событий, которые магазин рассылает в ключевые моменты. Подписавшись на них, можно выполнить свой код ровно тогда, когда нужно.

Как устроены события WooCommerce

Почти все события WooCommerce отправляются на document.body, а не на конкретный элемент. Это сделано намеренно: тело документа при Ajax-обновлениях не подменяется, поэтому обработчик переживает любые перерисовки корзины.

Базовый шаблон подписки выглядит так:

jQuery( document.body ).on( 'added_to_cart', function () {
    // код, который выполнится после добавления товара в корзину
} );

Обратите внимание на две детали. Во-первых, слушать нужно именно document.body — попытка навесить обработчик на саму кнопку сработает один раз и перестанет после первого же обновления фрагментов. Во-вторых, в WordPress используется jQuery, а не короткий $: сокращённый алиас по умолчанию отключён.

Событие added_to_cart и его данные

Самое востребованное событие — добавление товара в корзину. Оно приходит с четырьмя аргументами: объектом события, фрагментами разметки для обновления, хешем корзины и ссылкой на кнопку, по которой кликнули. Именно из кнопки удобнее всего доставать данные о товаре:

( function ( $ ) {
    $( document.body ).on( 'added_to_cart', function ( event, fragments, cart_hash, button ) {
        var product_id    = button.data( 'product_id' ),    // идентификатор товара
            product_qty   = button.data( 'quantity' ),      // количество
            product_sku   = button.data( 'product_sku' ),   // артикул
            product_name  = button.data( 'product_name' ),  // название
            product_price = button.data( 'product_price' ), // цена
            currency      = button.data( 'currency' );      // валюта

        // Пример: отправляем событие в аналитику через dataLayer
        window.dataLayer = window.dataLayer || [];
        window.dataLayer.push( {
            event: 'add_to_cart',
            item_id: product_id,
            item_name: product_name,
            quantity: product_qty,
            price: product_price,
            currency: currency
        } );

        // Для отладки: посмотреть все доступные данные кнопки
        console.log( button.data() );
    } );
} )( jQuery );

Строка с console.log( button.data() ) — самый быстрый способ понять, что вообще доступно в конкретной теме: набор атрибутов зависит от шаблона кнопки и установленных плагинов. Посмотрели в консоли, забрали нужное, строку удалили.

Отправлять данные можно куда угодно — в dataLayer для Google Tag Manager, в Яндекс.Метрику через ym() или в собственный эндпоинт. Принцип один: событие даёт вам момент и данные, дальше решаете вы.

Полный список событий

Ниже — события, сгруппированные по месту, где они возникают. Все слушаются на document.body, если не указано иное.

Добавление товара и фрагменты корзины

adding_to_cartсразу после клика по кнопке, до ответа сервера. Аргументы: кнопка, данные запроса
added_to_cartтовар добавлен. Аргументы: фрагменты, хеш корзины, кнопка
removed_from_cartтовар удалён. Аргументы те же
wc_cart_button_updatedкнопка добавления обновлена. Аргумент: кнопка
wc_fragment_refreshфрагменты нужно обновить
wc_fragments_loadedфрагменты загружены (например, мини-корзина)
wc_fragments_refreshedфрагменты обновлены

Страница корзины

updated_wc_divблок корзины перерисован
updated_cart_totalsитоги корзины пересчитаны
cart_totals_refreshedитоги обновлены
cart_page_refreshedстраница корзины обновлена
wc_cart_emptiedкорзина опустошена
applied_couponкупон применён. Аргумент: код купона
removed_couponкупон снят. Аргумент: купон
updated_shipping_methodизменён способ доставки
country_to_state_changedизменена страна, перестроен список регионов

Оформление заказа

init_checkoutпользователь открыл страницу оформления
update_checkoutчекаут нужно пересчитать
updated_checkoutчекаут пересчитан — момент, когда безопасно трогать разметку
checkout_errorпри оформлении возникла ошибка
payment_method_selectedвыбран способ оплаты
applied_coupon_in_checkoutкупон применён на чекауте
removed_coupon_in_checkoutкупон снят на чекауте

Карточка товара

found_variationвыбрана вариация товара. Аргумент: объект вариации

Важно: блочные корзина и чекаут

Это главное, что изменилось за последние годы и о чём молчит большинство старых подборок. В современных версиях WooCommerce корзина и оформление заказа собираются на блоках, а не на классических шорткодах. Блоки построены на React и не используют jQuery, поэтому привычные события чекаута там попросту не приходят.

Вместо них блоки рассылают нативные DOM-события с префиксом wc-blocks_:

document.body.addEventListener( 'wc-blocks_added_to_cart', function ( event ) {
    console.log( 'товар добавлен', event.detail );
} );

Документированы три таких события: wc-blocks_adding_to_cart — запрос на добавление отправлен, wc-blocks_added_to_cart — товар успешно добавлен, wc-blocks_removed_from_cart — товар удалён. Для совместимости WooCommerce переводит свои классические jQuery-события в нативные через внутреннюю функцию translatejQueryEventToNative(), поэтому базовые сценарии с добавлением товара продолжают работать в обоих мирах.

У события wc-blocks_added_to_cart есть параметр preserveCartData: он говорит блокам не перезапрашивать данные корзины, если код, вызвавший событие, уже их обновил. Мелочь, которая экономит лишний запрос.

Практический вывод простой. Перед тем как писать обработчик, посмотрите, на чём собран ваш чекаут. Если на шорткодах — работает весь список выше. Если на блоках — рассчитывайте на wc-blocks_*, а классические события чекаута проверяйте отдельно.

Куда положить код

Скрипт правильнее подключать отдельным файлом с явной зависимостью от jQuery, а не вставлять в подвал темы:

add_action( 'wp_enqueue_scripts', function () {
    wp_enqueue_script(
        'shop-events',
        get_stylesheet_directory_uri() . '/js/shop-events.js',
        array( 'jquery' ),
        '1.0.0',
        true
    );
} );

Зависимость array( 'jquery' ) здесь обязательна: без неё файл может загрузиться раньше самой библиотеки, и обработчик молча не навесится.

Частые ошибки

Обработчик на элементе вместо body. Классика: код срабатывает один раз, а после первого Ajax-обновления перестаёт. Причина в том, что элемент, на который вешали обработчик, уже заменён новым.

Код выполняется до готовности WooCommerce. Если скрипт подключён без зависимости от jQuery или выполняется слишком рано, подписка не создастся. Ошибки в консоли при этом может не быть вовсе.

Двойное срабатывание. Если подписку создавать внутри обработчика другого события — например, внутри updated_checkout, — при каждом пересчёте будет добавляться ещё один обработчик. Через несколько обновлений код выполнится десяток раз. Подписывайтесь один раз при загрузке страницы.

Проверка не на том типе страницы. События корзины не приходят на чекауте и наоборот. Если событие «не работает», сначала убедитесь, что вы на той странице, где оно вообще возникает.

Коротко

События WooCommerce — это способ выполнить свой код в нужный момент работы магазина, не гадая, когда закончится Ajax-запрос. Достаточно запомнить три вещи: слушать document.body, брать данные из аргументов события, а не из DOM, и проверить, на чём собраны ваши корзина и чекаут — на шорткодах или на блоках. От последнего зависит, какой набор событий вам вообще доступен.

Частые вопросы

Q.Почему обработчик перестаёт работать после обновления корзины?

Скорее всего, он навешен на конкретный элемент. WooCommerce при Ajax-обновлении заменяет разметку, и старый элемент вместе с обработчиком исчезает. Подписывайтесь на document.body — он при обновлениях не подменяется.

Q.Почему события чекаута не срабатывают?

Вероятно, у вас блочный чекаут. Блоки построены на React и не используют jQuery, поэтому классические события вроде updated_checkout там не приходят. Для блоков есть нативные события с префиксом wc-blocks_.

Q.Как узнать, какие данные доступны в событии?

Выведите в консоль данные кнопки: console.log( button.data() ) внутри обработчика added_to_cart. Набор атрибутов зависит от темы и плагинов, поэтому проверять нужно на своём магазине.

Q.Почему код выполняется несколько раз?

Обычно потому, что подписка создаётся внутри другого обработчика — например, внутри updated_checkout. При каждом пересчёте добавляется ещё один обработчик. Подписывайтесь один раз при загрузке страницы.

Источники

Предыдущая
Изменяем кнопку добавления в корзину, если товар уже в ней

Читайте также