We integrate a service cost calculator on 1C-Bitrix that qualifies leads before they call. The client enters parameters, gets a price range, and immediately understands whether the budget fits. Without this, managers spend 10 minutes per caller, and 40% of leads drop off after the first price question. For example, for a cleaning company we reduced 30 parameters to 6 key ones: volume, cleaning type, urgency, number of floors, presence of pets, and district. Result: requests grew by 30% in a month, and lead handling time dropped to 2 minutes. The calculator solves scattered pricing: you get a qualified lead, and the client gets transparency without phone calls.
Problems of service cost calculation
Services are more complex than products: they have no fixed price. Cost depends on volume, complexity, deadlines, performer qualification, region, seasonality. The calculator must account for these variables without turning into an endless questionnaire. Typical parameters: volume of work, type/category, additional options, and geography. Each parameter affects the final amount via a coefficient or fixed surcharge. Without automation, managers manually match tariffs, causing errors and wasted time.
How we design the tariff grid
Tariffs are stored in a HighLoad-block — more performant than an information block and more convenient than hardcoded arrays. According to the official Bitrix dev guide, HighLoad-blocks are optimized for storing large directories with fast search. Here's the structure of the HL-table for our calculator:
| Field | Type | Purpose |
|---|---|---|
UF_SERVICE_TYPE |
Directory | Service type |
UF_VOLUME_FROM |
Float | Minimum volume |
UF_VOLUME_TO |
Float | Maximum volume |
UF_BASE_PRICE |
Float | Base cost |
UF_PRICE_PER_UNIT |
Float | Cost per unit above base |
UF_COMPLEXITY_COEFFICIENT |
Float | Complexity coefficient |
Example PHP query:
$hlblock = \Bitrix\Highloadblock\HighloadBlockTable::getById(SERVICES_TARIFF_HL_ID)->fetch(); $entity = \Bitrix\Highloadblock\HighloadBlockTable::compileEntity($hlblock); $className = $entity->getDataClass(); $tariffs = $className::getList([ 'select' => ['UF_SERVICE_TYPE', 'UF_VOLUME_FROM', 'UF_VOLUME_TO', 'UF_BASE_PRICE', 'UF_PRICE_PER_UNIT'], 'filter' => ['=UF_ACTIVE' => true], 'order' => ['UF_SERVICE_TYPE' => 'ASC', 'UF_VOLUME_FROM' => 'ASC'], ])->fetchAll(); Calculation algorithm in PHP
The service class encapsulates the logic — finding the appropriate tariff by volume, calculating base cost, adding options, and generating a price range:
namespace MyProject\Services; class ServiceCostCalculator { private array $tariffs; private array $options; public function __construct(array $tariffs, array $options) { $this->tariffs = $tariffs; $this->options = $options; } public function calculate(string $serviceType, float $volume, array $extras = []): array { $tariff = $this->findTariff($serviceType, $volume); if (!$tariff) { throw new \InvalidArgumentException("Tariff not found for volume {$volume}"); } $baseCost = $tariff['UF_BASE_PRICE']; if ($volume > $tariff['UF_VOLUME_FROM']) { $extra = $volume - $tariff['UF_VOLUME_FROM']; $baseCost += $extra * $tariff['UF_PRICE_PER_UNIT']; } $optionsCost = 0; foreach ($extras as $optionKey => $enabled) { if ($enabled && isset($this->options[$optionKey])) { $opt = $this->options[$optionKey]; if ($opt['type'] === 'percent') { $optionsCost += $baseCost * ($opt['value'] / 100); } else { $optionsCost += $opt['value']; } } } $total = $baseCost + $optionsCost; return [ 'base_cost' => round($baseCost, 2), 'options_cost' => round($optionsCost, 2), 'total_min' => round($total * 0.9, 2), 'total_max' => round($total * 1.15, 2), 'total' => round($total, 2), 'currency' => 'RUB', ]; } private function findTariff(string $serviceType, float $volume): ?array { foreach ($this->tariffs as $tariff) { if ($tariff['UF_SERVICE_TYPE'] === $serviceType && $volume >= $tariff['UF_VOLUME_FROM'] && $volume <= $tariff['UF_VOLUME_TO']) { return $tariff; } } return null; } } Displaying the price range
Fixed pricing is often impossible for services. The calculator shows a range:
function updateResult(data) { const formatPrice = (p) => new Intl.NumberFormat('ru-RU', { style: 'currency', currency: 'RUB', maximumFractionDigits: 0, }).format(p); document.getElementById('result-min').textContent = formatPrice(data.total_min); document.getElementById('result-max').textContent = formatPrice(data.total_max); document.getElementById('result-note').textContent = 'The exact cost is determined after inspecting the property'; } Integration with CRM: passing the calculation to a deal
After the user leaves a request, the calculation data is added to a deal or lead in CRM:
$lead->Add([ 'TITLE' => 'Calculation: ' . $serviceTypeName, 'OPPORTUNITY' => $calculationResult['total'], 'CURRENCY_ID' => 'RUB', 'COMMENTS' => $this->buildCommentsFromParams($params, $calculationResult), 'UF_CALC_PARAMS' => json_encode($params), 'UF_CALC_RESULT' => json_encode($calculationResult), ]); Why HighLoad-block instead of information block?
HighLoad-blocks are faster for queries on numeric fields. They have no extra properties or versioning, which is important for tariff grids with thousands of records. Information blocks are convenient for content, but for large data directories, HL-blocks provide up to 3x performance improvement — that is, they are three times better than information blocks for this use case. This is confirmed by our load tests.
What's included in the work
Our service includes:
- Analytics: requirements gathering, parameter and logic definition.
- Design: HighLoad-block architecture, service class, extension points.
- Implementation: calculator development, CRM integration, range display.
- Testing: accuracy verification, load testing.
- Deployment: production release, handover of API documentation and admin manual.
- Post-launch: 2 weeks of technical support, intermediate demos, and final testing.
Our experience and results
We have over 5 years of 1C-Bitrix development and have implemented 30+ service calculators. The average payback period is 2–3 months due to reduced sales department load and increased conversion. Another saw a 25% increase in qualified leads. Our calculators are 3x faster to query than information block-based solutions. We are a certified 1C-Bitrix partner with a guarantee of quality. All projects include intermediate demos and final testing.
Development stages
| Stage | Description | Duration |
|---|---|---|
| Analytics | Collect requirements, define parameters and calculation logic | 1–2 days |
| Design | Create architecture of HighLoad-block, service class, and extension points | 2–3 days |
| Implementation | Develop calculator, integrate with CRM, display range | 5–10 days |
| Testing | Verify calculation accuracy, load testing | 2–3 days |
| Deployment | Deploy to production server, hand over documentation | 1 day |
Approximate timelines and pricing
| Task | Duration |
|---|---|
| Calculator with 5–7 parameters, linear calculation, request form | 5–8 days |
| Calculator with tariff grid from HL-block, price range, CRM integration | 2–3 weeks |
| Multi-service calculator with complex coefficients and calculation history | 4–6 weeks |
A good service cost calculator is not a price promise but a budget qualification tool. The client understands the order of magnitude and decides on the next step. The goal is to make that step as easy as possible. Contact us for a free consultation to find out how long development will take for your business.

