Skip to main content
Если события позволяют реагировать на корзину, а действия позволяют её изменять, то хуки меняют поведение самой корзины: как отрисовываются позиции, какие данные они несут и что происходит при добавлении в корзину. Хуки находятся в window.aftersell.cart.hooks.
Хук меняет то, что покупатель видит; действие меняет то, что находится в его корзине. Скрытие позиции бесплатного подарка с помощью трансформации оставляет её в корзине и в итоговой сумме. Удаление её через removeItem убирает её по-настоящему.
Хуки — это вызовы настройки, поэтому их безопасно регистрировать в самом начале вашего скрипта, без необходимости ждать ready(). Регистрируйте их в скрипте Initialization вашей корзины (см. Пользовательские скрипты).

Как работает регистрация

Каждый хук — это метод register*. Вы вызываете его со своей функцией; он возвращает функцию отмены регистрации, которую можно вызвать, чтобы удалить вашу.
Регистрация аддитивна, поэтому ваша функция работает рядом со всеми остальными. Это важно, потому что ваш скрипт редко бывает единственным на странице: приложение подписок, приложение комплектов и сама тема могут регистрироваться на один и тот же хук. Никто из них не может заменить ваш, и ничто из зарегистрированного вами не может быть молча отброшено тем, что загружается после вас. Хук, который выбрасывает исключение или не является функцией, пропускается; остальные продолжают работать, и корзина работает дальше. Одна сломанная интеграция не может вывести из строя добавление в корзину, селектор подписок или сортировку. Обратная сторона в том, что ваш сломанный хук отказывает молча: ничего не попадает в консоль браузера. См. Отладка о том, где эти сбои всё же проявляются.

registerLineTransform

registerLineTransform(fn) выполняется для каждой позиции корзины перед её отрисовкой. Используйте его, чтобы скрыть позицию или изменить её отображение, не затрагивая фактическое содержимое корзины покупателя. Функция получает позицию только для чтения плюс сеттеры. Возвращает функцию отмены регистрации.
Трансформация меняет только то, что отрисовывается. Она не может изменить цену, количество или идентичность позиции. Для этого используйте действия.
Используйте для: скрытия позиций подарков за покупку или добавленных приложениями, переименования позиций подписки, пометки товаров со скидкой, скрытия компонентов комплектов, которыми покупатель не должен управлять по отдельности. setInternalProperties — это сеттер, лежащий в основе группировки комплектов: проставление канонических свойств комплекта на каждую позицию — это способ заставить отдельные позиции корзины стороннего приложения отрисовываться как один товар. См. Группировка позиций комплектов из другого приложения.

registerLineComparator

Компаратор в той же форме, которую ожидает Array.prototype.sort. Он выполняется после скрытия и переименования, поэтому видит трансформированные позиции.
Компараторы составляются как разрешение ничьих: первый, вернувший ненулевое значение, решает для этой пары, а остальные опрашиваются только при ничьих. Возвращайте 0 для пар, о которых у вас нет мнения. Именно это передаёт решение следующему компаратору вместо навязывания ему порядка. Используйте для: поднятия подписок или дорогих товаров наверх, опускания бесплатных подарков и дополнений вниз, удержания спонсируемого товара первым.

registerCartEnricher

registerCartEnricher(registration) запрашивает дополнительные данные о товаре или варианте из Shopify Storefront API и прикрепляет их к каждой соответствующей позиции корзины в line.metadata[id]. Используйте его для вывода метаполей, тегов или чего-либо ещё, что предоставляет Storefront API, без необходимости изменений кода со стороны Aftersell. Возвращает функцию отмены регистрации. Каждый раз, когда корзина загружается или меняется, Aftersell запрашивает ваш фрагмент для каждого товара или варианта в корзине и прикрепляет результат. Запрос неблокирующий: корзина отрисовывается сразу и повторно излучает cart_updated, когда данные приходят. Медленный или сбойный фрагмент никогда не задерживает и не ломает корзину.
Поскольку обогащение асинхронно, всегда защищайте чтение, так как line.metadata.pricing равно undefined, пока не разрешится первый запрос, а metadata по умолчанию — {}. Используйте для: вытягивания метаполя на каждую позицию (оценка доставки, список ингредиентов, флаг «отправляется отдельно», множитель лояльности) и его отрисовки через блок Custom code. См. отображение данных метаполей на позициях корзины.
Несколько обогатителей спокойно сосуществуют, поскольку каждый id — это своё пространство имён, поэтому их данные никогда не сталкиваются.
Обогащённые значения возвращаются из Storefront API как есть и не санитизируются. Отображайте их как текст, а не как необработанный HTML.

registerSubscriptionOptionsTransform

Скрывайте или переименовывайте планы продаж, предлагаемые для позиции. Ваша функция получает опции только для чтения плюс сеттеры и ничего не возвращает.
Сеттеры, а не возвращаемый список — чтобы несколько скриптов могли сосуществовать. Если бы этот хук возвращал массив, трансформация, которую интересует только один план, естественным образом написала бы options.filter(...) и молча удалила бы планы всех остальных приложений. С сеттерами вы можете описать только собственные правки: патчи объединяются по плану и по полю, и последний записавший побеждает в настоящем конфликте по одному полю одного плана. Трансформация, выбросившая исключение, ничего не вносит, а остальные всё равно применяются. Каждая трансформация видит исходные опции, а не наполовину пропатченное представление, поэтому порядок регистрации не меняет того, что вы читаете.
Порядок планов остаётся таким, каким его вернул Shopify, поэтому трансформация не может переупорядочивать. Чтобы контролировать, какой план предлагается первым (и на какой подписывает кнопка апгрейда разовой покупки), используйте registerDefaultSubscriptionOptionSelector, который продвигает свой выбор в начало.
Вы также не можете добавить план или изменить цену: у discountPercent нет сеттера, потому что план, который Shopify не подтвердит при оформлении заказа, был бы просто нарушенным обещанием в селекторе.

registerDefaultSubscriptionOptionSelector

Выбирайте, какой план предварительно выбран для позиции. Верните id плана или null, чтобы пропустить.
Побеждает первый селектор, вернувший id доступного плана, поэтому возвращайте null для позиций, которые вас не интересуют, вместо того чтобы гадать. Это передаёт решение следующему селектору вместо его переопределения. Id, не соответствующий ни одному плану позиции, обрабатывается так же, как null, и тоже уступает, поэтому устаревший id не может обнулить селектор. Ваша функция получает (options, context) — тот же context, что и трансформация опций.

registerSkipAddToCartRule

Верните true, чтобы позволить конкретной форме товара добавлять в корзину обычным образом, полностью обходя Aftersell. Это полезно для формы, которой нужен собственный редирект или обработка.
Любое true пропускает, поэтому держите правило узким, соответствующим конкретным формам, которыми вы владеете, и возвращайте false для всего остального. Правила оцениваются в порядке регистрации и останавливаются на первом true, поэтому не помещайте в них побочные эффекты: сработает ли ваше вообще, зависит от того, что зарегистрировалось до него.
Если вы контролируете разметку формы, хук вам вообще не нужен: добавьте класс aftersell-cart-skip-atc к <form>, и Aftersell её не тронет. Используйте этот хук, когда вы не можете редактировать разметку или когда решение зависит от чего-то, что знает только ваш код.
Используйте для: формы предзаказа или запроса цены, которой нужен собственный редирект, пользовательского потока приложения подписок, кнопки «купить сейчас», которая должна вести прямо к оформлению заказа. Чтобы вместо этого отключить перехват для всей страницы, используйте skip_add_to_cart_interceptor, но предпочитайте этот хук, ограниченный названными вами формами.

Что дальше