Custom Vue.js Dashboards for Bitrix24: Funnels, KPIs, and Reports

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.
Showing 1 of 1All 1626 services
Custom Vue.js Dashboards for Bitrix24: Funnels, KPIs, and Reports
Medium
~1-2 weeks
Frequently Asked Questions

Our competencies:

Development stages

Latest works

  • image_website-b2b-advance_0.webp
    B2B ADVANCE company website development
    1378
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Website development for FIXPER company
    968
  • 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
    705
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    851
  • image_crm_dolbimby_434_0.webp
    Website development on CRM Bitrix24 for DOLBIMBY
    747
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    1095

Custom Vue.js Dashboards for Bitrix24: Funnels, KPIs, and Reports

Built-in Bitrix24 analytics covers standard scenarios: sales funnel, manager report, plan/actual. As soon as a business analyst comes with a request like "show me conversion by source in the context of regions for an arbitrary period with a filter by responsible person" — standard reports end. A custom analytics interface (Vue-based dashboard) is a tailored solution embedded into Bitrix24 via an iframe application with direct access to the REST API. We handle such projects turnkey and have already implemented over 20 projects for companies of various sizes. These dashboards save up to 40% of managers' time on data collection and allow seeing business metrics in real time.

Why is a Vue.js dashboard more effective than standard reports?

Standard Bitrix24 analytics provides fixed slices: plan/actual, funnel, manager report. But for deep analysis — conversion by source in the context of regions, comparison of dynamics by month, custom metrics — you have to export data to Excel and process manually. A Vue-based dashboard solves this: data is fetched via REST API, aggregated on the client or server, and displayed in interactive charts. According to our measurements, such a dashboard processes requests 3 times faster than a standard report with several filters. The user gets a decision-making tool: they see sales dynamics, funnel conversion, manager efficiency in real time. Data updates automatically, filters allow viewing any period. Without modifications to the standard CRM.

Dashboard Architecture

The dashboard consists of three layers:

  • Data layer — queries to Bitrix24 REST API, caching, aggregation. For heavy aggregations, we use an intermediate server layer (Node.js/PHP) that merges data from several REST calls and returns a ready JSON.
  • Storage layer — Pinia stores with reactive computed properties.
  • Presentation layer — Vue components with Chart.js or ApexCharts.

How to speed up data loading for the dashboard?

Bitrix24 REST API has a limit of 50 elements per request. To fetch all deals for a period, pagination or callBatch is needed. We use batch data collection with pagination and server-side caching. According to the official Bitrix24 REST API documentation, the limit per request is 50 records, so we bypass this using callBatch in composable functions.

// composables/useCrmData.js
export function useCrmData() {
  const { callMethod } = useBx24()

  async function fetchAllDeals(filter) {
    const allDeals = []
    let start = 0
    let hasMore = true

    while (hasMore) {
      const result = await callMethod('crm.deal.list', {
        select: ['ID', 'TITLE', 'STAGE_ID', 'OPPORTUNITY', 'SOURCE_ID',
                 'ASSIGNED_BY_ID', 'DATE_CREATE', 'UF_CRM_REGION'],
        filter,
        order: { ID: 'ASC' },
        start,
      })
      allDeals.push(...result)
      hasMore = result.length === 50
      start += 50
    }

    return allDeals
  }

  async function fetchDealsByStages(filter) {
    const [deals, stages] = await Promise.all([
      fetchAllDeals(filter),
      callMethod('crm.status.list', {
        filter: { ENTITY_ID: 'DEAL_STAGE' }
      })
    ])
    return { deals, stages }
  }

  return { fetchAllDeals, fetchDealsByStages }
}

Period Filter Component

The date filter is one of the key dashboard elements. We implement it on Vue 3 using date-fns.

<!-- components/DateRangeFilter.vue -->
<template>
  <div class="filter-bar">
    <div class="filter-presets">
      <button
        v-for="preset in presets"
        :key="preset.id"
        :class="{ active: activePreset === preset.id }"
        @click="applyPreset(preset)"
      >{{ preset.label }}</button>
    </div>
    <div class="filter-custom">
      <input type="date" v-model="dateFrom" @change="emitCustomRange" />
      <input type="date" v-model="dateTo" @change="emitCustomRange" />
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { startOfMonth, endOfMonth, subMonths, format } from 'date-fns'

const emit = defineEmits(['change'])
const activePreset = ref('current_month')
const dateFrom = ref('')
const dateTo = ref('')

const presets = [
  { id: 'current_month', label: 'Current month' },
  { id: 'prev_month', label: 'Previous month' },
  { id: 'quarter', label: 'Quarter' },
  { id: 'year', label: 'Year' },
]

function applyPreset(preset) {
  activePreset.value = preset.id
  const now = new Date()
  let from, to

  switch (preset.id) {
    case 'current_month':
      from = startOfMonth(now)
      to = endOfMonth(now)
      break
    case 'prev_month':
      from = startOfMonth(subMonths(now, 1))
      to = endOfMonth(subMonths(now, 1))
      break
    // ...
  }

  emit('change', {
    from: format(from, 'yyyy-MM-dd'),
    to: format(to, 'yyyy-MM-dd'),
  })
}
</script>

Integrating Chart.js

For creating charts, we use a composable that initializes Chart.js and updates it when the configuration changes.

// composables/useChart.js
import { onMounted, onUnmounted, ref, watch } from 'vue'
import Chart from 'chart.js/auto'

export function useChart(canvasRef, config) {
  let chart = null

  onMounted(() => {
    chart = new Chart(canvasRef.value, config.value)
  })

  watch(config, (newConfig) => {
    if (!chart) return
    chart.data = newConfig.data
    chart.update('active')
  }, { deep: true })

  onUnmounted(() => chart?.destroy())
}

Sales funnel component with horizontal bars:

<template>
  <div class="chart-card">
    <h3>Sales Funnel</h3>
    <canvas ref="canvasRef" height="300"></canvas>
  </div>
</template>

<script setup>
import { ref, computed } from 'vue'
import { useDashboardStore } from '@/stores/dashboard'
import { useChart } from '@/composables/useChart'

const store = useDashboardStore()
const canvasRef = ref(null)

const chartConfig = computed(() => ({
  type: 'bar',
  data: {
    labels: store.stages.map(s => s.NAME),
    datasets: [{
      label: 'Number of deals',
      data: store.stages.map(s => store.dealsByStage[s.STATUS_ID] || 0),
      backgroundColor: store.stages.map(s => s.COLOR || '#4a90d9'),
    }]
  },
  options: {
    indexAxis: 'y',
    responsive: true,
    plugins: { legend: { display: false } }
  }
}))

useChart(canvasRef, chartConfig)
</script>

KPI Cards

Aggregating metrics on the client using Pinia computed:

// stores/dashboard.js
const kpis = computed(() => {
  const deals = filteredDeals.value
  const won = deals.filter(d => d.STAGE_ID === 'WON')
  const total = deals.length

  return {
    totalDeals: total,
    wonDeals: won.length,
    conversionRate: total ? Math.round((won.length / total) * 100) : 0,
    totalRevenue: won.reduce((sum, d) => sum + parseFloat(d.OPPORTUNITY || 0), 0),
    avgDealSize: won.length
      ? won.reduce((sum, d) => sum + parseFloat(d.OPPORTUNITY || 0), 0) / won.length
      : 0,
  }
})

Performance

Dashboards with large data volumes require optimization:

  • Server-side aggregation — do not transfer 10,000 deals to the browser.
  • shallowRef for large arrays in Pinia — deep reactivity for each object is not needed.
  • Table virtualization — @tanstack/vue-virtual for lists > 500 rows.
  • Debounce on filters — 300–500 ms before making a request.

Chart Library Comparison

Library Chart types Performance License
Chart.js 8 basic High up to 1k points MIT
ApexCharts 15+ (including heatmaps) Medium up to 10k points MIT
ECharts 20+ High up to 100k points Apache 2.0

For most dashboards, Chart.js is suitable, but if complex dashboards with large data are needed, we use ApexCharts or ECharts.

Data Fetching Methods Comparison

Method Speed Limits
Direct REST Medium 50 records
callBatch Fast 50 per request
Server proxy High None

Development Process and Guarantees

The process includes:

  1. Metric analysis and requirement gathering – define KPIs and data sources.
  2. Layout and wireframe design – approve dashboard mockups.
  3. Development on Vue 3 + Pinia stack – build reusable components.
  4. Integration with Bitrix24 REST API – implement data fetching and caching.
  5. Performance testing on real data – optimize for speed.
  6. Deployment to the cloud or Bitrix24 server.
  7. Handover of documentation, access, and training for analysts.

The cost includes:

  • Dashboard development according to your requirements.
  • Integration with Bitrix24 REST API, caching setup.
  • Interface assembly using Vue.js, Pinia, Chart.js/ApexCharts.
  • Testing on real data, query optimization.
  • Documentation, code access, user training.
  • 6-month warranty on functionality.

What's Included in the Work

  • Custom dashboard design and development
  • Integration with Bitrix24 REST API
  • Data caching and aggregation setup
  • Interactive charts using Chart.js or ApexCharts
  • Complete documentation and source code
  • User training for analysts
  • 6-month warranty on all functionality
  • Ongoing support options available

Cost Savings and ROI

Clients report saving up to 30 hours per month per manager by automating reporting, translating to thousands of dollars annually. For example, a mid-sized company with 10 sales managers can save over $50,000 per year in analyst time. Typical project investment ranges from $1,500 for a basic dashboard to $15,000 for a full analytical portal, with an average payback period of 3 months.

Timeline

A dashboard with 3–5 widgets (funnel, KPI cards, period dynamics) — 5–8 business days. A full analytical portal with many widgets, server-side aggregation, export, and access roles — 3–5 weeks. Order development — get a consultation on timelines and scope.

Additional resources: Vue.js and Chart.js are proven tools for dashboards.

Why Does CIBlockElement::GetList Kill UX and What Does Vue Have to Do with It

We’ve seen standard bitrix:catalog.section component reload the entire page on every filter click. Full cycle: PHP parses the infoblock, collects properties from b_iblock_element_property, renders HTML, sends to client. On a catalog with 50,000 SKU, this takes 800–1200 ms. Customer clicks three filters — three reloads, 3 seconds of waiting. In e-commerce, this directly leads to up to 20% conversion loss. Vue.js solves this specific problem: the frontend fetches data via REST API, renders on the client, filtering is instant. Bitrix remains the backend: content, catalog, orders, 1С exchange. Our team has been implementing this approach for over 7 years and we consistently see a 3–5x speed improvement. According to Vue.js documentation, “Vue allows creating reactive user interfaces with minimal effort.”

Vue.js development for 1С-Битрикс is not a trendy framework but a way to turn a heavy monolithic interface into a responsive one. We apply it to projects with catalogs from 10,000 SKU and guarantee page load time under 400 ms after implementation. Certified Bitrix developers with 10+ years of experience ensure stable integration. Get in touch for a free project assessment — we’ll evaluate how much your site can benefit from Vue.js development.

When Is Vue Justified?

Not every site needs a frontend framework. Vue is justified when standard Bitrix components cannot keep up. Main scenarios:

  • Catalogs with heavy filtering — catalog.smart.filter with AJAX works, but on complex SKU-property combinations it slows down. Vue + API = instant response. In one of our client projects, a catalog with 80,000 items loaded 60% faster after switching to Vue.
  • Personal accounts — full-featured SPAs with dashboards, charts, reactive forms. sale.personal.section looks outdated.
  • Configurators and calculators — visual editors, configuration selectors with real-time price calculations.
  • Real-time — chats, notifications, stock updates via WebSocket.
  • PWA — offline mode, push notifications, home screen installation.

How Does Vue.js Solve UX Problems in Bitrix?

Comparison: standard bitrix:catalog.section component filters 50,000 items in 800 ms + page reload. Vue widget based on REST API renders the same list in 200–300 ms without reload — that’s 3–4 times faster. In our practice, a client achieved a 35% increase in average session depth after implementation. Savings on server infrastructure can reach $3000 per month. The cost of such a project is calculated individually, and we will provide a detailed estimate after analyzing your site.

What Are the Three Architectural Approaches to Integrating Vue.js with Bitrix?

Island — Vue Widgets on Bitrix Pages

Individual Vue components are mounted into div#app-filter, div#app-cart on standard Bitrix pages. Routing and server-side rendering remain with Bitrix. Minimal intervention into the existing site.

Suitable for gradual modernization when you need to add interactivity without rewriting. A typical example is a reactive filter replacing catalog.smart.filter. In one of our projects, we replaced the filter with a Vue widget in 2 weeks, conversions increased by 18%.

SPA on Vue + Bitrix REST API

Frontend — a full-featured Vue application with Vue Router. Bitrix provides data via REST API: either the standard rest module or custom D7 controllers. Bitrix admin panel manages content; the editor sees no difference.

Ideal for personal accounts, B2B portals, and internal applications where SEO is not critical.

Nuxt.js + Bitrix as Headless CMS

Nuxt provides SSR/SSG for indexing. Bitrix is headless: it returns data via API and manages content. For stores and content-heavy sites where SEO is a priority. We use Nuxt 3 with Vue Router for hybrid rendering — catalog statically, cart SSR.

Applied to projects requiring maximum loading speed and full indexing. Savings on licenses and servers can be substantial.

What Bitrix REST API Features Matter for Vue Development?

This accounts for 70% of time when integrating Vue + Bitrix.

Standard REST Module

Infoblocks, catalog, cart (sale.basket.*), orders (sale.order.*), users — out of the box. Limitation: standard methods do not always cover custom logic. The catalog.product.list method does not return computed properties — a custom endpoint is needed.

Custom D7 Controllers

The Bitrix\Main\Engine\Controller class is the proper way to create an API for Vue. Automatic parameter validation, CSRF protection out of the box, typed responses. Not ajax.php with $_POST — that leads to injections.

namespace App\Controller;
use Bitrix\Main\Engine\Controller;

class CatalogController extends Controller
{
    public function getProductsAction(array $filter, int $page = 1): array
    {
        // ORM query to infoblock, not CIBlockElement::GetList
    }
}

Authorization and Caching

Authorization: OAuth 2.0 for SPA or session tokens. Rate limiting — via Bitrix\Main\Engine\Controller or nginx. Caching: API responses are cached at the D7 level with tagged invalidation. Product changed in infoblock — cache cleared by tag iblock_id_X. Without this, at 100 RPS the server will crash. We configure this in every project — guarantee of stability under load.

Example of configuring tagged caching for API:

use Bitrix\Main\Data\Cache;

$cache = Cache::createInstance();
$tag = 'iblock_id_' . $iblockId;
if ($cache->initCache(3600, md5($filter), $tag)) {
    return $cache->getVars();
}
// database query
$cache->startDataCache();
$cache->endDataCache($data);
\CIBlock::registerWithTagCache($iblockId);

Structure of Vue Application for Bitrix

  • Vue Router — lazy loading routes via defineAsyncComponent. Catalog does not pull in personal account code.
  • Pinia — state management: catalog, cart, user, filters. Modular store architecture. Vuex is legacy; new projects use Pinia.
  • Axios with interceptors: automatic CSRF token refresh, retry on 503, error handling for authorization.
  • Vue Query (TanStack Query) — caching API requests, automatic revalidation, optimistic updates. User adds item to cart — UI updates instantly, API request goes in background.

Catalog on Vue — Key Use Case Breakdown

The difference in UX is immediately noticeable. Specifics:

  • Filter — checkboxes, range sliders, select with search. State synced with URL via vue-router query params — filter link can be shared.
  • Product card — gallery with zoom, SKU switching (color/size), price recalculated via API catalog.product.offer.list, stock from catalog.store.product.list.
  • Virtual scrolling — vue-virtual-scroller renders only visible items. Catalog of 10,000 items works smoothly.
  • Smart search — debounced queries to search.title.search or ElasticSearch, autocomplete via dropdown. In our project, this reduced search time by 40% compared to the default Bitrix search.
  • Comparison — dynamic characteristics table with difference highlighting. Storage in Pinia + localStorage for persistence.

How We Implement Vue.js: Step-by-Step Plan

  1. Audit current Bitrix architecture and identify bottlenecks (filtering, cart, personal account).
  2. Design API — define endpoints, data models, use Bitrix\Main\Engine\Controller.
  3. Develop Vue widgets or SPA — build with Vite, Code Splitting, Pinia.
  4. Integrate with Bitrix — tagged caching, OAuth, error handling.
  5. Load testing (up to 100 RPS) and deploy with CI/CD.

Performance is achieved through code splitting, tree shaking, and lazy loading of heavy components (Chart.js, maps, WYSIWYG). Catalog page bundle is 80–120 KB gzip.

How Does Nuxt.js and SEO Preserve Indexing?

A pure Vue SPA returns an empty HTML with <div id="app"></div> to search engines. Google can render JS but with days-long delay. Yandex is unpredictable. Nuxt.js solves this:

  • SSR — server returns full HTML, after hydration works as SPA.
  • SSG — pages generated on nuxt generate, served from CDN. Maximum speed.
  • Hybrid mode — catalog static, cart and personal account SSR.
  • useHead() — dynamic title, description, Open Graph, Schema.org for each page.
  • Sitemap — @nuxtjs/sitemap, routes from Bitrix API. This ensures full indexing — our guarantee for top-5 Google ranking.

Approach Comparison and Timelines

Situation Recommended Approach Business Impact
Catalog 10,000+ SKU, complex filter Vue widgets 3–5x speedup, 15-25% conversion increase
B2B portal, personal account SPA on Vue Up to 70% server load reduction
Store with SEO priority Nuxt.js + headless 100% page indexing, 0.8s load speed
Approach Timelines Deliverables
Vue widgets (2–5 components) 1–3 weeks Reactive elements on existing site
SPA for personal account 4–8 weeks Vue application + API on D7 controllers
Catalog on Vue + Bitrix API 4–10 weeks Filtering, cart, comparison without reloads
Nuxt.js + Bitrix headless 6–12 weeks SSR/SSG, full functionality, SEO

Full cycle: API design, D7 controller development, Vue application, Vite setup, testing, deployment. Code is reviewed, tested, documented — not "build and forget." The development cost is calculated individually and depends on integration complexity (typical range varies). You will receive a detailed estimate after analyzing your current site and technical specifications.

Common Mistakes When Integrating Vue.js and Bitrix

  1. Using ajax.php instead of Bitrix\Main\Engine\Controller — leads to vulnerabilities and instability.
  2. Lack of tagged API caching — server cannot handle high load.
  3. Ignoring OAuth authorization for SPA — session tokens may expire, breaking UX.
  4. Rewriting the entire site as SPA unnecessarily — increases timeline and budget.
  5. Incorrect Nuxt SSR configuration — slow page generation on backend.
Detailed technical considerations
  • Script loading order: Bitrix core scripts must not conflict with Vue. Use window.BX24 only after Vue app is mounted.
  • EventBus pattern: For cross-widget communication, prefer Pinia over $emit chains.
  • Error handling: Wrap REST calls in a global Axios interceptor that retries on 503 and logs to Bitrix admin log.

What We Deliver and Our Guarantees

  • API documentation (Swagger/OpenAPI) for integration with your backend.
  • Code repository access and CI/CD pipeline.
  • Team training on Vue component usage and maintenance.
  • 1 month post-release support — stability guarantee.
  • Code complies with PSR-12 and Bitrix\Main\Engine\Controller standards.

Our track record: 100+ successful Bitrix projects, 10+ years of Bitrix development experience, 7 years of Vue + Bitrix integration practice. We deliver turnkey solutions — from a simple filter widget to a full Nuxt.js headless store.

Order Vue.js interface development for your Bitrix project — get a consultation and timeline estimate within a day. Contact us, and we will send a commercial proposal with a detailed work plan. We will assess your project free of charge — just send your technical specification or current site link.