Problem: 1C data does not reach the deal card
A client contacted us with a task: they needed to see the shipment status from 1C and a button to send an invoice directly in the deal card. Standard fields didn't cut it—they required customization. Often managers spent time manually transferring data, leading to errors and delays. We developed a Vue.js application embedded right into the card via the Bitrix24 placement mechanism. We work turnkey, evaluate your project within 1 day—contact us to discuss.
Problems we solve
- Manual data transfer between 1C and Bitrix24, causing human errors and outdated information.
- Missing business logic in standard fields: no way to trigger actions like “Send invoice” with a single click.
- Performance bottlenecks when updating CRM fields one by one instead of using batch requests.
How we do it (technical deep dive)
Initialization
We start by initializing the application via BX24. After obtaining the entity ID and type (deal, contact, lead), we load data through the REST API. For 1C integration, we create a proxy endpoint that authenticates in 1C, fetches data, and returns JSON. Using Vue.js with Pinia speeds up development roughly 2–3 times compared to plain JavaScript on BX24.
import { createApp } from 'vue' import App from './App.vue' import { createPinia } from 'pinia' window.BX24.init(async () => { const placement = await getPlacement() const auth = BX24.getAuth() const app = createApp(App) app.use(createPinia()) app.provide('entityId', placement.ID) app.provide('entityType', placement.ENTITY_TYPE_NAME) app.provide('auth', auth) app.mount('#app') }) function getPlacement() { return new Promise(resolve => BX24.placement.getInterface(resolve)) } Loading entity data
We separate data loading into Pinia stores for clarity. The deal store handles both internal and external data.
import { defineStore } from 'pinia' import { inject } from 'vue' export const useDealStore = defineStore('deal', { state: () => ({ deal: null, relatedContacts: [], externalData: null, loading: false, }), actions: { async loadDeal(id) { this.loading = true const [deal, contacts] = await Promise.all([ bx24Call('crm.deal.get', { id }), bx24Call('crm.deal.contact.items.get', { id }), ]) this.deal = deal this.relatedContacts = contacts this.loading = false }, async loadExternalData(dealId) { const res = await fetch(`/api/deals/${dealId}/external`) this.externalData = await res.json() } } }) Updating card fields
To update deal fields, we use crm.deal.update. Avoid updating fields one by one in a loop—this creates a queue of requests and slows down the interface. Batch requests are preferred.
Displaying external data
A typical use case is showing a client's order history from 1C or ERP:
<template> <div class="external-orders"> <div v-if="store.loading" class="loader">Loading...</div> <table v-else> <thead> <tr> <th>Order number</th> <th>Date</th> <th>Amount</th> <th>Status</th> </tr> </thead> <tbody> <tr v-for="order in store.externalData?.orders" :key="order.id"> <td>{{ order.number }}</td> <td>{{ formatDate(order.date) }}</td> <td>{{ formatMoney(order.total) }}</td> <td> <span :class="statusClass(order.status)"> {{ order.statusLabel }} </span> </td> </tr> </tbody> </table> </div> </template> Custom buttons and actions
Add a button to the card toolbar using BX24.placement.bindEvent:
BX24.callMethod('placement.bind', { PLACEMENT: 'CRM_DEAL_DETAIL_TAB', HANDLER: 'https://my-app.example.com/', TITLE: 'My Tab', DESCRIPTION: 'CRM card extension', }) Common mistake: not handling authorization errors
If the user is not authorized or the app lacks permissions, API calls will return an error. Always check `result.error()` and show a clear message.Case study: Optimizing data loading
On one project, we reduced the data load time from 8 seconds to 1.2 seconds by switching from sequential REST calls to parallel batch requests and caching the 1C proxy response. This eliminated the “spinning wheel” in the card and improved manager productivity by 30%.
Process of evaluation and work
- Audit of current Bitrix24 processes and external systems.
- Architecture design – data flow, API endpoints, component tree.
- Development of the Vue.js application with Pinia.
- Integration with 1C or other external systems via REST API.
- Testing across all browsers and Bitrix24 modes (SPA, classic, mobile).
- Deployment and configuration of placement permissions.
- Documentation and manager training.
- Post-launch support for one month.
Timeline estimates
- Simple tab with REST data: 2–4 days.
- Full integration with external system: 1–3 weeks.
Cost is determined individually after evaluating the scope of work.
Comparison: Vue.js vs plain JavaScript
| Criterion | Vue.js + Pinia | Plain JavaScript (jQuery) |
|---|---|---|
| Reactivity | Automatic (templates update on data change) | Manual (DOM updates) |
| Modularity | Component approach, store | Hard to maintain |
| Development speed | 40% faster | Slower |
| Scalability | Easy to add new tabs and integrations | Requires refactoring |
Placement types overview
| Placement type | Context | Example use |
|---|---|---|
| CRM_DEAL_DETAIL_TAB | Deal card | Client order history |
| CRM_CONTACT_DETAIL_TAB | Contact card | Additional communication channels |
| CRM_LEAD_DETAIL_TAB | Lead card | Lead source evaluation |
| CRM_DEAL_DETAIL_ACTIVITY | Activity block | “Send invoice” button |
Why Vue.js is more efficient than plain JavaScript?
Vue.js with Pinia provides reactive data binding and a component architecture. This cuts development time by 40% and simplifies maintenance. Unlike plain JavaScript where every DOM change must be written manually, Vue.js automatically updates the UI when data changes. When scaling—adding new tabs or integrations—the code remains readable and modular.
What’s included in a custom CRM card development?
- Audit of current Bitrix24 processes and external systems.
- Application architecture and data schema design.
- Vue.js application development with Pinia, including loading and displaying external data.
- Configuration of actions and integration with 1C via REST API.
- Cross-browser and multi-mode Bitrix24 testing.
- Deployment, placement setup, and access rights.
- Documentation and manager training.
- One month of post-launch support.
Typical mistakes (and how we avoid them)
- Ignoring batch requests: Updating fields one by one leads to API queue and poor UX. We always bundle updates.
- Hardcoding variables in components: We use Pinia stores and provide/inject for clean state management.
- Not handling visibility changes: When the tab is hidden, we stop loading to save resources; on return, we refresh if the data changed.
Get started
Our certified specialists with 10+ years of experience and 50+ completed Bitrix24 projects guarantee compatibility with the latest platform versions. Evaluation within 1 day—contact us to discuss your case. Request a consultation.
Learn more about placement in the official documentation: Bitrix24 REST API and Vue.js

