Код у застосунку
Майже все в міні-застосунку збирається без коду. Коли готових елементів і блоків не вистачає, свій код можна додати в трьох місцях:
| Де | Коли виконується | Для чого |
|---|---|---|
| Блок «JavaScript» | Коли сценарій дійшов до блоку | Дія за натисканням: скопіювати текст, відкрити посилання, порахувати значення, поговорити з мостом месенджера |
| Код застосунку | Один раз під час запуску, до першого екрана, і далі — за подіями | Лічильники аналітики, свої стилі, зовнішні віджети |
| «HTML-код» — елемент або весь екран | Поки екран відкритий | Своя верстка, калькулятор, віджет стороннього сервісу |
Код виконується на пристрої людини. Тому людина, яка розуміється на браузері, може побачити його й підробити те, що код надсилає на сервер. Не зберігайте в коді секретні ключі й обмежуйте, які змінні та теги код може змінювати, — про це нижче.
Блок «JavaScript»
Блок із категорії «Дані та логіка». Коли застосунок доходить до блоку, він виконує код і йде далі виходом «Виконано» або «Помилка».
| Налаштування | Що задає |
|---|---|
| «Код» | Тіло асинхронної функції: пишіть з await і об'єктом app. До 20 000 символів |
| «Час на виконання, секунд» | Від 1 до 60, за замовчуванням 10. Не встиг — сценарій піде виходом «Помилка», а сам код може допрацювати у фоні |
| «Змінна результату» | Що повернув return. Об'єкт запишеться як JSON |
| «Змінна помилки» | Текст помилки — для екрана після виходу «Помилка» |
| «Що може змінювати код» | Список дозволеного — див. нижче |


Підстановки {{ имя }} у коді не працюють: значення змінних читайте через app.variables.get().
Змінні, записані через app.variables.set(), і змінені теги йдуть на сервер разом із виходом блоку.
«Що може змінювати код»
Перемикач «Змінювати лише перелічене» ввімкнено в нового блоку. З ним сервер приймає від коду лише:
- змінні зі списку «Змінні»;
- теги зі списків «Теги контакту бота» і «Теги користувача застосунку» — порожній список означає, що ці теги код не змінює взагалі;
- змінні результату й помилки — їх дозволено завжди.
Решту сервер відкине й запише в журнал помилок «Блок відкинув записане кодом». Якщо код пише імена, яких немає у списках, налаштування блоку попередять про це й запропонують «Додати до списків».
Вимикайте обмеження, лише якщо від змінних і тегів нічого не залежить: інакше людина зможе записати собі, наприклад, тег VIP або знижку.
Об'єкт app
| Виклик | Що робить |
|---|---|
app.variables.get('name') |
Значення змінної |
app.variables.set('name', value) |
Записати змінну — піде на сервер із виходом блоку |
app.variables.all() |
Усі змінні об'єктом |
app.tags.has('vip') / add('vip') / remove('vip') / all() |
Теги користувача застосунку — є в кожного, навіть без чат-бота |
app.contact?.name |
Контакт чат-бота: id, name, first_name, last_name, username, phone, email, address, source, created_at, telegram_id, max_id. null, якщо застосунок відкрили не з бота |
app.contact.variables.get('name') / set('name', value) |
Власні змінні контакту, окремо від змінних застосунку. Записане піде в контакт із виходом блоку |
app.contact.tags.has('vip') / add / remove / all() |
Теги контакту бота |
app.platform |
Звідки відкрито: telegram, max, webchat, pwa або browser |
app.startParam |
Параметр посилання запуску (startapp) |
app.user |
language, name і username у месенджері |
app.device |
mode (ios або md), dark, standalone, width, height, userAgent |
await app.toast(message) |
Спливне повідомлення |
await app.alert(message, title) |
Повідомлення з кнопкою OK — чекає, поки його закриють |
await app.confirm(question) |
Запитання «так чи ні» — поверне true або false |
app.openLink('https://…') |
Відкрити посилання: у месенджері — його засобами, інакше в новій вкладці |
await app.copy(text) |
Скопіювати в буфер обміну |
await app.share({title, text, url}) |
Системне меню «Поділитися», без нього — копія посилання |
app.vibrate('success') |
Вібрація: light, medium, heavy, success, warning або error |
app.localStorage.setItem('key', 'value') |
Сховище користувача на сервері — див. нижче |
app.storage.get('key') / set / remove |
Сховище на пристрої, своє в кожного застосунку |
await app.sleep(500) |
Зачекати вказану кількість мілісекунд |
app.close() |
Закрити застосунок |
app.telegram |
Telegram.WebApp як є, поза Telegram — null |
app.max |
Міст MAX як є, поза MAX — null |
Приклад із налаштувань блоку:
// Тема і ширина екрана — у змінні
const device = app.device
app.variables.set('theme', device.dark ? 'dark' : 'light')
if (app.platform === 'telegram') {
app.vibrate('success')
}
// Що повернули — потрапить у змінну результату
return device.width
Помилки коду видно в консолі браузера в попередньому перегляді, і вони потрапляють у журнал помилок — «Помилка в коді JavaScript».
Код застосунку
Код на весь застосунок: виконується один раз під час запуску, до першого екрана, і слухає події. Відкривається кнопкою «Код застосунку» (значок «</>») на панелі над схемою. Якщо код задано, значок зафарбовано.
У вікні «Код застосунку»:
- «Код» — до 100 000 символів;
- «Змінні, які код може записати» — до 50 імен. Інші змінні сервер не прийме;
- шпаргалка подій і «Приклад» із кнопкою «Вставити приклад».


Код зберігається у версії: нова версія та шаблон отримують його копію. Після збереження відкритий попередній перегляд перезапускається.
Події
| Підписка | Коли спрацьовує |
|---|---|
app.on('start', ({platform, startParam}) => {}) |
Застосунок запустився |
app.on('screen', ({id, name, type}) => {}) |
Показано екран або вікно поверх нього |
app.on('event', ({blockId, eventId}) => {}) |
Натискання на кнопку, пункт або елемент — до надсилання на сервер |
app.on('field', ({variable, value}) => {}) |
Людина змінила поле введення |
app.on('error', ({message}) => {}) |
Застосунок показав помилку |
app.on('hide', () => {}) / app.on('show', () => {}) |
Застосунок згорнули й повернули |
app.on('theme', ({dark}) => {}) |
Змінилася світла або темна тема |
app.on('storage', ({key, newValue}) => {}) |
Код елемента «HTML» записав у localStorage |
- Підписка на
start,screenіthemeодразу отримує поточне значення — навіть якщо підписалися післяawait. app.on()повертає функцію відписки:const stop = app.on(…); stop(). Є йapp.off(name, handler).await app.loadScript('https://…')підключає зовнішній скрипт: лічильник, віджет, бібліотеку. Адреса — лишеhttp://абоhttps://.
Решта — як у блоку «JavaScript»: app.variables, app.toast, app.alert, app.openLink, app.storage, app.localStorage, app.telegram та інші. app.contact і app.tags тут лише для читання: змінювати теги — справа блоків тегів.
Змінні, записані через app.variables.set(), ідуть на сервер із наступною подією.
Приклад із вікна — Google tag:
// Підключаємо Google tag
window.dataLayer = window.dataLayer || []
function gtag() { dataLayer.push(arguments) }
gtag('js', new Date())
gtag('config', 'G-XXXXXXXXXX', {send_page_view: false})
await app.loadScript('https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX')
// Кожен екран — перегляд сторінки
app.on('screen', ({id, name}) => {
gtag('event', 'page_view', {page_title: name, page_location: location.origin + '/screen/' + id})
})
// Натискання — події
app.on('event', ({eventId}) => {
gtag('event', 'tap', {event_id: eventId})
})
Помилки коду застосунку — під час запуску та в обробниках — видно в консолі, і вони потрапляють у журнал помилок із причиною «Помилка в коді застосунку» та стеком викликів. Та сама помилка записується один раз.
«HTML-код»: елемент і екран
Свій HTML зі скриптами та стилями буває двох видів:
- елемент «HTML-код» — у групі «Віджети», стає в область екрана поруч з іншими елементами;
- екран «HTML-код» — третій вид екрана після «Стандартного вікна» і «Вкладок знизу»: увесь екран — ваш код, без шапки й областей. Новий такий екран одразу отримує приклад із кнопкою та вихід
next. Зробити його модальним вікном не можна.
Код працює в ізольованому фреймі: сесія, дані застосунку та решта екрана йому недоступні. Скрипти й стилі — всередині коду. Колір тексту фрейм бере з теми застосунку.
| Налаштування | Що задає |
|---|---|
| «Код» | HTML до 100 000 символів |
| «Висота» (в елемента) | «За вмістом» — підлаштовується під код, зокрема коли він сам змінює вміст; «Задати» — від 40 до 2000 пікселів, усе, що не вміститься, прокручується всередині |
| «Виходи» | До 20. У виходу — «Ключ» (латиниця, цифри, _ і -) і «Назва на схемі». Вихід — перехід на інший блок схеми |
| «Змінні, які код може записати» | До 50 імен. Інші сервер не прийме |


Що доступно коду у фреймі
| Виклик | Що робить |
|---|---|
app.event('next') |
Перейти виходом із цим ключем |
app.event('next', {name: 'value'}) |
Перейти й записати дозволені змінні |
app.variables.set('name', 'value') |
Записати дозволену змінну одразу, без переходу: екран не змінюється |
localStorage.setItem('key', 'value') |
Сховище користувача на сервері — див. нижче. sessionStorage живе, поки відкритий екран |
app.openLink('https://…') |
Відкрити посилання в браузері. Звичайні посилання <a> відкриваються так само |
{{ name }} |
Підставити значення змінної просто в код — як текст, з екрануванням |
На схемі код не запускається — замість нього заглушка. У редакторі екрана фрейм показує результат і перезапускається після редагування коду.
Сховища
localStorage на сервері |
app.storage |
|
|---|---|---|
| Де доступне | localStorage у фреймі «HTML-код», app.localStorage у блоці «JavaScript» і коді застосунку |
Блок «JavaScript» і код застосунку |
| Де зберігається | На сервері, у користувача застосунку | У браузері людини |
| Переживає | Перезапуск, очищення телефона, зміну пристрою в тому самому месенджері | Поки не очищено дані браузера |
| Спільне | Для всіх елементів «HTML-код», коду застосунку та блоків «JavaScript» одного застосунку | Своє в кожного застосунку |
| Значення | Лише рядки, до 100 000 символів разом із ключами | Будь-які значення, зберігаються як JSON |
Сховище на сервері своє для кожного майданчика: в однієї людини в Telegram, MAX і браузері воно різне.
Обмеження
- Код блоку «JavaScript» — до 20 000 символів, код застосунку й HTML-коду — до 100 000.
- Час на виконання блоку «JavaScript» — до 60 секунд.
- У журнал потрапляє не більше ніж 20 помилок на хвилину з одного блоку.