Skip to content

Всё для WordPress, веб-разработки — и не только

🤖 Настройка постоянного меню и кнопок для бота Facebook Messenger

🤖 Настройка постоянного меню и кнопок для бота 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, единый эндпоинт:

1POST 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:

1curl -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:

1curl -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
13if ($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, который вы указали. В ответе можно поприветствовать пользователя по имени или показать меню из кнопок.

Без настроенной кнопки «Начать» постоянное меню не отображается, это обязательное требование платформы.

Установка:

1curl -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 и верните персонализированное приветствие.

Удаление:

1curl -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}}. Персонализация по имени повышает вовлечённость, пользователь видит, что бот обращается именно к нему.

Установка:

1curl -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.

Удаление:

1curl -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. Это кнопки с готовыми вопросами, которые появляются до того, как пользователь что-то написал. Нажатие отправляет текст от имени пользователя и запускает диалог.

Удобно для онбординга: вместо пустого окна человек видит «Что ты умеешь?», «Где мой заказ?», «Связаться с поддержкой» и начинает диалог одним касанием.

Установка:

1curl -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 минут на страницу. Пакетные обновления меню для тысяч пользователей ставьте в очередь с задержкой.