Розробка віджетів для Бітрікс24
Класична ситуація: CRM вже використовується, всі угоди ведуть менеджери, але потрібно додати на картку угоди блок з даними із зовнішньої системи — наприклад, залишки на складі з ERP або статус доставки з транспортної компанії. Штатними засобами це не реалізувати, потрібен віджет через REST API та механізм вбудовування UI Extensions. Ми в нашій компанії регулярно вирішуємо такі завдання: інтеграція ERP, синхронізація статусів доставки, відображення фіскальних чеків з ОФД прямо в картці ліда. За роки роботи ми виробили чіткий підхід до розробки віджетів: від аудиту бізнес-процесів до викладки в маркетплейс. У цій статті ділимося практичними напрацюваннями.
Віджети в Бітрікс24 — окремий тип застосунків, які рендеряться всередині інтерфейсу порталу через iframe або JS SDK. В останніх версіях порталу Bitrix активно розвиває концепцію UI Extensions як більш продуктивну та зручну альтернативу класичним iframe-віджетам. Розберемося, що вибрати під конкретне завдання і як все влаштовано зсередини.
Як вибрати між iframe та UI Extensions?
| Критерій |
iframe-віджет |
UI Extensions |
| Сумісність |
Всі версії Бітрікс24 |
Портал свіжих версій (з підтримкою @bitrix24/b24jssdk) |
| Продуктивність |
Завантаження окремої сторінки |
Компоненти завантажуються швидше, шина подій пряма |
| Крос-доменні обмеження |
Потрібен CSP та SameSite |
Авторизація через postMessage |
| Складність розробки |
Нижча, простіше дебаг |
Вища, потрібен TypeScript |
Які типи віджетів та місця вбудовування існують?
Бітрікс24 підтримує кілька механізмів вбудовування:
- Placement API (BX24.placement.call) — класичний спосіб: застосунок реєструє placement, Бітрікс24 відображає його в потрібному місці інтерфейсу.
- UI Extensions — набір готових компонентів (Button, Dialog, Loader, Alert), доступних через
@bitrix24/b24jssdk.
- Slider — відкриття довільного URL у бічній панелі через
BX24.openApplication().
Актуальні плейсменти реєструються при встановленні застосунку через метод app.option.set та зберігаються в таблиці b_app_option. Список доступних місць вбудовування:
| Placement |
Де відображається |
| CRM_DEAL_DETAIL_TAB |
Вкладка на картці угоди |
| CRM_LEAD_DETAIL_TAB |
Вкладка на картці ліда |
| CRM_CONTACT_DETAIL_ACTIVITY |
Активність у таймлайні контакту |
| TASK_VIEW_TAB |
Вкладка в завданні |
| CALL_CARD |
Картка дзвінка |
| TELEPHONY_CALL_BEFORE_ANSWER |
До відповіді на дзвінок |
| TOP_MENU_ITEM |
Пункт верхнього меню |
Кожен placement передає у віджет контекстну інформацію: ID сутності, тип, права доступу. Детальніше про плейсменти читайте в офіційній документації.
Як влаштований iframe-віджет?
Типовий віджет складається з двох частин: обробника на сервері (endpoint, який поверне HTML сторінки віджета) та клієнтського коду всередині iframe.
Ініціалізація в клієнтському коді:
BX24.init(() => {
const placement = BX24.placement.info();
const dealId = placement.options.ID;
BX24.callMethod('crm.deal.get', { id: dealId }, (result) => {
if (result.error()) {
console.error(result.error());
return;
}
renderWidget(result.data());
});
});
Висота iframe — часта проблема. Бітрікс24 не робить iframe резиновим автоматично. Після рендеру контенту потрібно явно викликати:
BX24.fitWindow(() => {
// callback після зміни висоти
});
Якщо цього не зробити — віджет обріжеться або з'явиться внутрішній скролбар.
Чому UI Extensions швидше?
В останніх версіях порталу рекомендується використовувати @bitrix24/b24jssdk. Він дає типізований доступ до REST API прямо з iframe:
import { initializeB24Frame, B24Frame } from '@bitrix24/b24jssdk';
const $b24 = await initializeB24Frame();
const profile = await $b24.fetchProfile();
const result = await $b24.callMethod('crm.deal.list', {
filter: { ASSIGNED_BY_ID: profile.id },
select: ['ID', 'TITLE', 'STAGE_ID']
});
SDK бере на себе авторизацію (OAuth токен передається автоматично через postMessage), не потрібно зберігати client_secret на клієнті. UI Extensions запускається на 30% швидше, ніж iframe-віджет, завдяки прямій шині подій.
Реєстрація плейсменту та маніфест застосунку
Застосунок реєструє плейсменти при встановленні через хук OnAppInstall. Приклад у маніфесті:
{
"placements": [
{
"placement": "CRM_DEAL_DETAIL_TAB",
"handler": "https://myapp.example.com/widget/deal-tab",
"title": "Дані ERP",
"description": "Залишки та резерви по позиціях угоди"
}
]
}
Або програмно через REST:
POST /rest/placement.bind
{
"PLACEMENT": "CRM_DEAL_DETAIL_TAB",
"HANDLER": "https://myapp.example.com/widget/deal-tab",
"TITLE": "Склад"
}
Чому важлива безпека OAuth?
Всі запити від iframe до сервера повинні передавати AUTH_ID (короткоживучий токен, 1 година) або використовувати REFRESH_TOKEN для його оновлення. Ніколи не зберігайте client_secret у клієнтському коді — тільки на сервері.
Валідуйте вхідний event з postMessage:
window.addEventListener('message', (event) => {
if (event.origin !== 'https://your-portal.bitrix24.ru') return;
// обробка
});
OAuth — ключовий елемент безпеки. Досвід показує, що більшість помилок при розробці віджетів пов'язані з неправильною обробкою токенів. Детальніше про OAuth читайте на Wikipedia.
Типові помилки та їх вирішення
- Content Security Policy (CSP) Бітрікс24 обмежує
frame-ancestors. Ваш домен застосунку повинен бути в білому списку, що налаштовується автоматично при публікації в Маркеті або реєстрації локального застосунку.
- Повільна ініціалізація BX24.init() — якщо віджет завантажується довше 3 секунд, користувачі переключаються на іншу вкладку. Оптимізація: завантажуйте bx24.js через CDN, робіть скелетон-лоадер до отримання даних.
- Крос-доменні cookies — для сесійної авторизації свого бекенду використовуйте SameSite=None; Secure, інакше браузер заблокує куки всередині iframe.
Якщо ви зіткнулися з будь-якою з цих проблем — напишіть нам. Наші сертифіковані спеціалісти допоможуть діагностувати та усунути несправність. Зв'яжіться з нами для безкоштовної оцінки проєкту.
Що входить у роботу
- Аудит поточної CRM та інтеграційних сценаріїв
- Проектування архітектури віджета з урахуванням безпеки
- Реалізація та тестування в кількох браузерах (Chrome, Firefox, Safari, мобільні застосунки)
- Інтеграція із зовнішніми системами (ERP, ОФД, транспортні компанії)
- Документація зі встановлення та супроводу
- Навчання адміністраторів порталу
Ми даємо гарантію на всі виконані роботи. Тому при розробці ми використовуємо лише перевірені рішення та багаторічний досвід.
Терміни розробки
| Тип віджета |
Обсяг робіт |
Термін |
| Простий інформаційний віджет (читання даних CRM) |
S |
1–2 дні |
| Інтерактивний віджет із записом у CRM |
M |
3–5 днів |
| Віджет з інтеграцією зовнішньої системи |
L |
1–2 тижні |
| Комплект віджетів (5+ плейсментів) |
XL |
2–4 тижні |
Основний час йде не на сам віджет, а на налаштування OAuth-авторизації, обробку edge-кейсів (прострочений токен, портал в іншому датацентрі) та тестування в кількох браузерах — Бітрікс24 підтримує Chrome, Firefox, Safari та мобільні застосунки з різною поведінкою iframe.
Замовте розробку віджета вже сьогодні. Оцінимо ваш проєкт безкоштовно. Зв'яжіться з нами, щоб обговорити деталі.
Розробка та налаштування модулів 1С-Бітрікс
Головна пастка Бітрікса — init.php. Засунули туди обробник OnBeforeIBlockElementUpdate, потім ще один — через рік файл на 2000 рядків, і при кожному хіті вся ця купа виконується. Ми переносимо бізнес-логіку в повноцінні модулі з D7 ORM, власними таблицями та адміністративним інтерфейсом. Модуль можна вимкнути, перенести на інший проєкт, покрити тестами — з init.php нічого з цього не вийде. Досвід команди — 10+ років у Бітрікс, сертифіковані спеціалісти, гарантія на код 6 місяців. Замовте консультацію — розповімо, як перевести legacy-код у модульну архітектуру.
Як модульна архітектура підвищує продуктивність?
Чому init.php — найгірше місце для бізнес-логіки?
Init.php не підтримує автозавантаження класів, не має ізольованого простору імен, не піддається модульному тестуванню і не вимикається без правки самого файлу. Кожен обробник, написаний там, спрацьовує на кожному запиті, навіть якщо він не потрібен. У модулі ви реєструєте обробника через EventManager, і він виконується тільки при настанні події. Різниця в продуктивності — до 3 разів при 10+ обробниках.
Стандартні модулі: типові проблеми та рішення
Інформаційні блоки. Архітектура ІБ — перше, що ми рев'юїмо на будь-якому проєкті. Класична помилка: один інфоблок каталогу з 80 властивостями, з яких 30 — множинні. Таблиця b_iblock_element_property роздувається до мільйонів рядків, CIBlockElement::GetList на фільтрації за трьома властивостями йде в повне сканування. Переносимо довідники в Highload-блоки, прибираємо множинні властивості де можна, проєктуємо структуру з прицілом на те, що каталог виросте в 5 разів.
Інтернет-магазин (sale). Бізнес-правила кошика — окрема історія. Налаштовуємо пріоритети знижок, щоб дві акції не дали 60% замість 30%, підключаємо платіжні обробники, прописуємо кастомну валідацію через OnSaleOrderBeforeSaved.
Пошук. Вбудований модуль search з морфологією працює до 10–15 тисяч елементів. Далі — Elasticsearch. Налаштовуємо через API модуля пошуку Бітрікс, індексуємо через CSearchFullText або кастомні індексатори.
Highload-блоки для довідників, логів, користувацьких даних — замість роздутих ІБ. Прямі запити через Bitrix\Highloadblock\HighloadBlockTable, власні таблиці замість EAV-структури стандартних інфоблоків. Мільйон записів — без деградації.
Поштові події. Налаштування — не лише шаблони в b_event_message. Головне — SPF, DKIM, DMARC на DNS, інакше транзакційні листи летять у спам. Перевіряємо доставність, налаштовуємо bounce-обробку.
Проектування інфоблоків для продуктивності
Використовуємо Highload-блоки для довідкових даних (кольори, розміри, виробники), які не беруть участі в складних вибірках. Для торгових пропозицій — окремий інфоблок з прив'язкою через IBLOCK_ELEMENT_PROPERTY. Увімкнемо INDEX_PROPERTY для часто фільтрованих властивостей. Кешування теговане: при зміні елемента скидається лише пов'язаний кеш. Highload-блоки обробляють до 10 разів швидше, ніж інфоблоки з множинними властивостями, на об'ємах від 100 000 записів.
Розробка кастомних модулів
Кожен модуль — за структурою /local/modules/vendor.modulename/:
-
install/index.php — клас встановлення, створення таблиць через $DB->RunSQLBatch()
-
lib/ — класи D7 ORM, спадкоємці Bitrix\Main\ORM\Data\DataManager
-
admin/ — адміністративні сторінки через CAdminList, CAdminForm
-
include.php — автозавантаження, реєстрація обробників через EventManager::getInstance()->registerEventHandler()
- REST API endpoints через
\Bitrix\Rest\RestManager
Модуль реєструється в системі, з'являється у списку «Встановлені рішення», має свої налаштування в /bitrix/admin/settings.php?mid=vendor.modulename. Його можна вмикати, вимикати, оновлювати через UpdateSystem або свій механізм міграцій.
Приклади реалізованих завдань:
- Управління акціями — візуальний конструктор умов через
CAdminCalendar, таймери через агенти (CAgent::AddAgent), аналітика ефективності у зв'язці з модулем sale
- Калькулятор вартості — React-віджет на фронті, REST API у модулі, формули зберігаються в Highload-блоці
- Система бронювання — real-time календар, блокування через
$DB->StartTransaction() / $DB->Commit() при одночасних запитах, синхронізація з channel manager через webhook
Компоненти та композитний кеш
Кастомізація компонентів — через result_modifier.php і component_epilog.php, не через правку template.php стандартного шаблону. Так ядро оновлюється безболісно.
Композитний кеш (технологія «Композитний сайт») — сервер віддає готовий HTML, минаючи PHP-роутинг. Динамічні зони (кошик, авторизація) підвантажуються через CBitrixComponent::setFrameMode(true) та AJAX. TTFB падає до 30–50 мс. Але є нюанси: не всі компоненти сумісні, $APPLICATION->ShowPanel() ламає композит, потрібна акуратна розмітка <div id="bx-composite-...">.
Маркетплейс: аудит перед встановленням
Перед встановленням модуля з маркетплейсу — обов'язковий аудит. Перевіряємо: SQL-запити без підготовлених виразів (привіт, SQL-ін'єкції), пряме звернення до $_REQUEST без фільтрації, використання застарілого API старого ядра замість D7, конфлікти з модулем композитного кешування. Модуль без оновлень більше року та з парою десятків встановлень — швидше за все, проблема на найближчому оновленні PHP. Типовий випадок: модуль викликає CIBlockElement::GetList з нескинутим кешем — сайт падає при 5000 елементів.
Міграція на D7
При оновленні PHP або переході на нову редакцію — рефакторинг застарілих викликів:
-
CIBlockElement::GetList() → Bitrix\Iblock\Elements\ElementTable::getList()
-
CSaleOrder::GetList() → Bitrix\Sale\Order::getList()
-
CModule::IncludeModule() → Bitrix\Main\Loader::includeModule()
Тестування на staging, відкат через git при проблемах.
Згідно з офіційною документацією 1С-Бітрікс, D7 ORM є рекомендованим засобом для роботи з даними, забезпечуючи безпеку типів і автогенерацію запитів.
Порівняння підходів: Init.php vs Модуль
| Критерій |
Init.php |
Модуль з D7 ORM |
| Продуктивність |
Виконується на кожному хіті |
Виконується тільки при події |
| Тестованість |
Немає автозавантаження, тести неможливі |
Повна підтримка PHPUnit |
| Підтримуваність |
Кодова база зростає безконтрольно |
Ізольована структура, версіонування |
| Міграції |
Немає |
Власні таблиці, керування через install |
| Кешування |
Не підтримує автоінвалідацію |
Теговане кешування, скидання за подією |
Вартість та склад розробки модулів
Що входить у розробку модуля?
- Технічне завдання та архітектурна схема
- Код з дотриманням PSR-4 та код-стайлу Бітрікс
- Unit-тести (PHPUnit) на бізнес-логіку
- Інтеграційні тести на події та REST API
- Документація з встановлення, налаштування та API
- Передача доступів до репозиторію та документації
- Навчання адміністраторів роботі з модулем
- Гарантійна підтримка 6 місяців
Орієнтовні терміни та складність:
| Складність |
Приклади |
Терміни |
| Простий |
Віджет зворотного дзвінка, банерна система, простий калькулятор |
3–5 днів |
| Середній |
Система бронювання, конфігуратор товарів, модуль відгуків з модерацією |
1–2 тижні |
| Складний |
Мультирегіональність, кастомна програма лояльності, інтеграція з ERP |
2–4 тижні |
| Enterprise |
Маркетплейс-платформа, складні бізнес-процеси з безліччю ролей |
1–3 місяці |
Вартість розраховується індивідуально — зв'яжіться з нами для оцінки вашого проєкту.
Тестування модулів
Unit-тести через PHPUnit покривають бізнес-логіку: розрахунок знижок, валідацію, формування документів. Моки для Bitrix\Main\Application::getConnection() дозволяють тестам не залежати від БД. Інтеграційні тести перевіряють обробники подій на реальній базі — OnAfterIBlockElementAdd, OnSaleOrderSaved та інші. REST API endpoints тестуємо через curl або PHPUnit HTTP-клієнт. Критично для модулів, що працюють з b_sale_order, b_catalog_price — де помилка коштує грошей.
Сумісність перевіряється на PHP 7.4, 8.0, 8.1, 8.2 та редакціях: Стандарт, Малий бізнес, Бізнес. Перевіряємо конфлікти з популярними модулями маркетплейсу — вони люблять перехоплювати ті самі події. Навантажувальне тестування: заміри на 10K, 100K, 1M записів, профілювання через Xdebug на предмет витоків пам'яті та N+1 запитів.
Приклади з практики
Модуль акцій для мережі електроніки. Штатні знижки модуля sale не покривали сценарії «2+1», подарунок при покупці від суми, комбіновані умови. Зібрали візуальний конструктор: маркетолог створює правила через drag-and-drop, без тікетів у розробку. Календар акцій, автодеактивація через агенти, аналітика у прив'язці до b_sale_order — конверсія, середній чек, кількість застосувань. Час запуску нової акції впав з двох днів до півгодини.
Калькулятор для будівельників. Параметри (площа, матеріали, поверховість) → формула → попередній кошторис → заявка в CRM через CRest::call('crm.lead.add'). Регіональні коефіцієнти та сезонні націнки — з Highload-блоку, ціни матеріалів — з обміну з 1С. Кількість цільових заявок зросла на третину: клієнти бачать розбивку за статтями до дзвінка менеджеру.
Бронювання для мережі готелів. Real-time доступність через AJAX-запити до кастомної таблиці vendor_booking_slots, розрахунок тарифів за сезоном, синхронізація з Booking.com через channel manager API. Блокування номера при одночасному бронюванні — через SELECT ... FOR UPDATE у транзакції. Таймзони обробляються через \DateTimeZone — гість із Владивостока та менеджер із Москви бачать одну картину.
Оцінимо проєкт за 1 день. Пишіть — розповімо, що входить у розробку під ключ. Зв'яжіться з нами для консультації за вашим проєктом. Замовте розробку модуля під ключ — отримайте готове рішення з документацією та підтримкою.