Developing an analytics dashboard in Vue.js for 1C-Bitrix

Our company is engaged in the development, support and maintenance of Bitrix and Bitrix24 solutions of any complexity. From simple one-page sites to complex online stores, CRM systems with 1C and telephony integration. The experience of developers is confirmed by certificates from the vendor.
Our competencies:
Development stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1173
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Development based on Bitrix, Bitrix24, 1C for the company Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    745
  • image_crm_dolbimby_434_0.webp
    Website development on CRM Bitrix24 for DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    976

Analytics Dashboard Development on Vue.js for 1C-Bitrix

Standard reports in the Bitrix admin panel are static HTML tables generated on every page refresh. For real-time business performance monitoring this is not enough: you can't change the period without a reload, there's no trend visualization, and data from multiple sources isn't aggregated. Vue.js combined with Chart.js or ECharts transforms Bitrix data into a live dashboard.

Where the Data Comes From

Bitrix stores everything needed in the database: orders in b_sale_order, line items in b_sale_basket, payments in b_sale_pay_system_action, customers in b_user. The D7 ORM lets you build aggregating queries directly via DataManager:

$result = \Bitrix\Sale\Internals\OrderTable::getList([
    'select' => [
        new \Bitrix\Main\ORM\Fields\ExpressionField(
            'TOTAL', 'SUM(%s)', 'PRICE'
        ),
        new \Bitrix\Main\ORM\Fields\ExpressionField(
            'COUNT', 'COUNT(*)', 'ID'
        ),
        'DATE_KEY' => 'DATE_INSERT',
    ],
    'filter' => [
        '>=DATE_INSERT' => $dateFrom,
        '<=DATE_INSERT' => $dateTo,
        '=STATUS_ID' => ['N', 'P', 'F'],
    ],
    'group' => ['DATE_KEY'],
]);

A custom REST controller (extending Bitrix\Main\Engine\Controller) accepts period parameters and returns aggregated JSON. The controller is gated behind checkPermissions — only users with the sale_order_view right.

Vue Dashboard Structure

The dashboard is built from independent widgets — each Widget*.vue component loads its own data and displays its own loading state. The parent Dashboard.vue only manages the shared period via provide/inject.

Key widgets:

  • RevenueChart — line or bar chart of revenue over time (Chart.js line)
  • OrdersKpi — KPI cards: revenue, order count, average order value, conversion rate
  • TopProducts — horizontal bar chart of the top 10 products by sales
  • FunnelWidget — funnel: visitors → added to cart → placed order → paid
  • OrdersTable — latest orders with pagination, quick link to the order in the admin panel

Global period filter — DatePicker with preset ranges ("Today", "This week", "This month", "Last month", "Custom"). When the period changes, all widgets react via watchEffect or watch on period from inject and reload their data.

Integration with Multiple Sources

A real dashboard is rarely limited to a single system. A typical data stack for e-commerce on Bitrix:

  • Orders and revenueb_sale_order, b_sale_basket via D7
  • Traffic — Yandex.Metrika API or Google Analytics 4 Data API
  • CRM metrics — if the crm module is installed, CCrmDeal::GetList or Bitrix\Crm\DealTable
  • Ad spend — Yandex.Direct API, VK Ads API, if integrations are configured

In Vue each source is a separate composable:

// useMetrikaData.js
export function useMetrikaData(period) {
    const data = ref(null);
    const loading = ref(false);
    const error = ref(null);

    watchEffect(async () => {
        loading.value = true;
        try {
            data.value = await fetchMetrika(period.value);
        } catch (e) {
            error.value = e.message;
        } finally {
            loading.value = false;
        }
    });
    return { data, loading, error };
}

Parallel requests via Promise.all — the dashboard doesn't wait for each source sequentially.

Case: Dashboard for an Online Store Manager

An electronics store on Bitrix, 200–400 orders per day. The problem: the director asked managers every day to compile a report from 1C, the Bitrix panel, and Metrika. The process took 40 minutes.

We built a dashboard accessible at /area51/dashboard/sales/ (in the Bitrix admin area, behind authentication). Technically — an admin section page via CAdminSection, on which a Vue application is mounted.

Widgets: today's/yesterday's/7-day revenue with a trend arrow, order count by status (new/processing/completed/cancelled), top 5 products for the period, two-period comparison on a single chart, abandoned cart rate (b_sale_basket where ORDER_ID IS NULL).

Abandoned cart data — a custom query not available in Bitrix's standard reports:

SELECT DATE(DATE_INSERT) as day, COUNT(DISTINCT FUSER_ID) as abandoned
FROM b_sale_basket
WHERE ORDER_ID IS NULL
  AND DATE_INSERT >= NOW() - INTERVAL 30 DAY
GROUP BY day

The dashboard auto-refreshes every 5 minutes via setInterval — up-to-date data without pressing F5. Development time — 3 weeks, including all widgets and Metrika integration.

Query Performance

Aggregating queries on b_sale_order on large databases (100K+ orders) require indexes. Check with EXPLAIN:

  • DATE_INSERT — index is mandatory for period filtering
  • Composite index (STATUS_ID, DATE_INSERT) — for filtering by status and period simultaneously
  • Results of heavy aggregations are cached via Bitrix\Main\Data\Cache for 5–15 minutes

Stages and Timelines

Dashboard scale Estimated timeline
3-4 KPI cards + one chart 3-5 days
Full sales dashboard (5-8 widgets) 2-3 weeks
Dashboard with external API integration (Metrika, CRM) 3-5 weeks
Analytics platform with multiple roles 6-10 weeks

Timelines depend on the number of data sources, aggregation complexity, and custom visualization requirements.