Development of a product comparison module for 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
    1175
  • 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

Development of Product Comparison Module for 1C-Bitrix

The standard Bitrix distribution includes the bitrix:catalog.compare component and built-in session-based comparison cart. On simple projects this suffices. But as soon as requirements appear — store list between sessions, compare products from different categories, highlight differing characteristics, export table — the standard component hits its ceiling. A custom module solves these tasks without workarounds.

How Built-in Comparison Works and Where It Breaks

The built-in mechanism stores the list in $_SESSION['CATALOG_COMPARE'] and in the catalog_compare_items cookie. When adding a product, the component's AJAX method writes to the session. Problems:

  • Session lives until browser closes or timeout — user returns the next day and the list is empty.
  • No category separation — you can add a TV and boots to comparison, and the component tries to compare them.
  • Characteristics are displayed without highlighting differences.
  • No support for authenticated users: one person on two devices — two different lists.

Module Architecture

The module registers in the system via local/modules/vendor.compare/ with standard include.php and install/index.php. List storage:

Table b_compare_list:

Field Type Purpose
ID int auto_increment Primary key
USER_ID int Authenticated user ID, NULL for guests
SESSION_ID varchar(64) Session hash for guests
CREATED_AT datetime Creation date
UPDATED_AT datetime Last modification date

Table b_compare_item:

Field Type Purpose
ID int auto_increment
LIST_ID int FK to b_compare_list
PRODUCT_ID int Product offer ID
SECTION_ID int Catalog section ID
ADDED_AT datetime When added

ORM classes inherit from \Bitrix\Main\ORM\Data\DataManager. Limit on number of products in one list is set via module settings (table b_option, module namespace).

Merge Logic on Login

When a guest logs in, their anonymous list needs to be merged with permanent:

public static function mergeOnLogin(int $userId, string $sessionId): void
{
    $guestList = CompareListTable::getRow([
        'filter' => ['=SESSION_ID' => $sessionId, '=USER_ID' => false],
    ]);

    if (!$guestList) {
        return;
    }

    $userList = CompareListTable::getOrCreate($userId);

    $guestItems = CompareItemTable::getList([
        'filter' => ['=LIST_ID' => $guestList['ID']],
    ]);

    foreach ($guestItems as $item) {
        CompareItemTable::addIfNotExists($userList['ID'], $item['PRODUCT_ID']);
    }

    CompareListTable::delete($guestList['ID']);
}

The OnAfterUserLogin event from the main module is the place to call this method.

Highlighting Differing Characteristics

This is what the customer expects from comparison: rows where products differ should be visually highlighted. Algorithm:

  1. Get properties of all products in comparison via CIBlockElement::GetList() with SELECT = ['PROPERTY_*'].
  2. Build a matrix: key — property code, value — array of values for each product.
  3. For each matrix row check count(array_unique($values)) > 1 — if more than one unique value, mark as "different".
  4. On frontend, add CSS class compare-row--diff to rows with differences.

Additionally filter rows where all values are empty — they don't need to be shown.

Frontend: AJAX and State

The "Add to Comparison" button on the product card sends POST to the component via bitrix:main.ajax. Icon state (added / not added) is synchronized via localStorage on page load and updated after each AJAX response.

Product count in comparison is displayed in header via separate component, which reads count from session or module API without loading full data.

Exporting Comparison Table

Large projects request export to PDF or Excel. For PDF use mPDF or TCPDF (connected as dependency via composer in local/). For Excel — PhpSpreadsheet. The comparison table is formed from the same property matrix and rendered to file on user request.

Development Timeline

Scale Content Duration
Basic DB storage, AJAX add/remove, comparison table 4–6 days
Standard + Merge on login, highlight differences, header counter 8–10 days
Extended + PDF/Excel export, cross-category comparison, module settings in admin 12–16 days