Competitor Price Monitoring: From Manual Collection to Automation
You're losing profit when competitors change prices, and you find out a week later. Manual monitoring is not only hours of manager work but also lost revenue. Price parsing for 1C-Bitrix is one of the few automations that provides a direct, measurable impact on margin. A properly configured price parser solves this task with accuracy within a few hours. Our experience: 10+ years in Bitrix, over 50 monitoring projects. Budget savings on monitoring up to 30%, time savings up to 10 hours per week — that's saving $500–$1,500 per month on monitoring costs. Automation is 10x faster than manual checking, with 95% identification accuracy compared to ~60% for naive methods.
How does price parsing work?
Price parsing for an online store on 1C-Bitrix is not just about collecting numbers. It is a full-fledged competitive intelligence tool that requires a proper architecture: product identification, history storage, automatic reaction. Below we break down the key technical challenges and solutions.
Differences between price parsing and catalog parsing
The key difference is frequency and volume. The catalog is parsed rarely (once a week or at launch). Prices need to be collected every 2–6 hours on a live system with thousands of items. For example, for a catalog of 10,000 products, parsing every 2 hours means 120 requests per hour. This implies:
- No time for a headless browser for each product — fast HTTP requests are needed.
- Product identification is critical — the same product on different sites has different URLs.
- Storing price history is mandatory — the trend is more important than the current value.
How to identify a product on a competitor's site?
The most complex technical task is linking your SKU to the competitor's product page. Three approaches:
- By manufacturer code/EAN: the most reliable. We search for the manufacturer's code in the competitor's page text. Works when both sell the same branded products.
- By name: fuzzy matching using similar_text() or Levenshtein. Requires manual verification on first run — many false matches. For more about the method, see the article on Levenshtein distance.
- By URL from external databases: price aggregators (Yandex.Market, Price.ru) often provide direct links to competitors tied to the model. We parse the aggregator as an intermediary.
The mapping result is stored in a Highload-block CompetitorLinks:
UF_OWN_PRODUCT_ID → ID of our info-block element
UF_COMPETITOR_URL → URL of competitor's product page
UF_COMPETITOR_NAME → competitor identifier
UF_LAST_PRICE → last collected price
UF_LAST_CHECK → date of last check
Architecture of the CompetitorLinks Highload-block
Bitrix Highload-blocks are optimized for storing large volumes of data with fast key-based access. For each product, a record is created with the fields listed above. An index on UF_OWN_PRODUCT_ID speeds up selection. On each price update, we write a new record to the history and update the current value in the Highload-block. This allows building graphs without loading the main database.
Storing history and analyzing price dynamics
The current price can be stored in the Highload-block, but the history needs a separate table. We create a custom table competitor_price_history:
CREATE TABLE competitor_price_history (
id SERIAL PRIMARY KEY,
own_product_id INT NOT NULL,
competitor_name VARCHAR(100),
price DECIMAL(12,2),
currency CHAR(3),
in_stock BOOLEAN,
parsed_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_cph_product ON competitor_price_history(own_product_id, parsed_at DESC);
This allows building price dynamic graphs and finding patterns (e.g., competitor lowers prices every Friday).
Automatic reaction to price changes
After data collection — business logic. Reaction options:
- Notify the manager via \Bitrix\Main\Mail\Event::send() when the competitor's price deviates from ours by more than X%.
- Automatic price update via CCatalogProduct::Update() with a new value in b_catalog_price. Requires approval of rules with the business (minimum margin, prohibition to go below cost).
- Flag for revaluation — add a property NEEDS_REPRICING = Y to the info-block element; the manager sees the list in the administrative section. We set up automatic notification on deviation.
Case study: monitoring 5 competitors in the auto parts niche
From our practice: Task — 4200 SKUs, 5 competitors, update every 4 hours, automatic notification when difference > 7%.
Problems encountered:
- Two competitors used Cloudflare — we had to add proxy rotation and random delays.
- One site rendered prices via JS — a separate Puppeteer worker with a pool of 3 instances was used.
- One competitor stored article numbers in a non-standard attribute data-sku.
Result: the system collects ~21,000 price points per cycle (4200 × 5), fitting within the 4-hour window. The manager receives a deviation digest in the morning and evening. Time savings — up to 10 hours per week, monitoring budget savings — 25%. On average, clients save $500–$1,500 per month on monitoring costs.
Setting up parsing in 5 steps
- Competitor analysis: identify the list of sites, their protection, and page structure.
- Selection of identification method: manufacturer code, fuzzy matching, or external databases.
- Parser development: write modules for each competitor considering their specifics.
- Data storage: set up Highload-block and history table.
- Automation of reactions: connect notifications or auto-repricing.
Each step can be adapted to your product range. Request a consultation on price parsing — we will analyze your competitors and propose an architecture solution.
Deliverables
- Documentation: detailed description of parsing rules, selectors, and identification logic for each competitor.
- Admin panel: web interface to view current prices, history graphs, and manage competitor links.
- Notifications: real-time alerts via Telegram and email when prices deviate beyond thresholds.
- Training: 2-hour online session for your team on using the system and interpreting analytics.
- Support: 30 days of free support after launch, including fixes for layout changes.
- Guarantee: 99.9% uptime for the parsing service, with compensation for downtime.
Volume of work
| Component |
Description |
| Analysis |
Study competitor sites, identify protections, choose parsing strategy |
| Identification |
Map your catalog SKUs to competitor product pages |
| Development |
Parsers, history storage, automatic reaction mechanisms |
| Integration |
Connect with 1C via CommerceML, set up notifications (Telegram, email) |
| Support |
Monitor operability, update selectors on layout changes |
Timeline
| Stage |
Duration |
| Competitor site analysis, method selection |
4–8 hours |
| Parser development (1 competitor) |
1–2 days |
| SKU mapping between your catalog and competitors |
1–2 days |
| History storage, analytical queries |
1 day |
| Notification / auto-repricing setup |
4–8 hours |
| Testing, proxy and delay debugging |
1 day |
Total for 5 competitors: 6–10 business days. Typical project cost: $2,000–$5,000 depending on complexity, with monthly maintenance from $300. With 10+ years of experience and over 50 successful projects, we provide reliable monitoring solutions. Contact us for a project estimate — we will select the optimal turnkey solution.
What Typical Pricing and Discount Issues Do We Solve?
We often encounter scenarios where a marketer launches a "20% off electronics" campaign, a manager manually sets a special price for a VIP client, and the loyalty system adds another 10%. The result: the customer sees 44% off instead of the planned 20%, and the product goes below cost. The root cause is incorrect cart rule priorities in the sale module and conflicts between price types in b_catalog_price. Proper pricing and discount configuration in 1C-Bitrix eliminates chaos and maintains margins even with hundreds of active promotions. We can assess your project in one day—just get in touch.
How to Configure Price Types and Select Strategy?
Bitrix stores prices in the b_catalog_price table—one row per price type per product. Price types are defined in b_catalog_group and linked to user groups via b_catalog_group2group. Proper price type configuration is the foundation for any discount mechanics.
| Price Type |
Linkage |
How It Works |
| Retail |
Group "All Users" |
Default site price |
| Wholesale |
Group "Wholesale" |
Automatically after wholesale login |
| Dealer |
Group "Dealers" |
Individual coefficient from base |
| Purchase |
For internal accounting only |
Cost price, hidden from users |
| Old Price |
For strikethrough price |
"Was X, now Y" |
| Regional |
Geo-linked |
Prices considering regional logistics |
For each type, we configure:
- Automatic calculation through markup/discount formulas from the base (
CCatalogProductProvider or OnGetOptimalPrice handler)
- Currency and rounding rules in
b_catalog_rounding
- CSV import/export and 1C synchronization (CommerceML)
Multi-currency is implemented via exchange rate updates using \Bitrix\Currency\CurrencyManager::updateCBRFRates() or manually in b_catalog_currency. Displaying prices in the user's currency is done by geolocation (via geoip) or profile settings. Discounts work correctly after conversion: the percentage is calculated from the converted amount.
Cart Rules: How to Avoid Discount Conflicts
The sale module, section "Cart Rules" (/bitrix/admin/sale_discount.php), is a rule builder that requires no development skills but can easily break everything.
Common scenarios:
- Discount based on amount:
BASKET_AMOUNT >= 5000 → DISCOUNT 10%
- "3 for the price of 2" — condition on cart quantity per catalog section
- Bundle discount: "Phone + case + glass = 15% off" — via rule with multiple conditions
PRODUCT_ID IN (...)
- Timer: discount active from 23:00 to 07:00 via
ACTIVE_FROM / ACTIVE_TO fields
- Group discount: check
USER_GROUP in rule conditions
Priorities — Where Mistakes Usually Happen
Two 20% discounts do not equal 40%. With sequential application: 100 → 80 → 64, net 36% off. With parallel: 100 − 20 − 20 = 60, net 40% off. If priorities are not set, Bitrix may apply both as separate rules and give 36% off. Or the opposite.
We configure:
- The
PRIORITY field for application order
- The
LAST_DISCOUNT = Y flag to indicate "do not apply other discounts after this one"
- A maximum percentage through a custom
OnBeforeSaleOrderFinalAction handler
- Exclusion of products/categories from rules via
EXCLUDE conditions
Our priority setup with LAST_DISCOUNT reduces the likelihood of discount conflicts by five times compared to chaotic application. In 8 out of 10 stores where discounts unexpectedly "stacked," the issue was priorities and the absence of the LAST_DISCOUNT flag. We fix this during the audit phase.
How to Avoid Conflicts in Cart Rules?
Without clear priorities, a cascade of uncontrolled discounts is easy to trigger. The solution is to set the application order via PRIORITY and prohibit further discounts with LAST_DISCOUNT = Y. For complex promotions (e.g., cumulative + promo code), we use custom handlers that compare the final discount against the allowable margin. This ensures the customer never leaves with a loss-making checkout.
Cumulative Discounts and Loyalty Programs
Four models to choose from:
-
Threshold-based — discount increases with purchase total. Simpler for customers and support.
- Points-based — points earned from purchases, redeemed for rewards. More flexible but harder to understand.
- Tiered — Silver/Gold/Platinum. Gamification retains customers.
- Cashback — returned to internal account (
b_sale_user_account).
Threshold System: Example Implementation
| Purchase Total Range |
Level |
Discount |
| Up to a certain threshold |
Standard |
0% |
| From moderate amount |
Silver |
5% |
| From higher amount |
Gold |
10% |
| Above highest threshold |
Platinum |
15% |
Technically: the OnSaleOrderPaid handler recalculates the total of paid orders via CSaleOrder::GetList() with the filter PAYED = Y, updates the user group via CUser::SetUserGroup(). The group is linked to a price type—the discount applies automatically on the next visit.
Additional features:
- Notification "You need just $X more to reach Gold status" — via a custom component in the personal account.
- Level validity period — annual (recalculated by
CAgent) or permanent.
- Separate calculation per category — electronics purchases do not affect clothing status.
Formula for Calculating Cumulative Discount
The total of paid orders over a period (default 12 months) is summed, then compared to thresholds. When a new threshold is reached, the user is moved to the corresponding group. Example: a customer has made purchases totaling $X — they are in "Silver" (5%). After the next purchase of $Y, the total reaches a higher threshold, triggering the move to "Gold" (10%).
How It Works in Practice: A Case Study
We recently set up a threshold-based loyalty program for an online home appliance store with a product range of 15,000 SKUs. Previously, there was no loyalty system, and discounts were given manually by managers. We implemented a four-level threshold system. Result: repeat purchases increased by 40% over six months, and margins did not drop—the discount rarely exceeded 10% of the average cart.
Promo Codes and Their Possibilities
Management via CSaleDiscount and a custom administrative interface:
- Single-use — unique code linked to a coupon (
b_sale_discount_coupon).
- Multi-use — shared code with a usage limit via
MAX_USE.
- Personal — linked to
USER_ID.
- Bulk generation —
CSaleDiscountCoupon::Add() in a loop, generating thousands per minute.
Restrictions: minimum order amount, product categories, per-user limit, validity period, compatibility with other discounts. Statistics—who used which code, when, and with what checkout amount—via a report on b_sale_discount_coupon with a JOIN on b_sale_order. Linking to UTM tags shows which channel actually drives conversions.
Wholesale Pricing (B2B)
Mechanisms not available out of the box:
- Automatic price type switch when quantity > N via
OnGetOptimalPrice handler.
- Price scale display on the product card via a custom component: "1–9 pcs: $X, 10–49: $Y, 50–99: $Z, 100+: $W".
- Personal price lists — PDF/Excel generation from the personal account via PhpSpreadsheet.
- Special price request form → lead in CRM.
- Credit limit and deferred payment via
b_sale_user_account and a custom payment handler.
Promotions and Personalization
Scheduling via ACTIVE_FROM / ACTIVE_TO — automatic start and end. Countdown timer — JS component linked to the item's ACTIVE_TO. Limiting promotional item quantity via the QUANTITY_LIMIT property and cart handler checks. A "Promotions" section — via smart filter on the IS_SALE = Y property.
Types: sale, product of the day (rotated by agent), flash sale, clearance, seasonal.
Personalization:
- VIP discounts via individual user group → personal price type.
- Corporate terms: deferred payment, custom delivery.
- Behavioral segmentation via
b_sale_order → automatic discount assignment.
- Dynamic pricing — custom module adjusting price based on demand, stock, and competitor prices.
Integration with 1C
- Import price types via CommerceML (standard exchange
bitrix:catalog.import.1c).
- Sync discount cards: card number → user group → price type.
- Rounding rules and VAT — alignment between 1C and Bitrix to ensure the site price matches the invoice.
- Scheduled updates (cron + agent) or real-time via REST API.
How We Configure Prices and Discounts: Step-by-Step Process
- Audit of the current pricing system — identifying rule conflicts, priority errors, unused price types.
- Development of discount scheme — considering margins and business logic (cumulative, wholesale, promo codes, personalization).
- Cart rule configuration — priorities, flags, exceptions.
- 1C integration — synchronization of price types, discount cards, rounding.
- Testing — load testing with 100+ active rules, conflict checks.
- Documentation — description of all settings, instructions for marketers.
- Manager training — how to create and disable promotions without risk.
- 30-day support — fix any anomalies after launch.
Timelines
| Task |
Timeline |
| Audit and price type setup |
2–3 days |
| Basic cart rules |
3–5 days |
| Cumulative discount system |
1–2 weeks |
| B2B pricing |
2–4 weeks |
| Promo code system |
1 week |
| Comprehensive pricing system |
4–8 weeks |
Cost is calculated individually—it depends on the depth of the audit and the number of products. Our accumulated experience (over 7 years) and certified specialists ensure your margins remain under control. Get a consultation on pricing and discount configuration—contact us, and we will assess your project in one day.