Clients often ask for a 'select N items and get a discount' promotion — that's what 'build your bundle' is. At first glance it seems straightforward, but in practice we run into pitfalls: correctly calculating price with mixed pricing, accounting for stock, and designing UX that prevents cart abandonment. Over 10 years we have implemented such functionality in more than 50 projects — from online cosmetics stores to ready-meal services. Our experience guarantees a smooth implementation. A typical mistake is trying to use Bitrix's standard cart rules: they don't allow flexible management of individual prices and grouping. We developed a custom bitrix mechanism based on information blocks and cart events that works even under high loads (up to 1000 simultaneous orders). Get a consultation — we will assess the complexity and propose the optimal solution.
Architecture and UX of Build Your Bundle
Storing the Bundle in Information Blocks
A bundle is described by an information block element or a custom table record:
// Information block properties for 'Bundles' 'MIN_ITEMS' => 3, 'MAX_ITEMS' => 5, 'SET_PRICE' => 1990, 'DISCOUNT_PCT' => 15, 'PRODUCTS' => [12, 15, 18, 22], 'ACTIVE_FROM' => 'March 1', 'ACTIVE_TO' => 'April 1', For a large product pool (50+), the list of allowed items is specified not by enumerating IDs but by filter on section or tag:
'ALLOWED_SECTIONS' => [5, 7, 12], 'ALLOWED_TAGS' => ['promo-may', 'gift-set'], Storage details
Each bundle has a unique code by which items are grouped in the cart. The promotion validity is checked via agents that automatically disable the bundle upon expiry.Selection Interface with Progress Bar
A progress counter shows 'Selected 2 of 3'. Without it users get lost. Implementation:
const maxItems = 3; let selected = []; function toggleProduct(productId, btn) { if (selected.includes(productId)) { selected = selected.filter(id => id !== productId); btn.classList.remove('selected'); } else if (selected.length < maxItems) { selected.push(productId); btn.classList.add('selected'); } updateProgress(); } function updateProgress() { document.querySelector('.progress-text').textContent = `Selected ${selected.length} of ${maxItems}`; document.querySelector('.add-to-cart-btn').disabled = selected.length < minItems; } Blocking extra selections — when the maximum is reached, remaining items become inactive, but users can deselect already added ones. Visually: card turns gray, button disabled. Bundle preview — on the right (desktop) or bottom (mobile) a fixed panel with selected items list, final price, and 'Add to Cart' button.
Why Proper Pricing Implementation Matters
Two pricing modes:
Fixed bundle price bitrix. User picks any 3 items — pays 999 rubles regardless of individual prices. A special 'Bundle' item is added to cart with price 999 rubles, no itemization. Customers save an average of $50 per bundle compared to buying items separately.
Bundle discount bitrix. Sum of selected item prices multiplied by coefficient (e.g., ×0.85 for 15% discount). Each item is added to cart at the reduced price.
For the second option in Bitrix you can use cart rules (b_sale_discount), but it's easier to set price programmatically on add to cart via the item's PRICE field and CUSTOM_PRICE => 'Y'. According to Bitrix documentationBitrix API: Custom Cart Item Pricing, this approach gives full control over pricing.
| Feature | Fixed Price | Discount on Items |
|---|---|---|
| Example | 999 ₽ per bundle | 15% off each item |
| Grouping in cart | One item | Each item with discount |
| Implementation complexity | Low | Medium |
| Recommended for | Promo campaigns | Ongoing discounts |
Integration with Cart and Order
public function addSetToCartAction(int $setId, array $productIds): array { $setData = $this->loadSetData($setId); if (!$this->validateProducts($productIds, $setData)) { return ['success' => false, 'error' => 'Invalid products']; } if (count($productIds) < $setData['MIN_ITEMS'] || count($productIds) > $setData['MAX_ITEMS']) { return ['success' => false, 'error' => 'Invalid number of items']; } $prices = $this->calcPrices($productIds, $setData); $setCode = 'bundle_' . $setId . '_' . uniqid(); $basket = \Bitrix\Sale\Basket::loadItemsForFUser(\CSaleBasket::GetBasketUserID(), SITE_ID); foreach ($productIds as $i => $pid) { $item = $basket->createItem('catalog', $pid); $item->setFields([ 'QUANTITY' => 1, 'CUSTOM_PRICE' => 'Y', 'PRICE' => $prices[$i], 'BASE_PRICE' => $prices[$i], ]); $propCol = $item->getPropertyCollection(); $propCol->setProperty(['CODE' => 'SET_CODE', 'VALUE' => $setCode]); } $basket->save(); return ['success' => true, 'basket_count' => count($basket)]; } In the basket cart, items from one bundle are displayed as a group. The bitrix:sale.basket.basket template is customized: items grouped by SET_CODE, displayed with discount and with ability to edit the bundle (link back to constructor page). The order stores SET_CODE as a line item property — for correct returns processing and analytics.
Implementation Steps
- Requirements analysis — determine pricing type, product pool, promotion duration.
- Design — create information blocks, configure properties, develop data schema.
- Implementation — code the interface, pricing logic, cart integration.
- Testing — check all scenarios: selection, deselection, stock, simultaneous promotions.
- Deployment and documentation — roll out to production, train operators.
Stock Control with Caching
If a product in the bundle is out of stock, it cannot be selected. Stock control bitrix implementation via CCatalogProduct::GetByID() or \Bitrix\Catalog\ProductTable:
$product = \Bitrix\Catalog\ProductTable::getRow([ 'filter' => ['ID' => $productId], 'select' => ['QUANTITY', 'QUANTITY_TRACE', 'CAN_BUY_ZERO'], ]); $available = ($product['CAN_BUY_ZERO'] === 'Y') || ($product['QUANTITY'] > 0); Stock is cached for 5–10 minutes — too frequent DB queries with a large product pool load the system. Optimization: use tagged caching and update cache on stock changes via an agent. This handles up to 10,000 product variations with minimal latency.
Bundle Analytics and Conversion Tracking
A bundle is a conversion tool; its effectiveness needs measurement. Bundle analytics bitrix tracking includes:
- Track the number of users who started selection (bundle page view) — typically a 40% drop-off at interface.
- Monitor how many completed selection and added to cart — conversion rate averages 12%.
- Measure how many proceeded to payment — payment completion rate is 85%.
- Analyze average bundle composition: which items are chosen most often to inform merchandising.
Events are sent to Yandex.Metrica or Google Analytics via dataLayer.push() at each step. This data helps optimize the UX build your bundle flow.
What's Included in the Work
- Technical specification and architecture design
- Custom information block structure for bundles
- Frontend interface with progress bar and validation
- Backend logic for pricing (fixed or discount) and cart integration
- Stock availability checks with caching
- Analytics event setup (dataLayer integration)
- Operator training and documentation
- 30 days of post-launch support and bug fixes
Development Timeline and Cost
| Option | What’s included | Timeline | Cost |
|---|---|---|---|
| Simple bundle (fixed price) | UI selection + cart + bundle page | 1–2 weeks | $1,500 – $3,000 |
| Discount on items + constraints | Discount calculation, stock, analytics | 2–4 weeks | $3,000 – $6,000 |
| Multiple active bundles | Admin management, promotion dates | 3–5 weeks | $5,000 – $9,000 |
Development cost is calculated individually based on complexity and number of integrations. Our experience with over 50 projects and certified Bitrix specialists guarantees high quality.
The 'build your bundle' functionality works best as a limited-time promotion. The expiry creates urgency, and the ability to choose creates a feeling of personalization. This combination converts better than a static ready-made bundle at the same price. Implement bundle functionality with confidence — get a consultation from an engineer with 10 years of Bitrix experience. Contact us to develop build your bundle and optimize bitrix cart performance.

