Корзина и избранное
Виджеты SearchBooster не хранят корзину сами: они спрашивают у сайта, что сейчас в корзине и избранном, и сообщают сайту, когда покупатель нажал кнопку. Подключение отличается для поискового виджета и для блоков рекомендаций <sb-widget>, но формат данных общий:
type Cart = Record<string, number>; // { "110166": 2 } — id из фида → количествоtype Favourites = Record<string, boolean>; // { "110166": true }Хуки передаются в настройках виджета в offer.cart и offer.favourites. Это функции, поэтому их задают в своём коде инициализации, а не в JSON личного кабинета.
window.searchbooster({ apiKey: 'PROJECT_UUID', offer: { cart: { // что сейчас в корзине сайта items: async () => { const cart = await fetch('/api/cart').then((r) => r.json()); return Object.fromEntries(cart.items.map((i) => [i.productId, i.quantity])); }, // покупатель изменил количество; верните новое количество onChangeOfferCount: async ({ operationType, currentQuantity, ...offer }) => { const next = { add: 1, inc: currentQuantity + 1, dec: Math.max(currentQuantity - 1, 0), removeAll: 0 }[operationType]; try { await fetch('/api/cart', { method: 'POST', body: JSON.stringify({ id: offer.id, quantity: next }) }); return next; } catch { return currentQuantity; } }, // клик «В корзине» — перейти в корзину onGoToCart: () => (location.href = '/cart'), // своя кнопка, например для товаров не в наличии addToCartConfig: async (offer) => offer.available ? undefined : { label: 'Подробнее', action: () => (location.href = offer.url) }, }, favourites: { items: async () => ({ '110166': true }), onChange: async ({ isFavourite, ...offer }) => { await fetch('/api/favourites', { method: isFavourite ? 'PUT' : 'DELETE', body: JSON.stringify({ id: offer.id }) }); return isFavourite; }, }, }, cartCount: { offer: { count: true }, completions: { count: true } }, // счётчик «− N +» вместо кнопки initialized(sb) { sb.mount({ widget: 'search-popup', selector: '#search-input' }); },});operationType |
Когда |
|---|---|
add |
Первый клик «В корзину» |
inc / dec |
Плюс / минус в счётчике |
removeAll |
Удаление |
Сравнение — offer.compare с теми же items и onChange({ isCompare, ...offer }).
Есть два способа.
1. Скрипты в личном кабинете — Виджеты → Общие настройки: тело функции, которое возвращает корзину, избранное и сравнение. Например:
// «Корзина»return Object.fromEntries(window.myShop.cart.items.map((i) => [i.id, i.qty]));2. Функции на сайте — определите их до загрузки скрипта виджетов, они важнее скриптов из кабинета:
window.sbEvents = window.sbEvents || {};window.sbEvents.getCart = async () => ({ '110166': 1 });window.sbEvents.getFavourites = async () => ({ '99839': true });window.sbEvents.getCompare = async () => ({});Клик «В корзину» в блоке выполняет JS-код события «Добавление в корзину» из настроек виджета в личном кабинете; в коде доступна переменная payload — товар из фида:
// поле события «Добавление в корзину» в настройках виджетаwindow.myShop.cart.add(payload.id, 1);Событие add_to_cart для аналитики виджет отправляет сам.
Корзина изменилась вне виджета
Заголовок раздела «Корзина изменилась вне виджета»Покупатель добавил товар на странице сайта — сообщите всем виджетам SearchBooster, чтобы обновились счётчики и кнопки:
// частично: только изменённые товары, включая удалённые (0 / false)window.sbEvents?.pushEvent('UPDATE_CART', { '110166': 2, '99839': 0 });window.sbEvents?.pushEvent('UPDATE_FAVOURITES', { '110166': true });
// полностью: поисковый виджет заново вызовет offer.cart.items()window.sbEvents?.pushEvent('UPDATE_CART');Также поддерживается UPDATE_COMPARE. Если корзина меняется так, что сайт не может сообщить об этом, включите в поисковом виджете периодическое перечитывание: offer.cart.usePollingRate: true и offer.cart.pollingRate (мс).
Покупку отправляйте как purchase в dataLayer (трекер) или в API событий — так она попадёт в статистику выручки поиска и рекомендаций.