
🤖 Настройка постоянного меню и кнопок для бота Facebook Messenger
Вы запустили бота в Facebook Messenger, он отвечает на сообщения, но чего-то не хватает. Пользователь заходит в чат и видит пустое окно. Ни меню, ни подсказок, ни кнопки «Начать». Первое касание, и тишина. Люди просто не понимают, что ваш бот умеет.
Три компонента превращают безликого бота в понятный интерфейс: постоянное меню с быстрыми действиями, кнопка «Начать» для первого контакта и текст приветствия, который встречает пользователя по имени. Раньше всё это настраивалось через устаревший параметр thread_settings. Сейчас Meta перевела управление на единый Messenger Profile API, и старые вызовы cURL из туториалов 2017 года просто не работают.
В этом гайде, актуальный подход к настройке постоянного меню, кнопки Get Started и приветствия через Messenger Profile API. С рабочими примерами cURL и PHP-обработчиком POSTBACK, который различает нажатия на пункты меню.
💡 Быстрый обзор:
- Настроить постоянное меню через
persistent_menuв Messenger Profile API: до 20 пунктов, локализация, отключение композера - Добавить кнопку «Начать» через параметр
get_started: при первом касании Facebook возвращает PSID пользователя - Прописать текст приветствия через
greeting: шаблоны{{user_first_name}}работают и в 2026 году - Написать PHP-обработчик POSTBACK: switch по
payloadразличает, на какой пункт меню нажал пользователь - Учесть лимиты: 10 вызовов Profile API за 10 минут на страницу, до 24 часов на обновление кеша меню
Что изменилось: Thread Settings → Messenger Profile API
До 2020 года меню, кнопка «Начать» и приветствие настраивались раздельными POST-запросами к эндпоинту /me/thread_settings. Тип настройки указывался в теле через setting_type: call_to_actions для меню, greeting для приветствия. В 2026 году этот подход не работает, эндпоинт исключён из документации.
Сейчас все свойства бота задаются через Messenger Profile API, единый эндпоинт:
1 POST https://graph.facebook.com/v22.0/me/messenger_profile?access_token=PAGE_ACCESS_TOKEN
Тело запроса, JSON-объект с нужными свойствами: persistent_menu для меню, get_started для кнопки «Начать», greeting для приветствия, ice_breakers и whitelisted_domains. Можно передать их вместе или по отдельности. Профиль перезаписывается, не передавайте свойство, если не хотите его менять.
Официальная документация: Persistent Menu на Meta for Developers. Версия API обновляется каждые полгода, уточняйте актуальную через Changelog.
Требования для работы меню, актуальные на июнь 2026:
- Страница Facebook опубликована, бот переведён в режим «public» в настройках приложения
- У приложения есть разрешение
pages_messaging - Пользователь запускает Messenger версии 106 или выше
- Кнопка «Начать» настроена (без неё меню не показывается)
- У вас роль администратора страницы

1. Постоянное меню (persistent_menu)
Меню висит слева от поля ввода, пользователь нажимает на иконку «гамбургер» и видит список действий. Это навигация верхнего уровня: «Помощь», «Каталог», «Поддержка». До 20 пунктов, но Meta рекомендует ограничиться пятью для лучшего UX.
Каждый пункт, объект с type (postback или web_url), title (до 30 символов) и либо payload, либо url. Эмодзи в заголовках работают, копируйте с getemoji.com.
Установка меню. Отправьте POST к Messenger Profile API:
1 curl -X POST -H "Content-Type: application/json" -d '{ 2 "persistent_menu": [ 3 { 4 "locale": "default", 5 "composer_input_disabled": false, 6 "call_to_actions": [ 7 { 8 "type": "postback", 9 "title": "🆘 Помощь", 10 "payload": "HELP_PAYLOAD" 11 }, 12 { 13 "type": "postback", 14 "title": "📰 Новости", 15 "payload": "LATEST_POSTS_PAYLOAD" 16 }, 17 { 18 "type": "web_url", 19 "title": "🌐 Сайт", 20 "url": "https://yoursite.com/", 21 "webview_height_ratio": "full" 22 } 23 ] 24 } 25 ] 26 }' "https://graph.facebook.com/v22.0/me/messenger_profile?access_token=PAGE_ACCESS_TOKEN"
Успешный ответ: {"result": "success"}. Меню появится не сразу, кеш на стороне клиента обновляется до 24 часов. При тестировании удалите переписку и начните заново, чтобы увидеть изменения мгновенно.
Удаление меню. DELETE с параметром fields:
1 curl -X DELETE "https://graph.facebook.com/v22.0/me/messenger_profile?fields=persistent_menu&access_token=PAGE_ACCESS_TOKEN"
Отключение композера. Если бот работает только через меню и кнопки, выставьте "composer_input_disabled": true. Поле ввода исчезнет, пользователь взаимодействует исключительно через пункты меню и postback-кнопки. Полезно для FAQ-ботов и каталогов.
Локализация. Добавьте объекты с ключом locale для каждого языка. Объект с "locale": "default" обязателен, он работает как fallback:
1 { 2 "persistent_menu": [ 3 { 4 "locale": "default", 5 "call_to_actions": [...] 6 }, 7 { 8 "locale": "ru_RU", 9 "call_to_actions": [...] 10 } 11 ] 12 }
Пользовательское меню. Через эндпоинт /me/custom_user_settings можно переопределить меню для конкретного пользователя по PSID. Лимит: 10 вызовов на пользователя за 10 минут. После удаления пользовательского меню восстанавливается страничное.
2. Обработка POSTBACK в PHP
Когда пользователь нажимает пункт меню с type: "postback", Facebook отправляет на ваш webhook событие messaging_postbacks. В теле запроса, объект postback с полем payload, которое вы задали при настройке меню.
PHP-обработчик читает входящий JSON из php://input, извлекает payload и через switch определяет, какое действие выполнить. Ниже, актуальный код для 2026 года с эндпоинтом v22.0:
1 <?php 2 // Читаем входящий запрос от Facebook 3 $input = json_decode(file_get_contents('php://input'), true); 4 5 // Извлекаем данные получателя и отправителя 6 $page_id = $input['entry'][0]['id']; 7 $sender = $input['entry'][0]['messaging'][0]['sender']['id']; 8 9 // Определяем, сообщение или postback 10 $message = $input['entry'][0]['messaging'][0]['message']['text'] ?? ''; 11 $postback = $input['entry'][0]['messaging'][0]['postback']['payload'] ?? ''; 12 13 if ($message || $postback) { 14 15 if ($message) { 16 $reply = 'Получено сообщение: ' . $message; 17 } else { 18 switch ($postback) { 19 case 'HELP_PAYLOAD': 20 $reply = 'Вы нажали кнопку «Помощь». Чем могу помочь?'; 21 break; 22 23 case 'LATEST_POSTS_PAYLOAD': 24 $reply = 'Вот свежие публикации за эту неделю.'; 25 break; 26 27 default: 28 $reply = 'Действие не распознано. Попробуйте ещё раз.'; 29 } 30 } 31 32 // Формируем ответ 33 $responseJSON = json_encode([ 34 'recipient' => ['id' => $sender], 35 'message' => ['text' => $reply], 36 ]); 37 38 $access_token = 'YOUR_PAGE_ACCESS_TOKEN'; 39 $url = 'https://graph.facebook.com/v22.0/me/messages?access_token=' . $access_token; 40 41 // Отправляем через cURL 42 $ch = curl_init($url); 43 curl_setopt($ch, CURLOPT_POST, 1); 44 curl_setopt($ch, CURLOPT_POSTFIELDS, $responseJSON); 45 curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']); 46 $result = curl_exec($ch); 47 curl_close($ch); 48 }
Что изменилось. Версия API в URL поднята с v2.7 до v22.0. Вместо ручной сборки JSON-строки используется json_encode(), меньше шансов сломать экранирование. Добавлен default-блок в switch для неопознанных payload. Конструкция ?? (null coalescing) чище старых isset() с тернарниками.
Где разместить. Код идёт в файл, на который указывает webhook-URL приложения Facebook. Обычно это webhook.php в корне сайта. Убедитесь, что метод GET на этот же URL обрабатывает верификацию webhook через hub_challenge.
Важно. Access token храните в переменных окружения или конфиге, не в коде. Для локальной разработки используйте .env-файл с PAGE_ACCESS_TOKEN=....
3. Кнопка «Начать» (get_started)
Кнопка появляется на экране приветствия при первом контакте пользователя со страницей. После нажатия Facebook присылает messaging_postbacks с payload, который вы указали. В ответе можно поприветствовать пользователя по имени или показать меню из кнопок.
Без настроенной кнопки «Начать» постоянное меню не отображается, это обязательное требование платформы.
Установка:
1 curl -X POST -H "Content-Type: application/json" -d '{ 2 "get_started": { 3 "payload": "GET_STARTED_PAYLOAD" 4 } 5 }' "https://graph.facebook.com/v22.0/me/messenger_profile?access_token=PAGE_ACCESS_TOKEN"
Payload, произвольная строка до 1000 символов. В PHP-обработчике добавьте case 'GET_STARTED_PAYLOAD' в switch и верните персонализированное приветствие.
Удаление:
1 curl -X DELETE "https://graph.facebook.com/v22.0/me/messenger_profile?fields=get_started&access_token=PAGE_ACCESS_TOKEN"
4. Текст приветствия (greeting)
Приветствие показывается в пустом чате до первого сообщения. Поддерживает шаблоны {{user_first_name}} {{user_last_name}} и {{user_full_name}}. Персонализация по имени повышает вовлечённость, пользователь видит, что бот обращается именно к нему.
Установка:
1 curl -X POST -H "Content-Type: application/json" -d '{ 2 "greeting": [ 3 { 4 "locale": "default", 5 "text": "Привет, {{user_first_name}}! Я бот-помощник. Задайте вопрос или откройте меню слева." 6 } 7 ] 8 }' "https://graph.facebook.com/v22.0/me/messenger_profile?access_token=PAGE_ACCESS_TOKEN"
Текст приветствия тоже поддерживает локализацию, добавляйте объекты с ключом locale.
Удаление:
1 curl -X DELETE "https://graph.facebook.com/v22.0/me/messenger_profile?fields=greeting&access_token=PAGE_ACCESS_TOKEN"
5. Ice Breakers: частые вопросы до первого сообщения
Ice Breakers, относительно новая фича Messenger Platform. Это кнопки с готовыми вопросами, которые появляются до того, как пользователь что-то написал. Нажатие отправляет текст от имени пользователя и запускает диалог.
Удобно для онбординга: вместо пустого окна человек видит «Что ты умеешь?», «Где мой заказ?», «Связаться с поддержкой» и начинает диалог одним касанием.
Установка:
1 curl -X POST -H "Content-Type: application/json" -d '{ 2 "ice_breakers": [ 3 { 4 "question": "Что ты умеешь?", 5 "payload": "ICE_CAPABILITIES" 6 }, 7 { 8 "question": "Где мой заказ?", 9 "payload": "ICE_ORDER_STATUS" 10 } 11 ] 12 }' "https://graph.facebook.com/v22.0/me/messenger_profile?access_token=PAGE_ACCESS_TOKEN"
До 4 вопросов, максимум 80 символов на вопрос. Payload обрабатывается в том же PHP-обработчике через switch.
⁉️🤔 Частые вопросы
Почему меню не появляется, хотя запрос вернул success?
Основные причины: не настроена кнопка «Начать», страница не опубликована, приложение в режиме разработки, пользователь использует старую версию Messenger или Facebook Mobile Browser. Меню кешируется локально, обновление на стороне клиента занимает до 24 часов. Для теста удалите переписку с ботом и начните заново. Если меню всё ещё не видно, проверьте все пункты: страница опубликована, бот публичный, разрешение
pages_messagingполучено, кнопка «Начать» настроена.
Можно ли сделать вложенное меню?
Да, через параметр
call_to_actionsвнутри пункта меню. Вложенность поддерживает один уровень, подменю раскрывается при нажатии на родительский пункт. Формат аналогичен основному меню: массив объектов сtype,titleиpayload/url. Родительский пункт с вложенным меню не может бытьweb_url, толькоpostback. Максимальная глубина, один уровень. Это ограничение платформы, обойти его нельзя.
Чем user-level menu отличается от page-level?
Page-level меню одно для всех пользователей страницы. User-level через
/me/custom_user_settingsпозволяет показывать разные пункты разным людям: новым, «Что я умею», вернувшимся, «История заказов». User-level обновляется в реальном времени, страничное, с задержкой до 24 часов. Лимит: 10 вызовов на пользователя за 10 минут. После удаления пользовательского меню автоматически восстанавливается страничное.
Как проверить, что webhook принимает POSTBACK?
Включите режим отладки в настройках приложения Facebook и нажмите пункт меню в чате с ботом. В логах появится запись с полем
postback.payload. Альтернативно добавьтеerror_log(print_r($input, true))в начало обработчика и смотрите логи сервера. Для локальной разработки используйте ngrok: он пробрасывает публичный HTTPS-URL на ваш localhost с валидным сертификатом.
Нужно ли обновлять код, если API версия меняется?
Да, дважды в год. Meta выпускает новую версию API каждые полгода, старые отключает через 2 года после выхода замены. Следите за Changelog Messenger Platform. В коде достаточно заменить номер версии в URL, логика вызовов меняется редко. Плановое отключение: v19.0, январь 2026, v20.0, май 2026, v21.0, октябрь 2026. Версия v22.0 активна до мая 2027. Ставьте в коде переменную
$api_version.
Что делать с ботом после настройки: чек-лист
Меню, кнопка и приветствие, это фундамент, а не финал. Когда базовая механика работает, три шага превращают бота из визитки в полезный инструмент:
Подключите аналитику. Facebook Messenger Insights показывает открытия, отправленные и полученные сообщения, активные диалоги. Без этих данных вы не узнаете, какими пунктами меню реально пользуются.
Настройте fallback-ответ. Когда пользователь пишет текст, не предусмотренный сценарием, бот должен отвечать осмысленно, а не молчать. Добавьте в обработчик ветку default с предложением открыть меню или связаться с человеком.
Обновляйте меню под сезон. Акции, новые продукты, праздничные распродажи, меняйте пункты меню в течение года. Через Messenger Profile API это делается одним POST-запросом.
Если бот обрабатывает заказы или собирает контакты, настройте домен в whitelisted_domains для корректной работы WebView внутри Messenger. И не забывайте про rate limits: 10 вызовов Profile API за 10 минут на страницу. Пакетные обновления меню для тысяч пользователей ставьте в очередь с задержкой.



