> ## Documentation Index
> Fetch the complete documentation index at: https://docs.botflow.cc/llms.txt
> Use this file to discover all available pages before exploring further.

# Конструктор воронок

> Как собрать сценарий бота: блоки, условия, стрелки, сообщения, медиа и кнопки.

Бот в BotFlow работает по блокам. Каждый блок это шаг сценария: он отправляет
сообщение и ждёт, что подписчик напишет или нажмёт. Дальше бот идёт по стрелкам к
следующему блоку, реагируя на слова подписчика, нажатия кнопок и события трекера. Схема
собирается мышкой на холсте раздела «Конструктор сценария», код писать не нужно.

## Типы блоков

Блоков всего пять типов. Каждый отвечает за свой шаг сценария.

<Columns cols={2}>
  <Card title="Стартовое условие" icon="play">
    Точка входа в воронку. Срабатывает, когда входящее сообщение или событие совпало с его
    условием. У такого блока обязано быть хотя бы одно условие, иначе он не запустится никогда.
  </Card>

  <Card title="Состояние диалога" icon="comment-dots">
    Обычный шаг диалога. Отправляет сообщение и ждёт ответ, дальше ведёт по стрелкам. Сам себя
    не запускает: попасть в него можно только по стрелке, по таймауту, через действие «Перейти
    в блок» или из кампании.
  </Card>

  <Card title="Fallback" icon="life-ring">
    Запасной блок с самым низким приоритетом. Отвечает на «помощь», «меню» или «отмена» в любом
    месте воронки и не сбивает подписчика с текущего шага. Чтобы реально увести его дальше,
    добавьте действие «Перейти в блок».
  </Card>

  <Card title="ИИ-оператор" icon="robot">
    Передаёт переписку виртуальному оператору. Своего готового текста у блока нет: ответ пишет
    модель. Персона, модель и язык настраиваются на странице [ИИ-оператор](/ru/ai-operator), а в
    самом блоке задаётся «Задача блока» и переключатель «Писать первым при входе».
  </Card>

  <Card title="Draft" icon="file-pen">
    Заготовка. Не срабатывает, пока вы не переключите её в рабочий тип. Удобно отложить блок,
    сохранив его настройки.
  </Card>
</Columns>

<Info>
  На каждое сообщение подписчика бот проверяет блоки по порядку: сначала стрелку из блока, где
  подписчик стоит сейчас, потом стартовые условия, и в последнюю очередь Fallback. Если подошло
  сразу несколько блоков, выигрывает более высокий приоритет условия, а при равенстве последний
  созданный блок. Стрелка «любой ответ» проверяется после стрелок с конкретным условием.
</Info>

## Условия: на что реагирует блок

Условие это строка, по которой блок или стрелка решают, подходит ли входящее сообщение. Как
именно сравнивать, вы выбираете в списке «Тип сравнения» рядом с полем «Ключевые слова».

| Тип сравнения                 | Что делает                                                                           | Пример                         |
| ----------------------------- | ------------------------------------------------------------------------------------ | ------------------------------ |
| Игнорируя ошибки и неточности | Срабатывает даже с опечатками (превед, првед, превет). Тип по умолчанию.             | `привет; консультация; купить` |
| Содержит ключевые слова       | Ищет слово или фразу внутри сообщения, регистр не важен. Понимает группы `(A\|B)`.   | `купить; цена; (тариф\|план)`  |
| Точное совпадение             | Сообщение должно совпасть целиком, регистр не важен.                                 | `Старт`                        |
| Регулярное выражение          | Поиск по регулярному выражению, регистр учитывается. Здесь `;` не делит на варианты. | `^(привет\|здравствуйте).*`    |

Грамматика одинакова для условия блока и условия стрелки:

* `;` разделяет варианты и работает как ИЛИ: `купить; оплатить; заказать`.
* `(A|B)` группирует слова в режиме ключевых слов: `(тариф|план) (сменить|поменять)`.
* `{{ }}` подставляет данные подписчика прямо в условие. Можно просто вписать переменную как
  условие: она подставит своё значение, и блок сработает, если входящее сообщение совпало с ним.
* Переменную можно сравнить: `{{ status }} != paid` или `{{ price }} > 100`. Операторы: `==`,
  `!=`, `>`, `>=`, `<`, `<=`. Для `==` и `!=` сравнение строковое без учёта регистра, для
  остальных числовое.
* Варианты в одном поле можно смешивать через `;`: `купить; {{ vip }} >= 5; заказать`.

<Info>
  Отдельного «И» (AND) в грамматике нет. Несколько вариантов через `;` тоже работают как ИЛИ:
  блок срабатывает, если подошёл хотя бы один. Понимать смысл сообщения умеет только блок
  «ИИ-оператор», обычная стрелка сверяет текст буквально.
</Info>

<Note>
  `{{ tag }}` это стартовый параметр из ссылки запуска бота: если подписчик перешёл по
  `t.me/ваш_бот?start=123`, то `{{ tag }}` станет равен `123`. Значение фиксируется один раз, при
  первом `/start`. Поэтому стартовый блок с условием `/start; {{ tag }}` ловит и обычный запуск
  командой, и запуск по параметру из ссылки.
</Note>

<Note>
  Пустое поле условия означает «любое сообщение от подписчика». Но если после подстановки
  `{{ }}` строка стала пустой, такое условие не совпадёт ни с чем.
</Note>

## Стрелки и таймауты

Стрелка (связь) ведёт от одного блока к другому. Её тип виден прямо на подписи стрелки.

* **Авто-переход.** Пустая стрелка без таймаута. Срабатывает сразу после того, как блок
  отправил сообщение. Так проходит только первая пустая стрелка, ответа подписчика она не ждёт.
* **По сообщению.** Срабатывает, когда подписчик пишет текст, подходящий под «Условие
  срабатывания».
* **По нажатию кнопки.** Ловит клик по инлайн-кнопке Callback этого блока. Отдельно такой тип
  стрелки не выбирают: вставьте нужную кнопку в условие стрелки из списка «Кнопки источника», и
  стрелка сама станет «По нажатию кнопки».
* **Через таймаут.** Срабатывает по таймеру, если подписчик молчит. Задержку вы задаёте в поле
  «Таймаут до перехода» в секундах, минутах, часах или днях.
* **Ждать любой ответ подписчика.** Стрелка проходит при любом ответе, будь то текст или клик,
  без проверки условия. Сама по себе не срабатывает и проверяется последней, чтобы не перебивать
  стрелки с конкретным условием.

<Warning>
  Любое входящее сообщение от подписчика отменяет ожидающие таймауты и напоминания этого блока.
  Поэтому «подождать сутки и напомнить» делается стрелкой с таймаутом в отдельный блок.
  Отдельного блока-задержки в конструкторе нет.
</Warning>

## Сообщение блока: текст, медиа и кнопки

Содержимое блока настраивается на вкладке «Сообщение».

### Текст

В конструкторе доступно базовое форматирование Telegram: жирный, курсив, подчёркивание,
зачёркивание, моноширинный, код, ссылки, спойлер и цитата. Расширенное форматирование
(заголовки, списки, таблицы) доступно в [Рассылках](/ru/broadcasts). Переключатель «Показывать
превью ссылок» решает, разворачивать ли карточку ссылки. Лимиты Telegram: до 4096 символов в
тексте и до 1024 в подписи к медиа.

### Медиа

К блоку прикрепляются пять видов медиа: Фото, Видео, Видеосообщение, Голос, Аудио.

* Несколько фото и видео уходят одним альбомом. Голос, аудио и видеосообщение отправляются
  отдельными сообщениями.
* Видеосообщение идёт без подписи и без кнопок.
* Инлайн-кнопки нельзя прикрепить к альбому: они уходят отдельным сообщением следом за ним.
* При загрузке квадратного видео до 60 секунд бот по умолчанию отправит его как видеосообщение.
  Тип можно переключить в «Отправить как» прямо на файле, и бот отправит выбранным типом.

<Note>Файл загружается прямо в блок. Подставить внешнюю ссылку или путь к файлу нельзя.</Note>

### Инлайн-кнопки

Каждая инлайн-кнопка занимает свою строку. Тип кнопки выбирается переключателем:

* **URL.** Открывает ссылку.
* **Callback.** Ловится блоком сценария по нажатию.
* **Скопировать.** Копирует текст в буфер обмена подписчика, например промокод.

Кнопке можно задать стиль (Обычная, `primary`, `success`, `danger`). В тексте и значении кнопки
работает подстановка `{{ }}`, например `{{ click_id }}` в ссылке. Лимиты Telegram: callback до
64 байт, ссылка до 2048 символов, копируемый текст до 256.

<Note>
  **Как кнопка ведёт дальше.** Кнопка Callback ловится блоком сценария по своему значению, тому
  тексту, что вы вписали в её callback. Поймать нажатие можно двумя способами:

  * Стрелкой из этого же блока: вставьте кнопку в условие стрелки из списка «Кнопки источника»,
    значение подставится в один клик.
  * Отдельным блоком «Стартовое условие», у которого в «Ключевых словах» стоит то же значение
    callback. Такой блок поймает нажатие из любого места воронки, даже если подписчик уже ушёл с
    блока с кнопкой.
</Note>

<Note>
  Свою reply-клавиатуру (обычные кнопки под полем ввода) в блоке задать нельзя, блок работает с
  инлайн-кнопками. Есть только переключатель «Убрать reply-клавиатуру у подписчика»: он прячет
  reply-клавиатуру, которую подписчик получил раньше.
</Note>

## Действия после отправки

На вкладке «Действия» настраивается, что произойдёт после того, как блок отправил сообщение.
Доступно три действия:

* **Поставить тег.** Помечает переписку тегом. Теги заводятся и управляются в разделе
  [Теги](/ru/tags).
* **Убрать тег.** Снимает тег с переписки.
* **Перейти в блок.** Меняет текущую позицию подписчика. Следующее его сообщение будет сверяться
  с условиями целевого блока.

<Note>Захвата ответа в переменную или запуска своего кода в действиях нет.</Note>

## Пуши: напоминания замолчавшим

Если подписчик застрял в блоке и не идёт дальше, его можно вернуть напоминанием на вкладке
«Пуши». Есть два режима:

* **Заданные сообщения по таймеру.** Вы пишете шаги сами, задержки отсчитываются от входа в блок.
* **ИИ сам решает когда и что писать.** Доступно только в блоке «ИИ-оператор». Модель сама
  выбирает момент и текст под контекст переписки и то, что известно о подписчике, в рамках
  заданных «не чаще» и «не реже» и лимита напоминаний.

Оба режима останавливаются, как только подписчик ответит, уйдёт дальше по воронке или заблокирует
бота.

## Переменные

В текст, кнопки и условия подставляются данные подписчика через `{{ }}`. Токены пишутся латиницей
и точно как в списке. Полный справочник в разделе [Переменные](/ru/variables).

* **Системные:** `first_name`, `last_name`, `full_name`, `username`, `user_id`, `telegram_id`,
  `date_of_birth`, `created_at`, `tag` (стартовый параметр из ссылки запуска, см. выше).
* **Динамические:** заполняются после постбека от партнёрки и хранят данные последнего события.
  `click_id` (идентификатор для партнёрских ссылок), `event.payout` (сумма события),
  `event.currency` (валюта), `event.trader_id` (идентификатор аккаунта или игрока у партнёра),
  `event.device_type` (тип устройства), `event.os_version` (версия ОС), `event.link_type`
  (тип ссылки).
* **Свои:** глобальные переменные, заведённые для бота.

<Warning>
  Имена переменных пишутся латиницей и точно как в списке. `{{ first_name }}` работает, а
  `{{ имя }}` вернёт пустую строку. Выдуманные токены вроде `{{ name }}`, `{{ chat_id }}` или
  `{{ phone }}` тоже дадут пустую строку. Менять скобки `{{ }}` нельзя.
</Warning>

## Системные события и конверсии

Стартовое условие и стрелки срабатывают не только на текст, но и на события. Готовые события
можно вставить из списка «Системные события», набирать их руками не нужно:

* Заблокировал бота и Разблокировал бота.
* Заявка на вступление и Заявка одобрена (для инвайт-кампаний каналов).
* Реакция.
* Конверсии трекера: Регистрация, Депозит, Повторный депозит, Вывод и другие постбеки. Про
  источники этих событий читайте в разделе [Трекер](/ru/tracker).

## Пример: небольшая воронка

<Steps>
  <Step title="Стартовое условие на /start" icon="play">
    Создайте блок «Стартовое условие». В поле «Ключевые слова» впишите `/start`, тип сравнения
    оставьте «Содержит ключевые слова». В сообщении поздоровайтесь: `Привет, {{ first_name }}!` и
    добавьте две инлайн-кнопки типа Callback: «Каталог» и «Задать вопрос».
  </Step>

  <Step title="Разводим подписчика по кнопкам" icon="arrows-split-up-and-left">
    От стартового блока протяните две стрелки: в условие каждой вставьте свою кнопку из списка
    «Кнопки источника». Одну стрелку ведите к блоку «Каталог», другую к блоку «Вопрос».
  </Step>

  <Step title="Состояние «Каталог»" icon="comment-dots">
    Создайте блок «Состояние диалога», отправьте в нём фото и описание. На вкладке «Действия»
    добавьте «Поставить тег», например «Смотрел каталог», чтобы потом собрать этих подписчиков в
    рассылку.
  </Step>

  <Step title="Fallback на «помощь»" icon="life-ring">
    Добавьте блок «Fallback» с условием `помощь; help` в режиме «Содержит ключевые слова». Он
    ответит подсказкой в любом месте воронки и не собьёт подписчика с текущего шага.
  </Step>

  <Step title="Напоминание по таймауту" icon="clock">
    От блока «Каталог» протяните стрелку «Через таймаут» на 1 день в отдельный блок-напоминание.
    Если за сутки подписчик ничего не написал, он получит мягкий пуш. Любое его сообщение раньше
    срока отменит напоминание.
  </Step>
</Steps>

<Tip>
  Схема сохраняется сама, статус виден в шапке («Сохранено»). Проверить воронку проще всего
  вживую: откройте бота в Telegram и напишите ему `/start`. Все переписки бота собираются в
  разделе «Мессенджер» (в меню бота это пункт «Сообщения»).
</Tip>

## Что дальше

<Columns cols={2}>
  <Card title="ИИ-оператор" icon="robot" href="/ru/ai-operator">
    Персона, модель и язык виртуального оператора для блока «ИИ-оператор».
  </Card>

  <Card title="Настройки бота" icon="gear" href="/ru/bot-settings">
    Имя, описание и текст «О боте», которые видят подписчики в Telegram.
  </Card>

  <Card title="Мессенджер" icon="comments" href="/ru/messenger">
    Как оператор перехватывает переписку вручную и возвращает её ИИ.
  </Card>

  <Card title="Рассылки" icon="paper-plane" href="/ru/broadcasts">
    Массовые сообщения по тегам и сегментам подписчиков, с расширенным форматированием.
  </Card>
</Columns>
