Development of the "Similar Products" block in 1C-Bitrix

Our company is engaged in the development, support and maintenance of Bitrix and Bitrix24 solutions of any complexity. From simple one-page sites to complex online stores, CRM systems with 1C and telephony integration. The experience of developers is confirmed by certificates from the vendor.
Our competencies:
Development stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1177
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Development based on Bitrix, Bitrix24, 1C for the company Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    747
  • image_crm_dolbimby_434_0.webp
    Website development on CRM Bitrix24 for DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    976

"Similar Products" Block Development for 1C-Bitrix

"Similar products" is a block for cases when the current product doesn't suit the buyer: different color, different size, different manufacturer. Or out of stock. The block's purpose is to keep the user in the catalog and offer an alternative, rather than sending them to a competitor's site.

Similarity Criteria

"Similar" is a concept that needs to be defined for each project. Possible criteria:

  • Same category — the basic level.
  • Same characteristics — for technical products (electronics, building materials): power, material, type.
  • Similar price — a buyer with a budget rarely moves to a different price tier.
  • Same brand — works for brand-dependent purchases (cosmetics, clothing).
  • Similar tags — if the catalog has a tag structure.

The similarity system is built as a weighted sum of matches across the chosen criteria.

Similarity Score Algorithm

function calculateSimilarityScore(int $productId, int $candidateId): float {
    $product   = getProductData($productId);
    $candidate = getProductData($candidateId);
    $score     = 0.0;

    // Same category (+30 points)
    if ($candidate['IBLOCK_SECTION_ID'] === $product['IBLOCK_SECTION_ID']) {
        $score += 30;
    }

    // Similar price (±20% → +20 points, ±40% → +10 points)
    $priceDiff = abs($candidate['PRICE'] - $product['PRICE']) / max($product['PRICE'], 1);
    if ($priceDiff <= 0.2) $score += 20;
    elseif ($priceDiff <= 0.4) $score += 10;

    // Brand match (+25 points)
    if ($candidate['PROP_BRAND'] && $candidate['PROP_BRAND'] === $product['PROP_BRAND']) {
        $score += 25;
    }

    // Characteristic matches (up to +25 points)
    $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;
}

Pre-Calculation for Catalogs with Thousands of Products

Calculating similarity on the fly for a catalog of 10,000+ products is not feasible. Pre-calculation:

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)
);

The agent calculates similarity within each category:

function RecalcSimilarProductsAgent(): string {
    static $sectionOffset = 0;
    $sections = getSectionsBatch($sectionOffset, 10);

    if (empty($sections)) {
        $sectionOffset = 0; // start over on next run
        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();';
}

The agent runs every night and processes 10 sections per run.

Component with Stock Awareness

Before displaying, filter out products with no stock:

$similarIds = getSimilarFromTable($productId, 20); // extra margin for filtering

$filter = [
    'ID'             => $similarIds,
    'ACTIVE'         => 'Y',
    '!ID'            => $productId,
];

// If configured: show only in-stock products
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']
);

Manual Similarity Management

For cases where the algorithm falls short (specific products, non-standard relationships) — add a manual management tool in the admin area. A manager opens a product → "Similar products" tab → multi-select from the catalog. Manual links take priority over automatic ones.

-- Manual links stored separately, not overwritten by the agent
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)
);

Display Logic

Final selection for the block: first manual links (ordered by sort), then automatic ones by score. If the combined total is less than required — fallback to products from the same category.

Difference from "Frequently Bought Together"

Criterion Similar products Bought together
Basis Product properties Order history
New products Works immediately Requires purchase history
Logic Alternative Complement
Location on site Product page Product page, cart
Impact on User retention Average order value

Timeline

Stage Timeline
Defining similarity criteria for the catalog 1 day
Score calculation algorithm + table 2–3 days
Pre-calculation agent 1–2 days
Component with filtering and fallback 2–3 days
Manual management in admin panel 1–2 days
Testing 1–2 days

Total: 1–1.5 weeks.