Skip to main content
События позволяют запускать код, когда что-то происходит в корзине. Они находятся в window.aftersell.cart.events. Подписка — это вызов настройки, поэтому её безопасно размещать в начале вашего скрипта, без необходимости ждать ready().

Доступные события

Подписка

events.on(event, handler) регистрирует обработчик и возвращает функцию, которая отменяет подписку:
  • events.once(event, handler): срабатывает один раз, затем отписывается сам.
  • events.off(event, handler): удаляет конкретный обработчик.
Обработчик, выбросивший исключение, изолируется и логируется в консоль; остальные обработчики продолжают выполняться.

Два правила

Почти каждая ошибка с событиями сводится к одному из них.

Не изменяйте корзину из cart_updated без защитного условия

Изменение корзины внутри обработчика cart_updated снова вызывает cart_updated. Если этот обработчик снова изменяет корзину, у вас бесконечный цикл. Покупатель наблюдает, как его корзина лихорадочно меняется, пока страница бомбардирует Shopify.
Никогда не вызывайте действие безусловно из cart_updated или cart_loaded. Защитите его проверкой состояния, которое вы собираетесь создать, чтобы второй проход ничего не делал.
Корзина даёт вам одну страховку: обновление, дающее идентичную корзину, ничего не излучает, поэтому повторный запрос, который ничего не меняет, не перезапустит цикл. Это защищает от случайных «пустых» циклов. Это не защищает от обработчика, который действительно каждый раз изменяет корзину.

Считайте payload доступным только для чтения

Каждый обработчик одного события получает один и тот же объект. Его мутация меняет то, что видят обработчики после вашего, включая обработчики, принадлежащие другим приложениям магазина.
Чтобы действительно изменить корзину, используйте действие. Чтобы изменить отрисовку позиций, используйте registerLineTransform.

cart_loaded

Срабатывает один раз, когда корзина впервые загружается на странице. Payload — полный объект корзины.
Используйте для: всего, что должно выполняться относительно начального состояния корзины, например сверки бесплатного подарка, инициализации виджета или отправки содержимого корзины в аналитику при загрузке страницы. cart_loaded повторно воспроизводится для поздних подписчиков. Если вы подпишетесь после того, как корзина уже загрузилась, ваш обработчик вызывается немедленно с текущей корзиной. Порядок подписки никогда не имеет значения, поэтому вам не нужно беспокоиться о том, успел ли ваш скрипт раньше корзины.
Логика, которая должна быть корректной и при загрузке страницы, и при каждом последующем изменении, должна подписываться и на cart_loaded, и на cart_updated одной и той же функцией. Это стандартный паттерн для «держать X в синхронизации с корзиной».

cart_updated

Срабатывает каждый раз, когда содержимое корзины меняется после первой загрузки, будь то из drawer, из ваших собственных действий, из темы или из другого приложения. Payload — полный объект корзины.
Используйте для: синхронизации чего-либо вне корзины, например пользовательской итоговой суммы, индикатора прогресса, значка в шапке или события аналитики при каждом изменении. Обновление, дающее идентичную корзину, ничего не излучает. Повторное открытие drawer, возврат к вкладке или повторный запрос, вернувший то же содержимое, его не вызовут.
Перечитайте два правила перед вызовом действия отсюда.

item_added

Срабатывает, когда в корзине появляется новая позиция. Payload — { item }, где item — это позиция корзины.
Используйте для: отслеживания добавлений в корзину в стороннем инструменте аналитики. Это самое распространённое использование SDK. См. отслеживание добавления в корзину. Две вещи, которые нужно знать о том, как оно вычисляется:
Изменение количества — это не добавление. Корзина определяет добавления и удаления, сравнивая позиции, а не количества. Покупатель, увеличивший позицию с 1 до 3, вызывает cart_updated, а не item_added. Если вам нужно ловить и увеличения количества, сравнивайте с предыдущим состоянием в обработчике cart_updated.
Оно также не срабатывает для товаров, которые уже были в корзине при загрузке страницы; они приходят через cart_loaded. Добавление нескольких разных товаров сразу вызывает событие один раз на каждую позицию.

item_removed

Срабатывает, когда позиция исчезает из корзины. Payload — { item }, позиция в том виде, в каком она была непосредственно перед исчезновением, поэтому вы всё ещё можете прочитать её key, variantId и title.
Используйте для: отмены того, что вы сделали при добавлении, например сброса флага, повторного показа предложения, от которого покупатель отказался, или отправки удалений в аналитику. То же предостережение, что и для item_added: уменьшение количества без достижения нуля не является удалением.

cart_opened и cart_closed

Срабатывают при открытии и закрытии drawer. Без payload.
Используйте для: отслеживания просмотров, приостановки видео или карусели за drawer, переключения класса на странице. Ни одно из них не срабатывает при первоначальной загрузке страницы, только при фактическом открытии или закрытии.

checkout

Срабатывает, когда покупатель нажимает кнопку оформления заказа, непосредственно перед навигацией браузера. Без payload.
Используйте для: отслеживания намерения оформить заказ.
Вы не можете отменить оформление заказа из этого обработчика. Событие — это уведомление, а не барьер; навигация происходит независимо от того, что делает ваш код. Держите обработчик быстрым и синхронным: await или медленный сетевой вызов могут не успеть завершиться до выгрузки страницы. Используйте navigator.sendBeacon для всего, что нужно надёжно отправить.

Прослушивание извне SDK

Каждое событие также отправляется как DOM CustomEvent на window, поэтому вы можете слушать, не касаясь window.aftersell.cart. Это полезно из файла темы, стороннего приложения или скрипта, загружающегося независимо от корзины. Обратите внимание на именование: шина использует snake_case, DOM-события используют kebab-case с префиксом aftersell:cart:.
Payload приходит в event.detail и соответствует объекту корзины. События отправляются на window, поэтому слушатель в любом месте страницы их получает. Корзина отрисовывается в shadow root, но граница shadow никогда не находится на пути события. Каждая отправка клонирует payload, поэтому слушатель, мутирующий event.detail, не может повлиять на других, а слушатель, выбросивший исключение, не может нарушить работу SDK.
cart-loaded не воспроизводится повторно в DOM. Шина повторно воспроизводит cart_loaded для поздних подписчиков, но этот путь обходит DOM-отправку, поэтому window.addEventListener('aftersell:cart:cart-loaded'), зарегистрированный после того, как корзина уже загрузилась, никогда не сработает. Если порядок загрузки вашего скрипта не гарантирован, используйте window.aftersell.cart.events.on('cart_loaded', …), который воспроизводится повторно, или также слушайте aftersell:cart:cart-updated.

Стандартные события корзины Shopify

Отдельно корзина публикует стандартные события корзины Shopify на document всякий раз, когда она изменяет корзину, поэтому код темы и другие приложения могут реагировать на мутации Aftersell так же, как они реагируют на мутации темы:
Payload не находится в event.detail. detail несёт только { source: 'aftersell' } — метку, которую корзина использует, чтобы игнорировать собственные события вместо зацикливания. Всё из таблицы выше присваивается непосредственно объекту события, поэтому читайте event.action, а не event.detail.action.
Каждое событие также несёт promise, который Aftersell разрешает, когда завершается базовая запись, в соответствии со стандартом Shopify — ожидайте его, не разрешайте сами. Они отправляются на document и всплывают, поэтому слушатель на window тоже их получает.

Что дальше