Skip to content

Alles für WordPress, Webentwicklung — und mehr

🤖 Einrichtung eines persistenten Menüs und von Schaltflächen für den Facebook Messenger-Bot

🤖 Einrichtung eines persistenten Menüs und von Schaltflächen für den Facebook Messenger-Bot

Sie haben einen Bot in Facebook Messenger gestartet, er antwortet auf Nachrichten, aber etwas fehlt. Ein Nutzer öffnet den Chat und sieht ein leeres Fenster. Kein Menü, keine Hinweise, keine „Los geht's"-Schaltfläche. Erster Kontakt, und Stille. Die Leute verstehen schlicht nicht, was Ihr Bot kann.

Drei Komponenten machen aus einem gesichtslosen Bot eine verständliche Oberfläche: ein persistentes Menü mit Schnellaktionen, eine „Los geht's"-Schaltfläche für den Erstkontakt und ein Begrüßungstext, der den Nutzer mit Namen willkommen heißt. Früher wurde all das über den veralteten Parameter thread_settings konfiguriert. Inzwischen hat Meta die Steuerung auf die einheitliche Messenger Profile API verlagert, und alte cURL-Aufrufe aus Tutorials von 2017 funktionieren schlicht nicht mehr.

In dieser Anleitung geht es um den aktuellen Ansatz zur Konfiguration des persistenten Menüs, der „Los geht's"-Schaltfläche und der Begrüßung über die Messenger Profile API. Mit funktionierenden cURL-Beispielen und einem PHP-POSTBACK-Handler, der Klicks auf Menüpunkte unterscheidet.

💡 Kurzüberblick:

  • Persistentes Menü über persistent_menu in der Messenger Profile API konfigurieren: bis zu 20 Einträge, Lokalisierung, Deaktivieren des Eingabefelds
  • „Los geht's"-Schaltfläche über den Parameter get_started hinzufügen: beim ersten Kontakt liefert Facebook die PSID des Nutzers zurück
  • Begrüßungstext über greeting einrichten: {{user_first_name}}-Platzhalter funktionieren auch 2026 noch
  • Einen PHP-POSTBACK-Handler schreiben: eine Fallunterscheidung nach payload erkennt, welchen Menüpunkt der Nutzer angeklickt hat
  • Limits beachten: 10 Profile-API-Aufrufe pro 10 Minuten pro Seite, bis zu 24 Stunden für Menü-Cache-Aktualisierungen

Was sich geändert hat: Thread Settings → Messenger Profile API

Vor 2020 wurden Menü, „Los geht's"-Schaltfläche und Begrüßung mit separaten POST-Requests an den Endpunkt /me/thread_settings konfiguriert. Die Einstellungsart wurde im Body über setting_type angegeben: call_to_actions für das Menü, greeting für die Begrüßung. 2026 funktioniert dieser Ansatz nicht mehr, der Endpunkt wurde aus der Dokumentation entfernt.

Jetzt werden alle Bot-Eigenschaften über die Messenger Profile API gesetzt, einen einheitlichen Endpunkt:

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

Der Request-Body ist ein JSON-Objekt mit den benötigten Eigenschaften: persistent_menu für das Menü, get_started für die „Los geht's"-Schaltfläche, greeting für die Begrüßung, ice_breakers und whitelisted_domains. Sie können diese gemeinsam oder einzeln übergeben. Das Profil wird überschrieben, übergeben Sie eine Eigenschaft nicht, wenn Sie sie nicht ändern möchten.

Offizielle Dokumentation: Persistent Menu auf Meta for Developers. Die API-Version wird alle sechs Monate aktualisiert, prüfen Sie die aktuelle über das Changelog.

Voraussetzungen dafür, dass das Menü funktioniert, Stand Juni 2026:

  • Facebook-Seite ist veröffentlicht, Bot in den App-Einstellungen auf „öffentlich" geschaltet
  • App verfügt über die Berechtigung pages_messaging
  • Nutzer verwendet Messenger Version 106 oder höher
  • „Los geht's"-Schaltfläche ist konfiguriert (ohne sie wird das Menü nicht angezeigt)
  • Sie haben die Rolle des Seitenadministrators
Programmcode auf einem Bildschirm

1. Persistentes Menü (persistent_menu)

Das Menü hängt links neben dem Eingabefeld, der Nutzer klickt auf das „Hamburger"-Icon und sieht eine Liste von Aktionen. Das ist die Navigation auf oberster Ebene: „Hilfe", „Katalog", „Support". Bis zu 20 Einträge, aber Meta empfiehlt, sich für eine bessere UX auf fünf zu beschränken.

Jeder Eintrag ist ein Objekt mit type (postback oder web_url), title (bis zu 30 Zeichen) und entweder payload oder url. Emojis in Titeln funktionieren, kopieren Sie diese von getemoji.com.

Menü einrichten. Senden Sie einen POST-Request an die 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": "🆘 Help",
10 "payload": "HELP_PAYLOAD"
11 },
12 {
13 "type": "postback",
14 "title": "📰 News",
15 "payload": "LATEST_POSTS_PAYLOAD"
16 },
17 {
18 "type": "web_url",
19 "title": "🌐 Website",
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"

Erfolgreiche Antwort: {"result": "success"}. Das Menü erscheint nicht sofort, der clientseitige Cache aktualisiert sich innerhalb von bis zu 24 Stunden. Löschen Sie beim Testen die Konversation und starten Sie neu, um Änderungen sofort zu sehen.

Menü entfernen. DELETE mit dem Parameter fields:

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

Eingabefeld deaktivieren. Wenn der Bot nur über Menü und Schaltflächen funktioniert, setzen Sie "composer_input_disabled": true. Das Eingabefeld verschwindet, der Nutzer interagiert ausschließlich über Menüpunkte und Postback-Buttons. Nützlich für FAQ-Bots und Kataloge.

Lokalisierung. Fügen Sie Objekte mit dem Schlüssel locale für jede Sprache hinzu. Ein Objekt mit "locale": "default" ist verpflichtend, es dient als 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}

Benutzerdefiniertes Menü. Über den Endpunkt /me/custom_user_settings können Sie das Menü für einen bestimmten Nutzer anhand der PSID überschreiben. Limit: 10 Aufrufe pro Nutzer in 10 Minuten. Nach dem Entfernen des benutzerdefinierten Menüs wird das Seitenmenü wiederhergestellt.

2. POSTBACK in PHP verarbeiten

Wenn ein Nutzer auf einen Menüpunkt mit type: "postback" klickt, sendet Facebook ein messaging_postbacks-Ereignis an Ihren Webhook. Im Request-Body befindet sich ein postback-Objekt mit einem payload-Feld, das Sie bei der Menükonfiguration festlegen.

Der PHP-Handler liest das eingehende JSON aus php://input, extrahiert payload und ermittelt per switch, welche Aktion auszuführen ist. Nachfolgend der aktuelle Code für 2026 mit dem v22.0-Endpunkt:

1<?php
2// Read incoming request from Facebook
3$input = json_decode(file_get_contents('php://input'), true);
4
5// Extract recipient and sender data
6$page_id = $input['entry'][0]['id'];
7$sender = $input['entry'][0]['messaging'][0]['sender']['id'];
8
9// Determine whether message or 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 received: ' . $message;
17 } else {
18 switch ($postback) {
19 case 'HELP_PAYLOAD':
20 $reply = 'You clicked the "Help" button. How can I help?';
21 break;
22
23 case 'LATEST_POSTS_PAYLOAD':
24 $reply = 'Here are fresh posts from this week.';
25 break;
26
27 default:
28 $reply = 'Action not recognized. Try again.';
29 }
30 }
31
32 // Form response
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 // Send via 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}

Was sich geändert hat. Die API-Version in der URL wurde von v2.7 auf v22.0 angehoben. Statt manueller JSON-String-Verkettung kommt json_encode() zum Einsatz, wodurch das Risiko von Escaping-Fehlern sinkt. Ein default-Block im switch fängt nicht erkannte Payloads ab. Das ??-Konstrukt (Null-Coalescing) ist sauberer als die alte Kombination aus isset() und Ternäroperator.

Wo der Code platziert wird. Der Code gehört in die Datei, auf die die Webhook-URL der Facebook-App zeigt. Üblicherweise ist das webhook.php im Stammverzeichnis der Website. Stellen Sie sicher, dass die GET-Methode auf derselben URL die Webhook-Verifikation via hub_challenge abwickelt.

Wichtig. Speichern Sie den Access-Token in Umgebungsvariablen oder einer Konfigurationsdatei, nicht im Code. Für die lokale Entwicklung nutzen Sie eine .env-Datei mit PAGE_ACCESS_TOKEN=....

3. Get-Started-Button (get_started)

Der Button erscheint auf dem Willkommensbildschirm beim ersten Kontakt mit der Seite. Nach dem Klick sendet Facebook messaging_postbacks mit dem von Ihnen festgelegten Payload. Daraufhin können Sie den Nutzer mit Namen begrüßen oder ein Menü mit Buttons anzeigen.

Ohne konfigurierten „Get Started"-Button wird das persistente Menü nicht eingeblendet, dies ist eine zwingende Plattformanforderung.

Einrichtung:

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"

Der Payload ist eine beliebige Zeichenkette mit bis zu 1000 Zeichen. Ergänzen Sie im PHP-Handler den case 'GET_STARTED_PAYLOAD' im switch und geben Sie eine personalisierte Begrüßung zurück.

Entfernung:

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

4. Begrüßungstext (greeting)

Die Begrüßung wird in einem leeren Chat vor der ersten Nachricht angezeigt. Unterstützt werden die Platzhalter {{user_first_name}}, {{user_last_name}} und {{user_full_name}}. Die Personalisierung mit dem Namen steigert die Interaktionsrate, der Nutzer erkennt, dass der Bot ihn gezielt anspricht.

Einrichtung:

1curl -X POST -H "Content-Type: application/json" -d '{
2 "greeting": [
3 {
4 "locale": "default",
5 "text": "Hi, {{user_first_name}}! I am a helper bot. Ask a question or open the menu on the left."
6 }
7 ]
8}' "https://graph.facebook.com/v22.0/me/messenger_profile?access_token=PAGE_ACCESS_TOKEN"

Der Begrüßungstext unterstützt auch Lokalisierung, fügen Sie Objekte mit dem Schlüssel locale hinzu.

Entfernung:

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

5. Ice Breakers: häufige Fragen vor der ersten Nachricht

Ice Breakers sind ein relativ neues Feature der Messenger-Plattform. Es handelt sich um Buttons mit vorgefertigten Fragen, die erscheinen, bevor der Nutzer etwas geschrieben hat. Ein Klick sendet den Text im Namen des Nutzers und startet den Dialog.

Praktisch für das Onboarding: Statt eines leeren Fensters sieht die Person „Was kannst du?", „Wo ist meine Bestellung?", „Support kontaktieren" und startet den Dialog mit einer Berührung.

Einrichtung:

1curl -X POST -H "Content-Type: application/json" -d '{
2 "ice_breakers": [
3 {
4 "question": "What can you do?",
5 "payload": "ICE_CAPABILITIES"
6 },
7 {
8 "question": "Where is my order?",
9 "payload": "ICE_ORDER_STATUS"
10 }
11 ]
12}' "https://graph.facebook.com/v22.0/me/messenger_profile?access_token=PAGE_ACCESS_TOKEN"

Bis zu 4 Fragen, maximal 80 Zeichen pro Frage. Der Payload wird im selben PHP-Handler per switch verarbeitet.

⁉️🤔 Häufig gestellte Fragen

Warum erscheint das Menü nicht, obwohl die Anfrage erfolgreich zurückkam?

Hauptgründe: „Get Started"-Button nicht konfiguriert, Seite nicht veröffentlicht, App im Entwicklungsmodus, Nutzer verwendet eine alte Messenger-Version oder den Facebook Mobile Browser. Das Menü wird lokal zwischengespeichert, die clientseitige Aktualisierung kann bis zu 24 Stunden dauern. Löschen Sie zum Testen die Konversation mit dem Bot und beginnen Sie neu. Ist das Menü weiterhin nicht sichtbar, prüfen Sie alle Punkte: Seite veröffentlicht, Bot öffentlich, Berechtigung pages_messaging erhalten, „Get Started"-Button konfiguriert.

Kann man ein verschachteltes Menü erstellen?

Ja, über den Parameter call_to_actions innerhalb eines Menüeintrags. Die Verschachtelung unterstützt eine Ebene, das Untermenü klappt beim Klick auf den übergeordneten Eintrag auf. Das Format entspricht dem des Hauptmenüs: Array aus Objekten mit type, title und payload/url. Ein übergeordneter Eintrag mit Untermenü kann nicht web_url sein, sondern nur postback. Die maximale Tiefe beträgt eine Ebene. Dies ist eine Plattformbeschränkung und lässt sich nicht umgehen.

Worin unterscheidet sich das nutzerbezogene Menü vom seitenbezogenen?

Das seitenbezogene Menü gilt einheitlich für alle Nutzer der Seite. Das nutzerbezogene Menü über /me/custom_user_settings erlaubt es, verschiedenen Personen unterschiedliche Einträge anzuzeigen: Neue Nutzer sehen „Was kann ich tun", wiederkehrende Nutzer sehen „Bestellhistorie". Nutzerbezogene Aktualisierungen erfolgen in Echtzeit, seitenbezogene mit einer Verzögerung von bis zu 24 Stunden. Limit: 10 Aufrufe pro Nutzer innerhalb von 10 Minuten. Nach dem Entfernen des benutzerdefinierten Menüs wird das Seitenmenü automatisch wiederhergestellt.

Wie prüft man, ob der Webhook POSTBACK empfängt?

Aktivieren Sie den Debug-Modus in den Facebook-App-Einstellungen und klicken Sie im Chat mit dem Bot auf einen Menüeintrag. Die Logs zeigen einen Eintrag mit dem Feld postback.payload. Alternativ fügen Sie error_log(print_r($input, true)) am Anfang des Handlers ein und prüfen die Server-Logs. Für die lokale Entwicklung nutzen Sie ngrok: Es stellt eine öffentliche HTTPS-URL mit gültigem Zertifikat zu Ihrem Localhost durch.

Muss man den Code anpassen, wenn sich die API-Version ändert?

Ja, zweimal jährlich. Meta veröffentlicht alle sechs Monate eine neue API-Version und deaktiviert alte zwei Jahre nach Erscheinen der Nachfolgeversion. Verfolgen Sie den Changelog Messenger Platform. Im Code ersetzen Sie lediglich die Versionsnummer in der URL, die Aufruflogik ändert sich selten. Geplante Abschaltungen: v19.0, Januar 2026, v20.0, Mai 2026, v21.0, Oktober 2026. Version v22.0 ist bis Mai 2027 aktiv. Setzen Sie die Variable $api_version im Code.

Was nach der Einrichtung mit dem Bot zu tun ist: Checkliste

Menü, Button und Begrüßung sind das Fundament, nicht der Abschluss. Wenn die grundlegende Mechanik funktioniert, machen drei Schritte aus dem Bot mehr als eine Visitenkarte:

  • Analytics anbinden. Facebook Messenger Insights zeigt Öffnungen, gesendete und empfangene Nachrichten, aktive Dialoge. Ohne diese Daten wissen Sie nicht, welche Menüeinträge tatsächlich genutzt werden.

  • Fallback-Antwort konfigurieren. Schreibt ein Nutzer einen Text, der im Szenario nicht vorgesehen ist, soll der Bot sinnvoll reagieren und nicht schweigen. Fügen Sie einen Standardzweig im Handler ein, der das Öffnen des Menüs oder den Kontakt zu einem Menschen anbietet.

  • Menü saisonal aktualisieren. Aktionen, neue Produkte, Feiertagsverkäufe: Passen Sie die Menüeinträge übers Jahr hinweg an. Über die Messenger Profile API geschieht das mit einer einzigen POST-Anfrage.

Wenn der Bot Bestellungen verarbeitet oder Kontakte sammelt, konfigurieren Sie die Domain in whitelisted_domains für den korrekten WebView-Betrieb innerhalb des Messengers. Und vergessen Sie die Ratenlimits nicht: 10 Profile-API-Aufrufe pro 10 Minuten und Seite. Staffeln Sie Massen-Menüaktualisierungen für tausende Nutzer mit Verzögerungen.