Skip to content

Wszystko o WordPressie, tworzeniu stron — i nie tylko

🤖 Konfiguracja stałego menu i przycisków dla bota Facebook Messenger

🤖 Konfiguracja stałego menu i przycisków dla bota Facebook Messenger

Uruchomił Pan bota w Facebook Messengerze, odpowiada on na wiadomości, ale czegoś brakuje. Użytkownik wchodzi na czat i widzi puste okno. Nie ma menu, podpowiedzi ani przycisku „Rozpocznij". Pierwsze dotknięcie i cisza. Ludzie po prostu nie rozumieją, co Pana bot potrafi.

Trzy komponenty przekształcają bezimiennego bota w czytelny interfejs: stałe menu z szybkimi akcjami, przycisk „Rozpocznij" do pierwszego kontaktu oraz tekst powitania, który wita użytkownika po imieniu. Dawniej wszystko to konfigurowało się przez przestarzały parametr thread_settings. Obecnie Meta przeniosła zarządzanie na jednolity Messenger Profile API, a stare wywołania cURL z tutoriali z 2017 roku po prostu nie działają.

W tym poradniku przedstawiam aktualne podejście do konfiguracji stałego menu, przycisku Get Started oraz powitania przez Messenger Profile API. Z działającymi przykładami cURL i PHP-owym handlerem POSTBACK, który rozróżnia kliknięcia w pozycje menu.

💡 Szybki przegląd:

  • Skonfigurować stałe menu przez persistent_menu w Messenger Profile API: do 20 pozycji, lokalizacja, wyłączenie kompozytora
  • Dodać przycisk „Rozpocznij" przez parametr get_started: przy pierwszym dotknięciu Facebook zwraca PSID użytkownika
  • Ustawić tekst powitania przez greeting: szablony {{user_first_name}} działają również w 2026 roku
  • Napisać PHP-owy handler POSTBACK: switch po payload rozróżnia, którą pozycję menu kliknął użytkownik
  • Uwzględnić limity: 10 wywołań Profile API na 10 minut na stronę, do 24 godzin na odświeżenie cache menu

Co się zmieniło: Thread Settings → Messenger Profile API

Do 2020 roku menu, przycisk „Rozpocznij" i powitanie konfigurowało się osobnymi żądaniami POST do endpointu /me/thread_settings. Typ ustawienia podawało się w treści przez setting_type: call_to_actions dla menu, greeting dla powitania. W 2026 roku to podejście nie działa, endpoint został usunięty z dokumentacji.

Obecnie wszystkie właściwości bota ustawia się przez Messenger Profile API, jeden endpoint:

1POST https://graph.facebook.com/v22.0/me/messenger_profile?access_token=PAGE_ACCESS_TOKEN

Treść żądania to obiekt JSON z potrzebnymi właściwościami: persistent_menu dla menu, get_started dla przycisku „Rozpocznij", greeting dla powitania, ice_breakers i whitelisted_domains. Można je przesłać razem lub osobno. Profil jest nadpisywany, nie należy przesyłać właściwości, jeśli nie chce Pan jej zmieniać.

Oficjalna dokumentacja: Persistent Menu na Meta for Developers. Wersja API jest aktualizowana co pół roku, proszę sprawdzać aktualną przez Changelog.

Wymagania do działania menu, aktualne na czerwiec 2026:

  • Strona na Facebooku jest opublikowana, bot jest przełączony w tryb „public" w ustawieniach aplikacji
  • Aplikacja ma uprawnienie pages_messaging
  • Użytkownik uruchamia Messenger w wersji 106 lub wyższej
  • Przycisk „Rozpocznij" jest skonfigurowany (bez niego menu się nie wyświetla)
  • Ma Pan rolę administratora strony
Kod programu na ekranie monitora

1. Stałe menu (persistent_menu)

Menu znajduje się po lewej stronie pola wprowadzania, użytkownik klika ikonę „hamburger" i widzi listę akcji. To nawigacja najwyższego poziomu: „Pomoc", „Katalog", „Wsparcie". Do 20 pozycji, ale Meta zaleca ograniczenie się do pięciu dla lepszego UX.

Każda pozycja to obiekt z type (postback lub web_url), title (do 30 znaków) oraz albo payload, albo url. Emoji w tytułach działają, proszę kopiować z getemoji.com.

Ustawianie menu. Proszę wysłać POST do 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"

Pomyślna odpowiedź: {"result": "success"}. Menu nie pojawi się od razu, cache po stronie klienta odświeża się do 24 godzin. Podczas testowania proszę usunąć konwersację i zacząć od nowa, aby zobaczyć zmiany natychmiast.

Usuwanie menu. DELETE z parametrem fields:

1curl -X DELETE "https://graph.facebook.com/v22.0/me/messenger_profile?fields=persistent_menu&access_token=PAGE_ACCESS_TOKEN"

Wyłączanie kompozytora. Jeśli bot działa tylko przez menu i przyciski, proszę ustawić "composer_input_disabled": true. Pole wprowadzania zniknie, użytkownik wchodzi w interakcję wyłącznie przez pozycje menu i przyciski postback. Przydatne dla botów FAQ i katalogów.

Lokalizacja. Proszę dodać obiekty z kluczem locale dla każdego języka. Obiekt z "locale": "default" jest obowiązkowy, działa jako 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}

Menu użytkownika. Przez endpoint /me/custom_user_settings można nadpisać menu dla konkretnego użytkownika po PSID. Limit: 10 wywołań na użytkownika na 10 minut. Po usunięciu menu użytkownika przywracane jest menu strony.

2. Obsługa POSTBACK w PHP

Gdy użytkownik kliknie pozycję menu z type: "postback", Facebook wysyła na Pana webhook zdarzenie messaging_postbacks. W treści żądania znajduje się obiekt postback z polem payload, które Pan zdefiniował podczas konfiguracji menu.

Procedura obsługi w PHP odczytuje przychodzący JSON z php://input, wyodrębnia payload i za pomocą switch określa, którą akcję wykonać. Poniżej aktualny kod na rok 2026 z endpointem 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}

Co się zmieniło. Wersję API w URL podniesiono z v2.7 do v22.0. Zamiast ręcznego składania ciągu JSON stosowane jest json_encode(), co zmniejsza ryzyko popsucia escapowania. Dodano blok default w switch dla nierozpoznanych payloadów. Konstrukcja ?? (null coalescing) jest czystsza niż stare isset() z operatorami trójargumentowymi.

Gdzie umieścić. Kod trafia do pliku, na który wskazuje webhook URL aplikacji Facebook. Zazwyczaj jest to webhook.php w katalogu głównym witryny. Proszę się upewnić, że metoda GET na ten sam adres URL obsługuje weryfikację webhooka przez hub_challenge.

Ważne. Access token proszę przechowywać w zmiennych środowiskowych lub konfiguracji, nie w kodzie. Do pracy lokalnej proszę używać pliku .env z PAGE_ACCESS_TOKEN=....

3. Przycisk „Rozpocznij" (get_started)

Przycisk pojawia się na ekranie powitalnym podczas pierwszego kontaktu użytkownika ze stroną. Po kliknięciu Facebook wysyła messaging_postbacks z payloadem, który Pan wskazał. W odpowiedzi można przywitać użytkownika po imieniu lub pokazać menu z przycisków.

Bez skonfigurowanego przycisku „Rozpocznij" stałe menu nie jest wyświetlane, jest to obowiązkowy wymóg platformy.

Instalacja:

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, dowolny ciąg do 1000 znaków. W procedurze obsługi PHP proszę dodać case 'GET_STARTED_PAYLOAD' w switch i zwrócić spersonalizowane powitanie.

Usunięcie:

1curl -X DELETE "https://graph.facebook.com/v22.0/me/messenger_profile?fields=get_started&access_token=PAGE_ACCESS_TOKEN"

4. Tekst powitania (greeting)

Powitanie jest wyświetlane w pustym czacie przed pierwszą wiadomością. Obsługuje szablony {{user_first_name}} {{user_last_name}} i {{user_full_name}}. Personalizacja za pomocą imienia zwiększa zaangażowanie, użytkownik widzi, że bot zwraca się bezpośrednio do niego.

Instalacja:

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"

Tekst powitania obsługuje również lokalizację, proszę dodawać obiekty z kluczem locale.

Usunięcie:

1curl -X DELETE "https://graph.facebook.com/v22.0/me/messenger_profile?fields=greeting&access_token=PAGE_ACCESS_TOKEN"

5. Ice Breakers: częste pytania przed pierwszą wiadomością

Ice Breakers to stosunkowo nowa funkcja Messenger Platform. Są to przyciski z gotowymi pytaniami, które pojawiają się, zanim użytkownik cokolwiek napisze. Kliknięcie wysyła tekst w imieniu użytkownika i uruchamia dialog.

Jest to wygodne przy wdrażaniu: zamiast pustego okna osoba widzi „Co potrafisz?", „Gdzie jest moje zamówienie?", „Skontaktuj się z pomocą techniczną" i rozpoczyna dialog jednym dotknięciem.

Instalacja:

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"

Do 4 pytań, maksymalnie 80 znaków na pytanie. Payload jest obsługiwany w tej samej procedurze PHP przez switch.

⁉️🤔 Często zadawane pytania

Dlaczego menu nie pojawia się, mimo że zapytanie zwróciło success?

Główne przyczyny: nieskonfigurowany przycisk „Rozpocznij", nieopublikowana strona, aplikacja w trybie deweloperskim, użytkownik korzysta ze starej wersji Messengera lub Facebook Mobile Browser. Menu jest lokalnie buforowane, aktualizacja po stronie klienta trwa do 24 godzin. W celu przetestowania proszę usunąć konwersację z botem i rozpocząć ją od nowa. Jeśli menu nadal nie jest widoczne, proszę sprawdzić wszystkie punkty: strona jest opublikowana, bot jest publiczny, uzyskano uprawnienie pages_messaging, przycisk „Rozpocznij" jest skonfigurowany.

Czy można utworzyć menu zagnieżdżone?

Tak, poprzez parametr call_to_actions wewnątrz elementu menu. Zagnieżdżanie obsługuje jeden poziom, podmenu rozwija się po kliknięciu elementu nadrzędnego. Format jest analogiczny do menu głównego: tablica obiektów z type, title oraz payload/url. Element nadrzędny z zagnieżdżonym menu nie może być typu web_url, tylko postback. Maksymalna głębokość to jeden poziom. Jest to ograniczenie platformy, nie można go obejść.

Czym menu na poziomie użytkownika różni się od menu na poziomie strony?

Menu na poziomie strony jest jedno dla wszystkich użytkowników strony. Menu na poziomie użytkownika poprzez /me/custom_user_settings pozwala pokazywać różne elementy różnym osobom: nowym, „Co potrafię", powracającym, „Historia zamówień". Menu na poziomie użytkownika aktualizuje się w czasie rzeczywistym, menu strony, z opóźnieniem do 24 godzin. Limit: 10 wywołań na użytkownika w ciągu 10 minut. Po usunięciu menu użytkownika automatycznie przywracane jest menu strony.

Jak sprawdzić, czy webhook odbiera POSTBACK?

Proszę włączyć tryb debugowania w ustawieniach aplikacji Facebook i kliknąć element menu w czacie z botem. W logach pojawi się wpis z polem postback.payload. Alternatywnie można dodać error_log(print_r($input, true)) na początku handlera i obserwować logi serwera. Do lokalnego developmentu proszę używać ngrok: udostępnia on publiczny adres HTTPS na Pana/Pani localhost z ważnym certyfikatem.

Czy trzeba aktualizować kod, gdy zmienia się wersja API?

Tak, dwa razy w roku. Meta wydaje nową wersję API co pół roku, stare wyłącza 2 lata po premierze następcy. Proszę śledzić Changelog Messenger Platform. W kodzie wystarczy zmienić numer wersji w adresie URL, logika wywołań zmienia się rzadko. Planowane wyłączenia: v19.0, styczeń 2026, v20.0, maj 2026, v21.0, październik 2026. Wersja v22.0 jest aktywna do maja 2027. Proszę ustawić w kodzie zmienną $api_version.

Co robić z botem po konfiguracji: checklista

Menu, przycisk i powitanie to fundament, a nie finał. Gdy podstawowa mechanika działa, trzy kroki przekształcają bota z wizytówki w użyteczne narzędzie:

  • Proszę podłączyć analitykę. Facebook Messenger Insights pokazuje otwarcia, wysłane i odebrane wiadomości, aktywne dialogi. Bez tych danych nie dowiedzą się Państwo, z których elementów menu użytkownicy rzeczywiście korzystają.

  • Proszę skonfigurować odpowiedź fallback. Gdy użytkownik wpisze tekst nieprzewidziany w scenariuszu, bot powinien odpowiedzieć sensownie, a nie milczeć. Proszę dodać w handlerze gałąź default z propozycją otwarcia menu lub kontaktu z człowiekiem.

  • Proszę aktualizować menu sezonowo. Promocje, nowe produkty, wyprzedaże świąteczne, proszę zmieniać elementy menu w ciągu roku. Poprzez Messenger Profile API robi się to jednym żądaniem POST.

Jeśli bot obsługuje zamówienia lub zbiera kontakty, proszę skonfigurować domenę w whitelisted_domains dla poprawnego działania WebView wewnątrz Messengera. Proszę też nie zapominać o limitach częstotliwości: 10 wywołań Profile API w ciągu 10 minut na stronę. Wsadowe aktualizacje menu dla tysięcy użytkowników proszę umieszczać w kolejce z opóźnieniem.