Competitor Price Monitoring in 1C-Bitrix: Setup & Integration

Setting Up Competitor Price Monitoring for 1C-Bitrix We worked with a major home appliance online retailer whose competitors changed prices up to 15 times a day. Manual monitoring took a manager 2 hours daily, and reaction delays cost up to 5% margin on individual items. Our solution: automatic c

Our competencies:

Frequently Asked Questions

Setting Up Competitor Price Monitoring for 1C-Bitrix

We worked with a major home appliance online retailer whose competitors changed prices up to 15 times a day. Manual monitoring took a manager 2 hours daily, and reaction delays cost up to 5% margin on individual items. Our solution: automatic competitor price tracking inside 1C-Bitrix.

Price tracking is built in one of two ways: through a ready monitoring service (Competera, Metacommerce, Priceva) or via a custom parser. Ready services are simpler and more reliable but expensive for catalogs over 10,000 SKUs. Custom parsers are flexible and cheap to operate but require regular maintenance when competitor sites change. In both cases, the setup task is the same: collect data, save it in Bitrix, and present it to the manager in a convenient way.

Approach Comparison: Service vs Parser

Criteria Ready Service Custom Parser
Implementation speed 1–2 days 3–5 days
Dependency on external API Yes (key, limits) No (but depends on site structure)
Operating cost High (subscription) Low (server only)
Stability High Medium (parser break risk)
Catalog volume Limited by tariff Unlimited

The choice depends on your budget and volume. For catalogs over 50,000 products, a parser is usually more cost-effective.

Why You Should Not Store Competitor Prices in Infoblocks

Bitrix infoblocks are not designed for frequent mass updates. With 10,000 products and 5 competitors, you get 50,000 records rewritten every hour. The infoblock ORM generates unnecessary events (OnBeforeIBlockElementUpdate), flushes cache, and slows down the admin panel. The solution is to use HL-blocks or separate database tables. We prefer tables—they are faster, without event overhead or versioning.

Data Storage Architecture

Regardless of the data source, the storage structure is the same. We create two main tables: Competitors bl_price_competitors:

CREATE TABLE bl_price_competitors ( id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, domain VARCHAR(255) UNIQUE, active BOOLEAN DEFAULT true, logo_url VARCHAR(512) ); 

Competitor Prices bl_competitor_prices:

CREATE TABLE bl_competitor_prices ( id SERIAL PRIMARY KEY, product_id INT NOT NULL, -- b_iblock_element.ID competitor_id INT REFERENCES bl_price_competitors(id), price NUMERIC(12,2) NOT NULL, url VARCHAR(512), -- URL of competitor's page in_stock BOOLEAN DEFAULT true, checked_at TIMESTAMP NOT NULL DEFAULT NOW(), UNIQUE (product_id, competitor_id) -- one current price per competitor ); CREATE INDEX idx_comp_prices_product ON bl_competitor_prices(product_id, checked_at DESC); 

History bl_competitor_prices_history—a month-partitioned table to store changes without bloating the main table. When the current price is updated, the previous value moves to history.

API Integration via Monitoring Service

With a ready service, an agent requests data and writes to bl_competitor_prices:

function SyncCompetitorPrices(): string { $client = new PriceMonitoringClient(MONITORING_API_KEY); $data = $client->getPrices(['date' => date('Y-m-d')]); foreach ($data['products'] as $item) { $productId = ProductMapper::findBySku($item['sku']); if (!$productId) continue; foreach ($item['competitors'] as $comp) { $competitorId = CompetitorTable::getOrCreateByDomain($comp['domain']); // Save to history before update $current = CompetitorPriceTable::getByProductAndCompetitor($productId, $competitorId); if ($current && $current['PRICE'] != $comp['price']) { CompetitorPriceHistoryTable::add([ 'PRODUCT_ID' => $productId, 'COMPETITOR_ID' => $competitorId, 'PRICE' => $current['PRICE'], 'RECORDED_AT' => $current['CHECKED_AT'], ]); } CompetitorPriceTable::addOrUpdate([ 'PRODUCT_ID' => $productId, 'COMPETITOR_ID' => $competitorId, 'PRICE' => $comp['price'], 'URL' => $comp['url'], 'IN_STOCK' => $comp['in_stock'], 'CHECKED_AT' => new \Bitrix\Main\Type\DateTime(), ]); } } return __FUNCTION__ . '();'; } 

Calculating Price Position and Aggregates

Upon each update, we calculate aggregates and position in bl_product_price_position:

-- Updated via trigger or agent after sync INSERT INTO bl_product_price_position (product_id, our_price, min_comp, avg_comp, max_comp, rank, updated_at) SELECT cp.product_id, bcp.PRICE as our_price, MIN(cp.price) as min_comp, ROUND(AVG(cp.price), 2) as avg_comp, MAX(cp.price) as max_comp, (SELECT COUNT(*) + 1 FROM bl_competitor_prices cp2 WHERE cp2.product_id = cp.product_id AND cp2.price < bcp.PRICE) as rank, NOW() FROM bl_competitor_prices cp JOIN b_catalog_price bcp ON bcp.PRODUCT_ID = cp.product_id AND bcp.CATALOG_GROUP_ID = 1 GROUP BY cp.product_id, bcp.PRICE ON CONFLICT (product_id) DO UPDATE SET our_price = EXCLUDED.our_price, min_comp = EXCLUDED.min_comp, avg_comp = EXCLUDED.avg_comp, rank = EXCLUDED.rank, updated_at = NOW(); 

How to Set Up Alerts for Competitor Price Changes?

An agent compares new prices with previous ones and notifies managers of significant changes—for example, when a competitor becomes cheaper than us:

foreach ($priceChanges as $change) { if ($change['new_price'] < $change['our_price'] && $change['old_price'] >= $change['our_price']) { $message = sprintf( 'Competitor %s has lowered price on %s to %s RUB (ours: %s RUB)', $change['competitor_name'], $change['product_name'], number_format($change['new_price'], 2, ',', ' '), number_format($change['our_price'], 2, ',', ' ') ); \Bitrix\Main\Mail\Event::send([ 'EVENT_NAME' => 'COMPETITOR_PRICE_ALERT', 'LID' => SITE_ID, 'C_FIELDS' => ['MESSAGE' => $message], ]); } } 

Typical Mistakes in Monitoring Setup

  • Using infoblocks for storage—leads to performance degradation above 20,000 records.
  • Missing indexes on product_id and checked_at—the sync agent runs hours instead of minutes.
  • Parsers without error handling—when a competitor's site goes down, the agent throws an exception and stops until manual intervention.
  • Too infrequent updates—with once-a-day updates, you miss intraday fluctuations that can reach 30%.

What Is Included in Our Service Setup?

  • Analysis of your catalog and selection of the optimal data source (service or parser).
  • Creation of tables or HL-blocks for competitors, prices, and history.
  • Development of a synchronization agent with detailed error handling (logging, retries).
  • Implementation of a price position calculation module with ranking.
  • Display of competitor prices in the product card in the admin panel and on the storefront (optional).
  • Configuration of email or Bitrix24 notifications.
  • Architecture documentation and maintenance instructions.

Timelines and Our Guarantees

Phase Duration
Database schema and repositories 2 days
Sync agent with data source 2 days
Position and aggregate calculation 1 day
Display in product card (admin) 2 days
Change alerts 1 day
Testing 1 day
Total 9–10 days

Pricing is determined individually based on catalog size and integration complexity. We guarantee stable agent operation for 6 months after delivery. Contact us for a free project assessment, and we'll propose an architecture for your budget. Get a consultation on price monitoring architecture, and you'll see that automation pays off within the first two months.

Over 10 years of experience in Bitrix and Bitrix24 development, more than 50 successful integrations with price monitoring systems—our expertise handles any complexity.