Рекомендації товарів за історією покупок у 1С-Бітрікс

Ми впроваджуємо персоналізовані рекомендації на основі історії покупок у 1С-Бітрікс. Типова конверсія в повторні продажі — менше 5%. Після впровадження нашого підходу показник зростає до 20–30%. При цьому не потрібно підключати зовнішні ML-сервіси — вся логіка реалізується на SQL та PHP силами самог
Послуги, які ми пропонуємо
Показано 1 з 1Усі 1626 послуг
Рекомендації товарів за історією покупок у 1С-Бітрікс
Простий
~1 день

Наші компетенції:

Часті запитання

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1460
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Розробка веб-сайту для компанії ФІКСПЕР
    1019
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Розробка на базі Бітрікс, Бітрікс24, 1С для компанії Development of an Online
    761
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Розробка на базі 1С Підприємство для компанії МИРСАНБЕЛ
    882
  • image_crm_dolbimby_434_0.webp
    Розробка сайту на CRM Бітрікс24 для компанії DOLBIMBY
    809
  • image_crm_technotorgcomplex_453_0.webp
    Розробка на базі Бітрікс24 для компанії ТЕХНОТОРГКОМПЛЕКС
    1163

Ми впроваджуємо персоналізовані рекомендації на основі історії покупок у 1С-Бітрікс. Типова конверсія в повторні продажі — менше 5%. Після впровадження нашого підходу показник зростає до 20–30%. При цьому не потрібно підключати зовнішні ML-сервіси — вся логіка реалізується на SQL та PHP силами самого Бітрікс, що дає повний контроль і знижує витрати на зовнішні підписки.

Більшість рекомендацій — item-based («з цим товаром часто купують») та user-based («ваші минулі покупки схожі на покупки інших»). Обидва патерни використовують стандартні таблиці Бітрікс та оптимізуються індексами. Без правильного індексування JOIN на таблиці b_sale_order_basket у магазині з 500 000 замовлень виконується 30+ секунд; зі складеним індексом (PRODUCT_ID, ORDER_ID) запит вкладається в 0,1 секунди. Внутрішня реалізація окупається протягом кількох місяців завдяки відсутності щомісячної плати за ML-сервіси та зниженню навантаження на сервер.

Два основних патерни рекомендацій

Item-based: «з цим товаром часто купують». Аналізуємо спільну зустріваність товарів у замовленнях. User-based: «ваші минулі покупки схожі на покупки користувачів X, вони взяли ще Y». Обидва патерни будуються на даних зі стандартних таблиць Бітрікс.

Таблиці з даними про покупки

Вся історія замовлень у Бітрікс — три ключові таблиці:

  • b_sale_order — замовлення: поля USER_ID, CANCELED, STATUS_ID, PRICE
  • b_sale_order_basket — склад замовлень: ORDER_ID, PRODUCT_ID, QUANTITY, PRICE
  • b_catalog_product — наявність товару: QUANTITY, AVAILABLE

Для рекомендацій використовуємо лише нескасовані замовлення (CANCELED = 'N') у фінальних статусах. Статус F (Finished) — стандартний фінальний, але на багатьох проєктах використовуються кастомні статуси.

Item-based: «з цим часто купують»

Основний патерн — блок «Разом із цим товаром купують» на картці товару:

SELECT ob2.PRODUCT_ID, COUNT(DISTINCT ob1.ORDER_ID) AS co_purchase_count, SUM(ob2.QUANTITY) AS total_qty FROM b_sale_order_basket ob1 JOIN b_sale_order_basket ob2 ON ob1.ORDER_ID = ob2.ORDER_ID AND ob2.PRODUCT_ID != ob1.PRODUCT_ID JOIN b_sale_order o ON o.ID = ob1.ORDER_ID AND o.CANCELED = 'N' AND o.DATE_INSERT > NOW() - INTERVAL '90 days' WHERE ob1.PRODUCT_ID = :target_product_id GROUP BY ob2.PRODUCT_ID ORDER BY co_purchase_count DESC LIMIT 20; 

Цей запит виконується офлайн через агент Бітрікс — раз на 4 години. Результат пишеться в таблицю:

CREATE TABLE b_product_cross_sell ( SOURCE_ID INT NOT NULL, RECOMMENDED_ID INT NOT NULL, SCORE INT NOT NULL, UPDATED_AT TIMESTAMP DEFAULT NOW(), PRIMARY KEY (SOURCE_ID, RECOMMENDED_ID) ); CREATE INDEX idx_cross_sell_source ON b_product_cross_sell(SOURCE_ID, SCORE DESC); 

Індекс (PRODUCT_ID, ORDER_ID) на b_sale_order_basket критично важливий — без нього JOIN на великих магазинах (100k+ замовлень) виконуватиметься секундами.

User-based: персональні рекомендації для авторизованого користувача

Для конкретного користувача будується список товарів, які купили «схожі» покупці. «Схожість» — перетин історії покупок.

function getUserBasedRecs(int $userId, int $limit = 8): array { // 1. Історія покупок поточного користувача $myOrderIds = array_column( \Bitrix\Sale\OrderTable::getList([ 'filter' => ['USER_ID' => $userId, 'CANCELED' => 'N'], 'select' => ['ID'], ])->fetchAll(), 'ID' ); if (empty($myOrderIds)) return getPopularItems($limit); $myProductIds = array_column( \Bitrix\Sale\Internals\BasketTable::getList([ 'filter' => ['ORDER_ID' => $myOrderIds], 'select' => ['PRODUCT_ID'], ])->fetchAll(), 'PRODUCT_ID' ); // 2. Користувачі, які купили ті ж товари // 3. Товари цих користувачів, яких у нас немає $res = $GLOBALS['DB']->Query(" SELECT ob2.PRODUCT_ID, COUNT(DISTINCT o2.USER_ID) AS score FROM b_sale_order_basket ob1 JOIN b_sale_order o1 ON o1.ID = ob1.ORDER_ID AND o1.USER_ID = {$userId} JOIN b_sale_order_basket ob2 ON ob2.ORDER_ID IN ( SELECT DISTINCT o3.ID FROM b_sale_order o3 JOIN b_sale_order_basket ob3 ON ob3.ORDER_ID = o3.ID AND ob3.PRODUCT_ID IN (" . implode(',', array_map('intval', $myProductIds)) . ") WHERE o3.USER_ID != {$userId} AND o3.CANCELED = 'N' ) WHERE ob2.PRODUCT_ID NOT IN (" . implode(',', array_map('intval', $myProductIds)) . ") GROUP BY ob2.PRODUCT_ID ORDER BY score DESC LIMIT {$limit} "); $ids = []; while ($row = $res->Fetch()) $ids[] = (int)$row['PRODUCT_ID']; return $ids; } 

Фільтрація рекомендованих товарів

Рекомендовані ID передаються у фінальний фільтр перед відображенням — прибрати неактивні, зняті з продажу, з нульовим залишком:

$availableIds = \CIBlockElement::GetList( ['SORT' => 'ASC'], [ 'ID' => $recommendedIds, 'ACTIVE' => 'Y', 'IBLOCK_ID' => CATALOG_IBLOCK_ID, '>CATALOG_QUANTITY' => 0, ], false, ['nTopCount' => 8], ['ID'] )->fetchAll(); 

Кеш та інвалідація

Кеш item-based рекомендацій: по PRODUCT_ID, TTL = 4 години (синхронно з агентом оновлення). Кеш user-based: по USER_ID, TTL = 30 хвилин — коротше, тому що історія користувача змінюється. Інвалідація: при збереженні нового замовлення (OnSaleOrderSaved) скидати кеш для всіх товарів із замовлення через тег product_recs_{id}.

Переваги внутрішньої реалізації перед зовнішніми ML-сервісами

Готові сервіси (Recombee, Nosto) вимагають щомісячної оплати та інтеграції REST API. Внутрішня реалізація на Бітрікс:

  • не потребує зовнішніх залежностей,
  • працює швидше, оскільки дані вже в БД,
  • дає повний контроль над алгоритмом,
  • легко модифікується під специфіку каталогу.
Параметр Item-based User-based
Принцип «з цим товаром часто беруть» «люди зі схожою історією купили»
Дані Спільні покупки в замовленнях Перетин користувацьких кошиків
Оновлення Раз на 4 години агент Онлайн при запиті (кеш 30 хв)
Коли ефективний Товар має пов'язані позиції У користувача є історія покупок

Типові проблеми з продуктивністю та їх вирішення

Проблема Причина Рішення
JOIN виконується хвилинами Відсутній індекс (PRODUCT_ID, ORDER_ID) на b_sale_order_basket Створити складений індекс
Кеш застаріває некоректно Немає інвалідації за подією Додати обробник OnSaleOrderSaved із тегованим очищенням
User-based повільний для нових користувачів Відсутність історії Використовувати item-based або популярні товари як fallback

Чому індекс (PRODUCT_ID, ORDER_ID) критичний?

Без цього складеного індексу JOIN по b_sale_order_basket у магазині з 100 000 замовлень виконується 10–30 секунд. Програмні рішення на кшталт тимчасових таблиць не економлять ресурси. Індекс скорочує час до 0,05–0,1 секунди, що критично для агента, який виконується раз на 4 години.

Як забезпечується актуальність рекомендацій?

Item-based перераховуються раз на 4 години, user-based — при кожному запиті з кешем на 30 хвилин. Додатково при створенні нового замовлення скидається кеш для задіяних товарів. Це гарантує, що користувач бачить свіжі рекомендації, а навантаження на сервер залишається низьким.

Що входить у нашу роботу

  • Аудит поточної структури даних та навантажень на БД.
  • Реалізація агентів розрахунку item-based та user-based.
  • Створення таблиці b_product_cross_sell та необхідних індексів.
  • Інтеграція фільтрації за активністю та залишками.
  • Налаштування тегованого кешування та інвалідації за подіями.
  • Документація з архітектури та інструкція з деплою.
  • Навчання вашого розробника підтримці.

Терміни та вартість

Термін реалізації — від 3 до 7 робочих днів залежно від складності каталогу та обсягу даних. Точна вартість розраховується після аудиту — замовте аудит, і ми оцінимо проєкт безкоштовно.

Спираючись на досвід десятка впроваджень у магазинах з товарообігом від 50 млн грн, гарантуємо стабільну роботу без просадок продуктивності. Зв'яжіться з нами — проведемо аудит вашого каталогу та розрахуємо точну вартість. Отримайте персоналізовані рекомендації вже сьогодні.