Configuring Regional Pricing in 1C-Bitrix
Regional pricing is one of the most complex topics in the 1C-Bitrix catalog. "Show a price based on the customer's region" sounds straightforward, but in practice several mechanisms intersect: price types, user groups, geographic groups, and trade rules. Here is how it actually works under the hood.
How Regional Pricing Works
In 1C-Bitrix, regional pricing is implemented through a combination of two tools:
Price types (b_catalog_price_type) — the base mechanism. Each price type defines access by user groups. Example types:
-
BASE— standard retail price -
WHOLESALE— wholesale price -
MOSCOW— price for Moscow -
REGIONS— price for other regions
Trade rules (b_sale_discount) — conditional discounts and markups. These define: if the user belongs to the "Moscow" group — apply price type MOSCOW or a discount of X%.
Geographic groups — the sale.regions module (included in the Business edition). Determines the user's location and automatically adds them to the appropriate 1C-Bitrix group.
Step-by-Step Setup
Step 1. Create price types for each region: Trade Catalog → Settings → Price Types. Assign access rights — which user group can see which price type.
Step 2. Fill in prices for each type. Either manually in the product card, via CSV/XML import, or through 1C synchronization with multiple price types.
Step 3. Configure region detection. Options:
- Automatically by IP (the
salemodule + MaxMind GeoIP database) - Via session: the user selects a city from a dropdown
- Via cookie:
$_COOKIE['BITRIX_SM_SALE_LOCATION']
Step 4. Link the region to a user group via a trade rule:
// Programmatically adding a user to a group based on geolocation
$locationCode = \Bitrix\Sale\Location\LocationTable::getLocationCityCode($cityId);
if (in_array($locationCode, ['0000073738', '0c5b2444b22d4d0fa32c11a4401d4c46'])) {
// Moscow and Moscow Oblast — add to group 5
\CUser::SetUserGroup($userId, array_unique(array_merge($currentGroups, [5])));
}
Retrieving the Price in a Query
When fetching products, it is important to pass the correct user group to get the appropriate price type:
$userGroups = \Bitrix\Main\UserTable::getUserGroupIds($userId);
$products = \CCatalogProduct::GetList(
['SORT' => 'ASC'],
['IBLOCK_ID' => CATALOG_IBLOCK_ID, 'ACTIVE' => 'Y'],
false,
false,
['ID', 'NAME', 'CATALOG_PRICE_1', 'CATALOG_PRICE_3'] // Price type IDs
);
// Or via GetPrice with a specified price type
$price = \CCatalogProduct::GetOptimalPrice($productId, 1, $userGroups);
GetOptimalPrice returns the minimum price across all types accessible to the user's groups — this is the key method for regional pricing.
Caching and Performance
Regional pricing increases cache load: the same product listing looks different for different regions. Use tag-based caching with the region identifier included in the cache key:
$regionTag = 'region_' . \Bitrix\Sale\Location\LocationTable::getCurrentRegionCode();
$cacheId = 'catalog_section_' . $sectionId . '_' . $regionTag;
Timeline
| Configuration | Timeline |
|---|---|
| 2–3 price types + manual region selection | 1–2 days |
| Automatic region detection by IP + user groups | 2–4 days |
| Full setup with price synchronization from 1C | 4–7 days |







