Configuration Calculator on 1C-Bitrix Development

When launching an auto parts online store, we faced a problem: the standard 1C-Bitrix catalog did not allow the customer to assemble an engine from individual modules with compatibility verification. Each module had its own options, and combinations were interdependent. Customers got confused in com

Our competencies:

Frequently Asked Questions

When launching an auto parts online store, we faced a problem: the standard 1C-Bitrix catalog did not allow the customer to assemble an engine from individual modules with compatibility verification. Each module had its own options, and combinations were interdependent. Customers got confused in compatibility tables, and managers spent hours on manual selection. The solution—a configuration calculator on Bitrix with a dependency graph. The user selects options, the system checks compatibility in real time, shows the price, and adds the assembled set to the cart.

We, a team of certified developers with 10 years of experience, implement such configurators. Our approach guarantees reliable operation even with 50+ options. Relevant for auto dealers, furniture manufacturers, IT integrators, and industrial equipment suppliers. Order development—we will assess the project for free.

What is the difference from standard trade offers?

The standard catalog uses trade offers (SKUs) with fixed attribute combinations. Our configurator performs dynamic assembly: selecting the "Lux" package includes options A, B, C and blocks D. The final price is summed from components, not taken from an SKU. The result is a set of products for the cart. Thanks to the dependency graph, the configurator works 2 times faster than standard solutions.

How is the data model structured?

We use the HL-block ConfiguratorComponents to store options:

Field Type Description
UF_PRODUCT_ID Int ID of the base product in the catalog
UF_GROUP_CODE String Option group (engine, color, wheels)
UF_OPTION_CODE String Option code
UF_OPTION_NAME String Display name
UF_BASE_PRICE Float Option price
UF_PRICE_TYPE Enum fixed / percent / delta
UF_INCOMPATIBLE String Codes of incompatible options (comma-separated)
UF_REQUIRED_WITH String Options required when this one is selected

HL-block ConfiguratorPresets—ready-made configurations (Basic, Standard, Lux):

Field Type Description
UF_PRODUCT_ID Int Base product
UF_PRESET_CODE String Preset code
UF_PRESET_NAME String Name
UF_OPTIONS_JSON Text JSON with selected options
UF_DISCOUNT_PERCENT Float Discount on the preset

Why is the dependency graph critical for performance?

With 50+ options, manual testing is impossible. The dependency graph allows instant determination of incompatibilities and required options. Each selection triggers a price recalculation and blocking of non-applicable variants. We build the graph on the JS side to offload the server. As a result, the user sees updates without delays. 1C-Bitrix documentation recommends this approach for complex configurators.

How to manage option dependencies?

The central problem of the configurator is synchronizing dependencies. When an option is selected, we need to: remove incompatible options from other groups, automatically add required related ones, and recalculate the total price.

class ProductConfigurator { constructor(basePrice, components) { this.basePrice = basePrice; this.components = components; this.selected = {}; this.graph = this.buildIncompatibilityGraph(); } buildIncompatibilityGraph() { const graph = {}; this.components.forEach(c => { if (c.uf_incompatible) { graph[c.uf_option_code] = c.uf_incompatible.split(',').map(s => s.trim()); } }); return graph; } selectOption(groupCode, optionCode) { const blocked = this.graph[optionCode] || []; Object.keys(this.selected).forEach(g => { if (blocked.includes(this.selected[g])) delete this.selected[g]; }); this.selected[groupCode] = optionCode; const c = this.components.find( x => x.uf_group_code === groupCode && x.uf_option_code === optionCode ); if (c && c.uf_required_with) { c.uf_required_with.split(',').forEach(code => { const req = this.components.find(x => x.uf_option_code === code.trim()); if (req) this.selected[req.uf_group_code] = req.uf_option_code; }); } return this.calculate(); } calculate() { let total = this.basePrice; const breakdown = []; Object.entries(this.selected).forEach(([group, code]) => { const c = this.components.find( x => x.uf_group_code === group && x.uf_option_code === code ); if (!c) return; let price = 0; if (c.uf_price_type === 'fixed') price = c.uf_base_price; if (c.uf_price_type === 'percent') price = this.basePrice * c.uf_base_price / 100; if (c.uf_price_type === 'delta') price = c.uf_base_price; total += price; breakdown.push({ group, name: c.uf_option_name, price }); }); return { basePrice: this.basePrice, totalPrice: Math.round(total), breakdown }; } } 

Presets as an entry point

Most users do not configure from scratch. Ready-made presets serve as a starting point with the possibility of fine-tuning. A preset with a discount encourages choosing a ready package instead of manual assembly part by part. Budget savings of up to 30%—a tangible bonus.

function applyPreset(configurator, preset) { const options = JSON.parse(preset.uf_options_json); configurator.selected = {}; Object.entries(options).forEach(([group, code]) => { configurator.selected[group] = code; }); const result = configurator.calculate(); if (preset.uf_discount_percent > 0) { result.totalPrice = Math.round(result.totalPrice * (1 - preset.uf_discount_percent / 100)); result.presetDiscount = preset.uf_discount_percent; } return result; } 

How to add the configuration to the Bitrix cart?

public function addToCart(int $baseProductId, array $selectedOptions): \Bitrix\Main\Result { $basket = \Bitrix\Sale\Basket::loadItemsForFUser( \Bitrix\Sale\Fuser::getId(), \Bitrix\Main\Context::getCurrent()->getSite() ); $item = $basket->createItem('catalog', $baseProductId); $item->setFields([ 'QUANTITY' => 1, 'PROPS' => [[ 'NAME' => 'Configuration', 'CODE' => 'CONFIGURATION', 'VALUE' => json_encode($selectedOptions), ]] ]); foreach ($selectedOptions as $option) { if (!empty($option['product_id'])) { $optItem = $basket->createItem('catalog', $option['product_id']); $optItem->setFields([ 'QUANTITY' => 1, 'PRICE' => $option['price'], 'CUSTOM_PRICE' => 'Y', ]); } } return $basket->save(); } 

Saving user configuration

For authorized users, we use the HL-block SavedConfigurations:

$hash = md5($productId . json_encode($selectedOptions)); $existing = $SavedConfig::getList([ 'filter' => ['=UF_USER_ID' => $USER->GetID(), '=UF_HASH' => $hash] ])->fetch(); if (!$existing) { $SavedConfig::add([ 'UF_USER_ID' => $USER->GetID(), 'UF_PRODUCT_ID' => $productId, 'UF_OPTIONS' => json_encode($selectedOptions), 'UF_PRICE' => $totalPrice, 'UF_HASH' => $hash, ]); } 

For guests, we use sessionStorage or cookies with a limited lifetime.

Step-by-step configurator implementation guide

  1. Create HL-blocks for options and presets.
  2. Fill in data—groups, options, their prices and dependencies.
  3. Implement a JS widget on Bitrix Framework (or a separate interface).
  4. Integrate with the cart via the OnBeforeBasketAdd event.
  5. Configure caching for fast operation with many options.

How to ensure configurator scalability?

For 100+ options, we use tagged caching. Calculation results and compatibility are cached by key configurator_{product_id}. When options change, the cache is invalidated via an agent. Queries to HL-blocks are indexed by UF_PRODUCT_ID and UF_GROUP_CODE. This guarantees response time under 100 ms even under peak loads.

What is included in the work?

  • Designing the data model and dependency graph.
  • Developing the frontend widget on Bitrix Framework.
  • Integrating with the cart and orders.
  • Saving configurations for authorized and guest users.
  • API and setup documentation.
  • Training administrators to work with the configurator.
  • 30-day support after release.

Development timelines

Scope Description Timeline
Basic Up to 5 option groups, no dependencies, presets 5–8 days
Standard 5–15 groups, incompatibilities, configuration saving 2–3 weeks
Complex 15+ groups, items in cart, configuration history 4–8 weeks
Production Integration with 1C for up-to-date prices and stock 2–4 months

The main technical challenge is the dependency graph with a large number of options. With 50+ variants, manual testing is unrealistic: automated tests for compatibility logic are needed from day one of development. Our certified specialists guarantee the quality of the result. Learn more about 1C-Bitrix technology and configurators.

Contact us for a detailed audit of your project. We will assess the complexity for free and propose the optimal solution.