Перейти к содержимому
Разработка и REST

Виджеты Битрикс24: как встроить внешний сервис в портал

8 июня 2026 г.9 минут

Как разработать виджет для Битрикс24, который встраивается прямо в интерфейс CRM: карточка сделки, левое меню, детальная страница.

Виджет в Битрикс24 — это встроенный в интерфейс портала iframe с вашим внешним сервисом: вкладка на карточке сделки, панель в разделе CRM, кнопка в верхнем меню. В отличие от обычного REST-вызова снаружи, виджет живёт внутри интерфейса пользователя и должен общаться с порталом через JS-библиотеку BX24.js, а не только через HTTP. Разберём весь путь: от регистрации точки встраивания до передачи данных между iframe и порталом и типичных ошибок с авторизацией внутри виджета.

Точки встраивания (placement) и их регистрация

Каждое место интерфейса, куда можно встроить виджет, называется placement и имеет свой код: CRM_DEAL_DETAIL_TAB (вкладка на карточке сделки), CRM_DEAL_DETAIL_TOOLBAR (кнопка в панели инструментов сделки), CRM_CONTACT_DETAIL_TAB, SETTINGS_MENU и десятки других. Регистрация выполняется методом placement.bind: указываете PLACEMENT, HANDLER (URL вашего iframe-приложения) и опционально TITLE. После регистрации виджет автоматически появляется в соответствующем месте интерфейса у всех пользователей портала, установивших приложение.

POST /rest/1/xxxxxxxxxxxxxxxx/placement.bind.json

{
  "PLACEMENT": "CRM_DEAL_DETAIL_TAB",
  "HANDLER": "https://yourservice.example.com/widget/deal-panel",
  "TITLE": "Проверка контрагента"
}

// Список доступных точек:
// GET /rest/1/xxxxxxxxxxxxxxxx/placement.list.json

Что приходит в iframe при открытии виджета

Когда пользователь открывает вкладку с виджетом, Битрикс24 делает POST-запрос на HANDLER (или GET, в зависимости от настройки) с параметрами PLACEMENT, PLACEMENT_OPTIONS (JSON с контекстными данными — например, ID сделки, на карточке которой открыт виджет) и полным набором авторизационных данных AUTH_ID, REFRESH_ID, member_id, DOMAIN. Эти данные позволяют сразу, без отдельного OAuth-обмена, делать REST-запросы от имени текущего пользователя, открывшего вкладку — именно поэтому виджет не требует повторного логина.

BX24.js: мост между iframe и порталом

Внутри самого iframe подключается скрипт https://api.bitrix24.com/api/v1/ (или локальный //api.bitrix24.com/b24.js), инициализируется вызовом BX24.init(callback), после чего становятся доступны методы BX24.callMethod (для REST-вызовов без ручной передачи токена — библиотека сама подставляет авторизацию текущей сессии), BX24.placement.info() (получить контекст размещения — ID сущности, на которой открыт виджет), BX24.resizeWindow (подогнать высоту iframe под контент) и BX24.close (закрыть слайдер, если виджет открыт как модальное окно).

BX24.init(function(){
  var info = BX24.placement.info();
  var dealId = info.options.ID;

  BX24.callMethod('crm.deal.get', { id: dealId }, function(result){
    if(result.error()){
      console.error(result.error());
      return;
    }
    document.getElementById('deal-title').innerText = result.data().TITLE;
    BX24.resizeWindow(document.body.scrollWidth, document.body.scrollHeight);
  });
});

Авторизация внутри виджета: не полагайтесь только на клиент

Критичная ошибка — доверять данным, пришедшим в iframe через query-параметры, без проверки на сервере. Любой пользователь может подделать параметры в URL своего браузера и попытаться открыть виджет с чужим DEAL_ID. Работоспособная схема: сервер вашего приложения на каждый входящий запрос виджета проверяет подпись/токен через собственный REST-вызов к порталу (например, profile или crm.deal.get с полученным AUTH_ID) и убеждается, что пользователь действительно имеет право видеть эту сущность, а не просто доверяет тому, что передал клиентский JS.

Виджеты с сохранением состояния между открытиями

Виджет открывается заново при каждом переходе на вкладку — если нужно сохранять пользовательские настройки (например, выбранный шаблон документа), храните их не в localStorage браузера (это ненадёжно и не переносится между сотрудниками), а на своей стороне, привязав к паре member_id (идентификатор портала) + ID сущности + ID пользователя. Метод BX24.placement.info() всегда возвращает актуальный контекст, поэтому логику подгрузки состояния стройте вокруг этих трёх ключей.

Несколько виджетов на одной карточке — конфликты и порядок

Если на карточке сделки зарегистрировано несколько вкладок от разных приложений, их порядок определяется очерёдностью установки и не настраивается через API напрямую — учитывайте это при проектировании UX, не рассчитывайте, что ваша вкладка будет первой. Также помните, что каждый виджет — это отдельный iframe с собственным идентификатором сессии; данные между несколькими вашими виджетами на одной странице не передаются напрямую, обмен возможен только через ваш же backend.

  • CRM_DEAL_DETAIL_TAB / CRM_LEAD_DETAIL_TAB / CRM_CONTACT_DETAIL_TAB — вкладки на карточках CRM
  • CRM_DEAL_DETAIL_TOOLBAR — кнопка в панели инструментов карточки
  • CRM_DEAL_LIST_TOOLBAR — кнопка над списком сделок (массовые операции)
  • SETTINGS_MENU — пункт в общих настройках портала
  • TASKS_TASK_DETAIL_TAB — вкладка на карточке задачи
  • CALL_CARD — встраивание в карточку звонка (для интеграций телефонии)

Отладка виджета: типичные проблемы

  1. 1.Виджет не появляется на карточке — проверьте, что placement.bind реально выполнился (placement.get вернёт список активных привязок) и что HANDLER отвечает 200 на прямой запрос
  2. 2.Виджет открывается пустым — почти всегда проблема в CSP или в том, что BX24.init не был вызван до попытки использовать BX24.callMethod
  3. 3.Высота iframe не совпадает с контентом — забыт вызов BX24.resizeWindow после динамической подгрузки данных
  4. 4.Авторизация протухает через час работы с открытой вкладкой — нужно обрабатывать expired_token и делать повторный BX24.init или обновление токена на сервере
Правило серверной перепроверки. Никогда не выполняйте чувствительные операции (запись в CRM, доступ к платёжным данным) только на основании параметров, пришедших в iframe от клиента. Любой query-параметр в URL виджета можно подделать вручную в адресной строке — сервер обязан независимо подтвердить права пользователя через собственный вызов к REST API портала.

Курс школы: Вебхуки в Битрикс24 без программирования — от 9 990 ₽

Локальные виджеты против облачных

Если приложение работает как локальное (для одного портала), точки размещения регистрируются один раз в момент разработки. Если это публичное приложение из Маркета, регистрация должна выполняться программно в обработчике ON_APP_INSTALL — то есть каждый новый клиент получает виджеты автоматически при установке, без ручной настройки с вашей стороны. Соответственно, обработчик деинсталляции должен снимать привязки через placement.unbind, иначе после удаления приложения клиентом «мёртвые» вкладки могут оставаться видимыми до следующего обновления кеша интерфейса.

Виджет, который доверяет параметрам из URL без проверки на сервере, — это не интеграция с CRM, а дыра в безопасности с красивым UI поверх неё.

Производительность виджета и восприятие пользователем

Виджет, который загружается дольше полутора-двух секунд, воспринимается сотрудниками компании как «тормозящий Битрикс24» — хотя проблема на стороне вашего сервиса, репутационные издержки достаются платформе и в конечном счёте вам как разработчику. Оптимизируйте: не делайте синхронные тяжёлые REST-запросы к порталу до отрисовки хотя бы skeleton-интерфейса, кешируйте статичные данные (список полей, справочники) на своей стороне вместо повторного запроса при каждом открытии вкладки.

Слайдеры и модальные окна поверх интерфейса

Кроме статичных вкладок, виджет можно открыть как слайдер поверх текущего интерфейса методом BX24.openApplication или через кнопку в тулбаре с обработчиком, который открывает ваше приложение в модальном окне. Это удобно для разовых действий — «сформировать документ», «проверить дубликаты» — когда не нужна постоянная вкладка на карточке, а нужен разовый диалог с результатом. После завершения операции обязательно вызывайте BX24.close(), иначе слайдер останется висеть, и пользователю придётся закрывать его вручную, что выглядит как недоделанный интерфейс.

Взаимодействие виджета с полями карточки в реальном времени

Отдельная категория виджетов — не просто вкладки для просмотра, а инструменты, которые должны менять значения полей прямо на карточке без отдельного сохранения через отдельную кнопку. Для этого после вызова crm.deal.update из виджета стоит явно уведомить пользователя об успехе через простое сообщение в интерфейсе виджета, потому что сама карточка сделки не перезагружается автоматически — обновлённые данные в соседних полях интерфейса Битрикс24 подтянутся только после обновления страницы пользователем, и это стоит учитывать в UX, а не оставлять пользователя в недоумении, применились ли изменения.

Ограничения размера и стилизации iframe

Виджет — это ваш собственный HTML/CSS/JS внутри iframe, стили портала на него не распространяются, поэтому визуально он не обязан совпадать с темой Битрикс24, но для доверия пользователей стоит придерживаться нейтральной палитры и системных шрифтов, близких к интерфейсу платформы. Высота вкладки CRM_DEAL_DETAIL_TAB подстраивается под контент через BX24.resizeWindow, но ширина ограничена шириной родительского контейнера карточки — проектируйте адаптивную вёрстку, а не фиксированную ширину в пикселях, иначе на разных разрешениях экрана виджет будет обрезан или окружён пустым пространством.

Массовые операции через виджет над списком сущностей

Placement типа CRM_DEAL_LIST_TOOLBAR позволяет добавить кнопку прямо над списком сделок, которая получает не одну сущность, а массив выбранных ID через PLACEMENT_OPTIONS. Это удобно для сценариев вроде «отправить выбранные сделки на проверку во внешнюю систему одним кликом» — но важно закладывать в такой виджет собственную индикацию прогресса и обработку частичных сбоев: если из 40 выбранных сделок 3 не удалось обработать из-за ошибки внешнего сервиса, пользователь должен увидеть, какие именно, а не молчаливый общий успех или общий провал всей пакетной операции.

Обновление уже установленных виджетов

Если вы меняете HANDLER или добавляете новую точку размещения для уже установленного у клиентов приложения, повторный вызов placement.bind с тем же PLACEMENT и новым HANDLER обновляет привязку без переустановки приложения целиком. Это позволяет выкатывать новые версии виджета плавно, без необходимости просить клиентов переустанавливать интеграцию — но обязательно тестируйте обратную совместимость PLACEMENT_OPTIONS, потому что старые открытые вкладки в браузерах пользователей могут какое-то время обращаться к новой версии HANDLER с ожиданиями старого формата данных.

Что изучить дальше

Вебхуки в Битрикс24 без программирования

Заявка с сайта сама создаёт сделку, а данные из Битрикс24 уходят во внешний сервис — без программиста. 16 коротких уроков с готовыми шаблонами запросов, 4 практических задания и защита ключей.