Configuration of Dynamic Pricing in 1C-Bitrix
Dynamic pricing is when price changes automatically per rules: depending on demand, inventory, competitors, time of day or user behavior. Unlike discounts and promotions, here price in b_catalog_price can change multiple times per day. Implementation requires understanding how Bitrix applies prices and clear rule architecture.
How Bitrix calculates final price
Calculation chain: base price (b_catalog_price) → catalog discounts (b_catalog_discount) → cart rules (b_sale_discount) → total. Dynamic pricing works at first level — changes base price, or intercepts via OnGetOptimalPrice event and returns different value.
Second option (via event) is preferable: doesn't pollute price history in b_catalog_price, doesn't affect price indexing, easier to rollback.
Dynamic pricing rules
Rules stored in custom table bl_dynamic_pricing_rules:
| Field | Description |
|---|---|
rule_type |
stock / demand / competitor / time |
iblock_id |
infoblox or NULL (all) |
product_id |
specific product or NULL (all in section) |
condition_json |
condition parameters (stock, hour, coefficient) |
price_modifier |
coefficient (1.15 = +15%, 0.9 = -10%) |
priority |
application order on conflict |
active |
enabled/disabled |
Event handler
AddEventHandler('catalog', 'OnGetOptimalPrice', function(&$fields) {
$productId = $fields['PRODUCT_ID'];
$basePrice = $fields['PRICE']['PRICE'] ?? null;
if (!$basePrice) return;
$modifier = DynamicPricingEngine::getModifier($productId);
if ($modifier && $modifier != 1.0) {
$fields['PRICE']['PRICE'] = round($basePrice * $modifier, 2);
$fields['PRICE']['BASE_PRICE'] = $basePrice; // original for discount display
}
});
DynamicPricingEngine::getModifier() loads applicable rules from cache (\Bitrix\Main\Data\Cache, TTL 300 sec) and calculates result coefficient. With multiple rules — multiply or take minimum/maximum depending on business logic.
Stock-based rule
If product stock falls below threshold — raise price (encourage early purchase or limit rush). Get inventory from b_catalog_store_product via \Bitrix\Catalog\StoreProductTable:
$stock = \Bitrix\Catalog\StoreProductTable::getList([
'filter' => ['PRODUCT_ID' => $productId],
'select' => ['AMOUNT'],
'runtime' => [new \Bitrix\Main\ORM\Fields\ExpressionField('TOTAL', 'SUM(%s)', 'AMOUNT')],
])->fetch()['TOTAL'] ?? 0;
if ($stock < 5) return 1.2; // +20% at stock < 5 units
if ($stock < 20) return 1.1; // +10% at stock < 20 units
return 1.0;
Caching and performance
Event OnGetOptimalPrice is called on every price render — in catalog, on detail page, in cart. Without cache one catalog page with 48 products makes 48 DB calls. Cache modifier by PRODUCT_ID with TTL 5 minutes. When inventory or rules change — clear cache by tag dynamic_price_{productId}.
What to configure
-
bl_dynamic_pricing_rulestable with rule set -
DynamicPricingEngineclass with caching and rule application logic -
OnGetOptimalPriceevent handler ininit.phpor module - Admin interface for rule management
- Price change logging in
bl_dynamic_pricing_logfor audit







