We are still updating this page. Some data may be missing here — we will complete it shortly.
Goal
A frame app that gets real-time updates from Bitrix24 — for example, the badge counter goes up when a new chat message arrives or when a CRM activity changes hands. The Pull client multiplexes WebSocket and long-polling transports; you only see one callback.
Stack & Prerequisites
- Vue 3 + Vite (or Nuxt) running inside a Bitrix24 placement
@bitrix24/b24jssdk@^1.0.0- The portal must have the Pull module enabled (it is on every cloud and most on-premise installations)
pnpm add @bitrix24/b24jssdk
Full Example
src/components/PullPanel.vue:
<script setup lang="ts">
import { onBeforeUnmount, onMounted, ref } from 'vue'
import {
initializeB24Frame,
LoadDataType,
LoggerFactory,
useB24Helper,
type B24Frame,
type TypePullMessage
} from '@bitrix24/b24jssdk'
const logger = LoggerFactory.createForBrowser('PullPanel', import.meta.env.DEV)
const events = ref<Array<{ at: string, command: string }>>([])
let $b24: B24Frame | null = null
const {
initB24Helper,
destroyB24Helper,
usePullClient,
useSubscribePullClient,
startPullClient
} = useB24Helper()
function handleEvent(message: TypePullMessage) {
logger.info('pull', message)
events.value.unshift({
at: new Date().toLocaleTimeString(),
command: message.command
})
// Keep the visible log short.
if (events.value.length > 20) events.value.length = 20
}
onMounted(async () => {
$b24 = await initializeB24Frame()
// App + Profile are required so the helper can register a Pull channel.
await initB24Helper(
$b24,
[LoadDataType.App, LoadDataType.Profile],
'pull-panel-init'
)
usePullClient()
// Listen to events from the `crm` module. Use `'application'` (default) for
// your own app's custom events.
useSubscribePullClient(handleEvent, 'crm')
startPullClient()
})
onBeforeUnmount(() => {
destroyB24Helper()
$b24 = null
})
</script>
<template>
<section>
<h2>Live events</h2>
<ul v-if="events.length">
<li v-for="(event, index) in events" :key="index">
<code>{{ event.at }}</code> — {{ event.command }}
</li>
</ul>
<p v-else>Waiting for events…</p>
</section>
</template>
Run It
Open the app inside Bitrix24, then trigger a CRM event in another tab — drag a deal to a new stage, add an activity, change the responsible person. Within a second the event command (e.g. crm_deal_update) appears at the top of the list. The component keeps the last 20 events visible.
How It Works
useB24Helper()returns a closure over a singleB24HelperManagerinstance. It is not a Vue composable — it doesn't read Vue lifecycle hooks. You wire it intoonMounted/onBeforeUnmountyourself.initB24Helper($b24, dataTypes, requestId)loads the data the Pull client needs to register a channel. WithoutLoadDataType.AppandLoadDataType.Profilethe subsequentusePullClient()call throws.usePullClient()instantiates the Pull transport (WebSocket with long-polling fallback).useSubscribePullClient(handler, moduleId)registers your callback for that module.startPullClient()actually opens the connection — call it last.destroyB24Helper()tears down the transport and unregisters subscribers. Calling it on unmount prevents the WebSocket from leaking when the app slider closes.
Limitations
- The order must be
initB24Helper→usePullClient→useSubscribePullClient→startPullClient. CallinguseSubscribePullClientbeforeusePullClientthrowsPullClient is not initialized. The error is intentional — it surfaces wiring mistakes early. useB24Helper()returns one shared instance per closure. If you create a seconduseB24Helper()and callinitB24Helperagain, the second call re-uses the existing manager rather than building a new one.moduleIddefaults to'application'. To listen to portal modules ('crm','tasks','im', …) pass them explicitly. Subscribing to multiple modules requires multipleuseSubscribePullClientcalls.- Pull events are best-effort. They are great for "wake the UI up", not for "this is the source of truth". Always re-fetch via REST when the user takes an action that depends on freshness.
See also
- Recipe: Frame app skeleton — minimal frame app this builds on top of.
B24Frame— the iframe entry point.