Developing Vue.js Widgets for Bitrix24
Developing Vue.js Widgets for Bitrix24
Bitrix24 is not just a CRM. It is an open platform with a REST API, an application system, and a mechanism for embedding custom interfaces through widgets. A widget is a Vue.js application that opens inside the Bitrix24 interface and extends its functionality: adding buttons to CRM cards, displaying custom dashboards, integrating external services directly into the manager's interface.
This represents a fundamentally different level of working with Bitrix24 — not configuration, but platform extension.
Widget Embedding Types
Bitrix24 has several application embedding mechanisms:
Slider — the application opens in a side panel on top of the Bitrix24 interface. The most common type. Launched via a button in the portal's right panel, from a menu, or via BX24.openApplication().
CRM card embedding — a tab or block in a lead, deal, or contact card. Implemented via the REST event CRM_*_DETAIL_TAB. The widget receives the context of the open card (entity ID, type).
Context menu — a button in the context menu of a CRM entity list. Receives an array of selected IDs.
Embedded in the feed — custom type publications in the activity stream.
Telephony — buttons and interface in the call card.
Each embedding type is registered via rest_app_event when the application is installed. The configuration is stored on the Bitrix24 side; the widget code itself is hosted on an external server.
Vue Widget Architecture
A Vue widget for Bitrix24 is a Vue 3 application that:
- Is embedded in a Bitrix24 iframe (or opens as a slider).
- Interacts with Bitrix24 via the JS SDK (
BX24.js). - Works with data via the Bitrix24 REST API.
Initializing the BX24 SDK:
import { createApp } from 'vue';
import App from './App.vue';
document.addEventListener('DOMContentLoaded', () => {
BX24.init(() => {
const app = createApp(App);
app.provide('bx24', BX24);
app.mount('#app');
});
});
Getting context from a CRM card:
// In the component
const bx24 = inject('bx24');
const placement = bx24.placement.info();
// placement.options contains the ID of the open entity
const dealId = placement.options.ID;
// Request deal data via REST
bx24.callMethod('crm.deal.get', { id: dealId }, (result) => {
dealData.value = result.data();
});
Calling the REST API in batches — for efficient requests:
bx24.callBatch({
deal: ['crm.deal.get', { id: dealId }],
contacts: ['crm.deal.contact.items.get', { id: dealId }],
products: ['crm.deal.productrows.get', { id: dealId }],
}, (results) => {
deal.value = results.deal.data();
contacts.value = results.contacts.data();
products.value = results.products.data();
});
OAuth Application vs Webhook
For widgets that need to be installed at multiple clients — an OAuth application is developed with registration in the Bitrix24 Marketplace. For internal corporate use — a local application via webhook is sufficient.
The architectural difference is significant:
- Webhook — a static token, tied to a specific portal, requires no OAuth flow.
-
OAuth application — requires storing tokens (
access_token/refresh_token) on the application server side, token refresh logic, and installation via the Marketplace.
For corporate widgets (for a single company only) — webhook is simpler and faster. For a commercial product — OAuth.
Case Study: Delivery Cost Calculation Widget in Deal Card
Client — a logistics company. Task: managers need to see delivery costs directly in the Bitrix24 deal card, without switching to a separate calculation system.
Solution: a Vue widget as a tab in the deal card.
How it works:
- The widget opens in the deal card and reads the delivery address (custom field
UF_CRM_DEAL_DELIVERY_ADDRESS) and cargo weight (UF_CRM_DEAL_WEIGHT) from it. - The Vue application sends a request to the internal cost calculation API (REST service on Laravel).
- Displays a rate table: by transport type (road, air, rail), delivery times, and costs.
- The manager selects a suitable option — the "Save" button writes the cost to the deal field via
crm.deal.update.
Technical stack:
- Vue 3 + Composition API
- BX24.js SDK for Bitrix24 interaction
- Axios for API calculation requests
- Vite for bundling
- Application hosted on a separate host (
widget.company.ru), Bitrix24 opens it in an iframe
Development took 12 working days: configuring the application in Bitrix24, developing the Vue component, integrating with the calculation API, testing in a test portal, deployment.
Security Considerations
The widget opens in an iframe on a domain different from the Bitrix24 portal. Key considerations:
- CORS — the backend REST API must allow requests from the client's Bitrix24 portal domain.
-
Request verification — when using a webhook, request signatures must be verified via
application_token. -
iframe policies — the backend's
X-Frame-Optionsheader must allow embedding in the Bitrix24 domain.
Timeframes
Corporate widget (one embedding type, webhook) — 8–15 days: design, Vue component development, BX24 SDK integration, testing. OAuth application for the Marketplace with multiple embedding types — 3–8 weeks, including server side, OAuth flow, documentation, and passing the Marketplace review.
Bitrix24 is a closed system with limited interface extension points. But those points exist: embedded applications, custom tabs in CRM cards, widgets in the left panel, buttons in the feed. Developing widgets in Vue.js makes it possible to embed custom functionality into the Bitrix24 interface — calculators, selectors, dashboards, integration panels.
How Applications and Widgets Work in Bitrix24
Bitrix24 provides several embedding mechanisms:
Embedded Applications. The application opens in an iframe inside the Bitrix24 interface. Placed in the left navigation panel, in a popup, or as a separate tab. Communicates with Bitrix24 via the JS SDK (BX24.js).
CRM Card Widgets. Via CRM Detail Tab — a custom tab in a lead, deal, contact, or company card. Displayed as an iframe with your application, receives context (entity ID, data) via BX24.placement.info().
On-premise Bitrix24. For on-premise installations, additional embedding points are available via PHP hooks and custom components. But web applications via REST/iframe work everywhere — both in the cloud and on-premise.
Bitrix24 Marketplace. A widget can be published as an application in the Marketplace and used by other companies.
BX24.js SDK: Interacting with the Platform
A Vue widget communicates with Bitrix24 via BX24.js — the official JavaScript SDK. Key methods:
// Application initialization
BX24.init(() => {
// Get placement context
const placement = BX24.placement.info()
// placement.options.ID - CRM entity ID
// Call REST API
BX24.callMethod('crm.deal.get', { id: placement.options.ID }, (result) => {
if (result.error()) console.error(result.error())
else console.log(result.data())
})
})
// Resize iframe
BX24.fitWindow()
// Open user selection dialog
BX24.selectUser((user) => {
console.log(user.id, user.name)
})
In Vue 3, wrap BX24 in a composable:
// composables/useBX24.js
export function useBX24() {
const callMethod = (method, params) => new Promise((resolve, reject) => {
BX24.callMethod(method, params, (result) => {
if (result.error()) reject(result.error())
else resolve(result.data())
})
})
const placementInfo = () => BX24.placement.info()
return { callMethod, placementInfo }
}
Vue Widget Architecture
Standard project structure:
/src
/components # Widget UI components
/composables # useBX24, useDeals, useContacts
/stores # Pinia stores for state
/views # Widget pages/states
App.vue
main.js
/public
index.html # iframe entry point
The widget is built via Vite into static files and deployed to a server with HTTPS. Bitrix24 opens index.html in an iframe.
Important: Bitrix24 requires HTTPS for all embedded applications. Local development — via ngrok or a local SSL certificate.
Case Study: Cost Calculator Widget in Deal Card
Client — a transport company, Bitrix24 cloud. In the deal card, managers manually calculated transport costs: distance × rate × load factor × cargo type surcharge. They made errors, recalculated, and the amounts in deals diverged from actual invoices.
Task: a calculator widget in the deal card that automatically pulls data from deal fields (route, cargo type, weight), calculates the cost, and writes the result back to the deal field.
Implementation:
Placement: CRM_DEAL_DETAIL_TAB — custom tab in the deal card.
On opening, the widget:
- Gets the deal ID via
BX24.placement.info() - Pulls deal data via
crm.deal.get— route, cargo type, weight fields - Requests rates from its own API (the rate schedule was stored in an external database)
- Calculates cost in real time as parameters change
- "Apply" button writes the calculated amount back via
crm.deal.update
Calculator interface: Vue 3 + Pinia for state management, <Suspense> for the loading state while deal data is being retrieved.
Additionally: the widget showed the calculation history for this deal — stored in a custom field of type "string" as JSON.
After implementation, errors in deal amounts dropped to zero. Managers stopped keeping an Excel calculator next to the CRM.
Publishing and Deployment
Widget for a single company (not Marketplace):
- Create a "Local application" in Bitrix24 settings
- Specify the handler URL (address of the deployed index.html)
- Configure placements and access rights
- The developer receives
client_idandclient_secretfor OAuth
Deployment: static files on S3 + CloudFront or on a dedicated VPS with nginx. CI/CD via GitHub Actions: push to main → Vite build → deploy to server.
Timeframes
Simple widget (one CRM tab, reading/writing deal data) — 5–10 working days. Complex widget with its own backend, history, integration with external APIs — 15–30 working days.







