A category manager spends up to 30% of their time manually checking prices — opening product cards, comparing with competitors, repeating the cycle. With a catalog of 50,000 SKUs, that's hundreds of man-hours per month that could be spent on strategic pricing. We set up a dashboard that shows problematic positions within 30 seconds, the difference in rubles and percentages, and allows price changes right on the screen. This approach reduces analysis time by 10x compared to manual comparison and lowers the chance of errors when copying data.
On one project with a catalog of 120,000 products, we implemented the dashboard in 8 days. After launch, managers reduced time on price analysis from 4 hours to 15 minutes per day. Average time savings on price analysis — 30%, implementation payback is 2–3 months due to reduced manual labor. We'll estimate your project in 1 day and provide a quote without overcharges. Contact us for a consultation.
Data Sources
The dashboard is built on three tables:
-
bl_competitor_prices— current competitor prices -
bl_product_price_position— aggregates (min/max/average of competitors, our rank) -
b_catalog_price— our current prices
Data in the aggregate table is updated by an agent after each competitor price synchronization. To speed up queries, we add indexes on product_id, rank, and updated_at fields. SQL optimization allows processing catalogs up to 1 million products without noticeable delays. For catalogs over 500,000 SKUs, we additionally set up table partitioning and tagged caching via Bitrix Cache.
Why a Heat Map by Sections Is Key to Quick Diagnosis
Instead of scrolling through endless products, the manager immediately sees which catalog section is "on fire". We generate a map: green (>70% in 1st place), yellow (50–70%), red (<50%). This cuts analysis time by 10x compared to manual checking.
// Query for section aggregates $sectionStats = \Bitrix\Main\Application::getConnection()->query(" SELECT s.NAME as section_name, COUNT(*) as total_products, COUNT(CASE WHEN ppp.rank = 1 THEN 1 END) as on_first_place, ROUND(AVG(ppp.rank), 1) as avg_rank, COUNT(CASE WHEN ppp.our_price > ppp.min_comp THEN 1 END) as losing_count FROM bl_product_price_position ppp JOIN b_iblock_element ie ON ie.ID = ppp.product_id JOIN b_iblock_section s ON s.ID = ie.IBLOCK_SECTION_ID GROUP BY s.ID, s.NAME ORDER BY losing_count DESC ")->fetchAll(); What Metrics Does the Dashboard Show?
Price Position — product distribution by rank:
SELECT rank, COUNT(*) as product_count FROM bl_product_price_position WHERE updated_at > NOW() - INTERVAL '24 hours' GROUP BY rank ORDER BY rank; Displayed as a bar chart: "1st place — 34 products, 2nd place — 87, 3rd place — 124..." Products Where We Are More Expensive Than the Minimum Competitor Price:
SELECT ie.ID, ie.NAME, ppp.our_price, ppp.min_comp as competitor_min, ROUND((ppp.our_price - ppp.min_comp) / ppp.min_comp * 100, 1) as diff_pct, ppp.rank FROM bl_product_price_position ppp JOIN b_iblock_element ie ON ie.ID = ppp.product_id WHERE ppp.our_price > ppp.min_comp AND ppp.min_comp > 0 ORDER BY diff_pct DESC LIMIT 50; Lost Revenue (estimate):
SELECT SUM( (ppp.our_price - ppp.min_comp) / ppp.our_price * oe.order_count * ppp.our_price ) as estimated_lost_revenue FROM bl_product_price_position ppp JOIN ( SELECT product_id, COUNT(DISTINCT order_id) as order_count FROM b_sale_basket WHERE date_insert > NOW() - INTERVAL '30 days' GROUP BY product_id ) oe ON oe.product_id = ppp.product_id WHERE ppp.our_price > ppp.min_comp; How to Update Data Without Reloading?
The "Refresh Data" button triggers an AJAX request to the backend, which synchronizes data with the price source and recalculates aggregates. The interface remains responsive — no F5.
document.getElementById('refresh-btn').addEventListener('click', function() { this.disabled = true; fetch('/bitrix/services/main/ajax.php?action=PriceDashboard:refresh', { method: 'POST', headers: {'X-Bitrix-Csrf-Token': BX.bitrix_sessid()} }) .then(r => r.json()) .then(data => { if (data.status === 'ok') location.reload(); }); }); Dashboard Page Structure
The page at /bitrix/admin/price_dashboard.php consists of three blocks: Top block — summary KPIs:
- Total products under monitoring: N
- Of which more expensive than competitors: N (XX%)
- Average price position: X.X place
- Products in 1st place: N
Middle block — heat map by catalog sections (described above). Bottom block — table of problematic products with columns:
| Product | Art | Our Price | Min Competitor | Difference | Rank | [Change Price] |
|---|
The "Change Price" button — inline editing with saving via AJAX into b_catalog_price. Upon saving, the bl_price_change_log logs who changed, when, from which price, to which price.
Details of Inline Editing Implementation
For inline editing, we use the `bitrix:main.ui.grid` component with a custom action. After changing the price, a request is sent to `/bitrix/services/main/ajax.php?action=PriceDashboard:updatePrice` which validates data, writes to `b_catalog_price` and the log. If the price goes out of allowable limits, the user receives an error message.Work Process
- Analysis — we study your current catalog, competitor price sources, typical manager queries. Define key metrics.
- Design — design HL-block structure, agents, SQL queries, and interface.
- Implementation — write code: aggregate queries, dashboard with Chart.js, inline editing, export.
- Testing — test on real data, measure performance, fix bottlenecks.
- Launch — deploy to production, train managers, hand over documentation.
Export to Excel
The "Export to Excel" button generates a report via \PhpOffice\PhpSpreadsheet: all products with competitor prices in separate columns (each competitor is a separate column), our price, position, recommended price (if a repricer is configured).
What's Included in the Work (Deliverables)
- Configured aggregate tables with optimized indexes
- SQL queries for KPIs, heat map, and problem list
- Dashboard interface (PHP + JS + Chart.js)
- Inline price editing with logging
- Export to Excel
- Manager manual on working with the dashboard
- 30-day warranty on stable operation
Timelines
| Stage | Time |
|---|---|
| Aggregate queries and optimization | 2 days |
| Top KPI block + Chart.js | 1 day |
| Heat map by sections | 1 day |
| Problem product table + inline editing | 2 days |
| Excel export | 1 day |
| Testing | 1 day |
| Total | 8–9 days |
Common Mistakes When Implementing a Dashboard
Ignoring indexes. Without proper indexes (especially on product_id and rank), queries on a catalog of 100,000 products can take minutes. We always check EXPLAIN and add composite indexes.
Synchronization during peak load. Updating aggregates via agent once an hour is usually safe, but if parsing runs during active manager work, it's better to shift the schedule to night or use a job queue.
Lack of change logging. Without the bl_price_change_log, it's impossible to track who changed prices and when. This is critical for reports and audits.
With our experience (more than 50 dashboard implementations on Bitrix), we avoid these pitfalls. Certified specialists with 7+ years of working with 1C-Bitrix guarantee a stable solution. Order a turnkey dashboard setup.
Get a consultation — contact us, we'll evaluate your project and prepare a roadmap. Your commercial manager will get a tool that really saves time. For details on working with HL-blocks, refer to the official 1C-Bitrix documentation for Highload blocks.

