Розробка блоку "схожі товари" 1С-Бітрікс
«Схожі товари» — блок для тих випадків, коли поточний товар не підходить покупцеві: інший колір, інший розмір, інший виробник. Або немає в наявності. Задача блоку — утримати користувача в каталозі і запропонувати альтернативу, а не відпустити його на інший сайт.
Критерії схожості
«Схожий» — поняття, яке потрібно визначити для кожного проекту. Можливі критерії:
- Та сама категорія — базовий рівень.
- Ті самі характеристики — для технічних товарів (електроніка, будматеріали): потужність, матеріал, тип.
- Близька ціна — покупець із бюджетом рідко переходить в іншу цінову категорію.
- Той самий бренд — працює для брендозалежних покупок (косметика, одяг).
- Схожі теги — якщо в каталозі є тегова структура.
Система схожості будується як зважена сума збігів за обраними критеріями.
Алгоритм розрахунку схожості
function calculateSimilarityScore(int $productId, int $candidateId): float {
$product = getProductData($productId);
$candidate = getProductData($candidateId);
$score = 0.0;
// Та сама категорія (+30 очок)
if ($candidate['IBLOCK_SECTION_ID'] === $product['IBLOCK_SECTION_ID']) {
$score += 30;
}
// Близька ціна (±20% → +20 очок, ±40% → +10 очок)
$priceDiff = abs($candidate['PRICE'] - $product['PRICE']) / max($product['PRICE'], 1);
if ($priceDiff <= 0.2) $score += 20;
elseif ($priceDiff <= 0.4) $score += 10;
// Збіг бренду (+25 очок)
if ($candidate['PROP_BRAND'] && $candidate['PROP_BRAND'] === $product['PROP_BRAND']) {
$score += 25;
}
// Збіги за характеристиками (до +25 очок)
$specKeys = ['PROP_MATERIAL', 'PROP_COLOR', 'PROP_SIZE_TYPE'];
$specScore = 0;
foreach ($specKeys as $key) {
if (isset($product[$key], $candidate[$key]) && $product[$key] === $candidate[$key]) {
$specScore += 8;
}
}
$score += min($specScore, 25);
return $score;
}
Попередній розрахунок для каталогів із тисячами товарів
Розраховувати схожість «на льоту» для каталогу в 10 000+ товарів неможливо. Попередній розрахунок:
CREATE TABLE custom_similar_products (
product_id INT NOT NULL,
similar_id INT NOT NULL,
score FLOAT NOT NULL,
calculated_at DATETIME DEFAULT NOW(),
PRIMARY KEY (product_id, similar_id),
INDEX idx_product (product_id, score DESC)
);
Агент рахує схожість усередині кожної категорії:
function RecalcSimilarProductsAgent(): string {
static $sectionOffset = 0;
$sections = getSectionsBatch($sectionOffset, 10);
if (empty($sections)) {
$sectionOffset = 0; // почати спочатку при наступному запуску
return 'RecalcSimilarProductsAgent();';
}
foreach ($sections as $section) {
$products = getProductsBySection($section['ID']);
foreach ($products as $p) {
$scores = [];
foreach ($products as $candidate) {
if ($candidate['ID'] === $p['ID']) continue;
$scores[$candidate['ID']] = calculateSimilarityScore($p['ID'], $candidate['ID']);
}
arsort($scores);
$top = array_slice($scores, 0, 20, true);
saveSimilarProducts($p['ID'], $top);
}
}
$sectionOffset += 10;
return 'RecalcSimilarProductsAgent();';
}
Агент запускається кожної ночі; обробляє по 10 розділів за запуск.
Компонент з урахуванням наявності
Перед відображенням відфільтровуємо товари без залишку:
$similarIds = getSimilarFromTable($productId, 20); // запас з урахуванням фільтрації
$filter = [
'ID' => $similarIds,
'ACTIVE' => 'Y',
'!ID' => $productId,
];
// Якщо в налаштуваннях: показувати лише товари в наявності
if ($arParams['ONLY_AVAILABLE'] === 'Y') {
$filter['>CATALOG_QUANTITY'] = 0;
}
$res = \CIBlockElement::GetList(
[],
$filter,
false,
['nPageSize' => (int)$arParams['LIMIT']],
['ID', 'NAME', 'DETAIL_PAGE_URL', 'PREVIEW_PICTURE', 'CATALOG_PRICE_1']
);
Ручне управління схожістю
Для випадків, коли алгоритм не справляється (специфічні товари, нестандартні зв'язки) — додаємо інструмент ручного управління в адміністративній частині. Менеджер відкриває товар → вкладка «Схожі товари» → мультивибір із каталогу. Ручні зв'язки мають пріоритет над автоматичними.
-- Ручні зв'язки зберігаються окремо, не перезаписуються агентом
CREATE TABLE custom_similar_manual (
product_id INT NOT NULL,
similar_id INT NOT NULL,
sort INT DEFAULT 500,
created_by INT,
created_at DATETIME DEFAULT NOW(),
PRIMARY KEY (product_id, similar_id)
);
Логіка відображення
Підсумкова вибірка для блоку: спочатку ручні зв'язки (у порядку sort), потім автоматичні за score. Якщо загалом менше потрібної кількості — fallback до товарів тієї самої категорії.
Різниця з «З цим товаром купують»
| Критерій | Схожі товари | З цим купують |
|---|---|---|
| Основа | Властивості товару | Історія замовлень |
| Нові товари | Працює одразу | Потрібна історія покупок |
| Логіка | Альтернатива | Доповнення |
| Місце на сайті | Картка товару | Картка товару, кошик |
| Впливає на | Утримання користувача | Середній чек |
Терміни
| Етап | Термін |
|---|---|
| Визначення критеріїв схожості для каталогу | 1 день |
| Алгоритм розрахунку score + таблиця | 2–3 дні |
| Агент попереднього розрахунку | 1–2 дні |
| Компонент із фільтрацією та fallback | 2–3 дні |
| Ручне управління в адмінці | 1–2 дні |
| Тестування | 1–2 дні |
Разом: 1–1.5 тижні.







