Skip to content

Tutto per WordPress, lo sviluppo web — e non solo

🤖 Impostazione del menu persistente e dei pulsanti per il bot di Facebook Messenger

🤖 Impostazione del menu persistente e dei pulsanti per il bot di Facebook Messenger

Hai lanciato un bot su Facebook Messenger, risponde ai messaggi, ma manca qualcosa. Un utente apre la chat e vede una finestra vuota. Nessun menu, nessun suggerimento, nessun pulsante «Inizia». Primo contatto, e silenzio. Le persone semplicemente non capiscono cosa può fare il tuo bot.

Tre componenti trasformano un bot anonimo in un'interfaccia comprensibile: un menu persistente con azioni rapide, un pulsante «Inizia» per il primo contatto e un testo di benvenuto che saluta l'utente per nome. In passato, tutto questo veniva configurato tramite il parametro deprecato thread_settings. Ora Meta ha spostato il controllo sull'API unificata Messenger Profile, e le vecchie chiamate cURL dei tutorial del 2017 semplicemente non funzionano.

In questa guida, l'approccio attuale per configurare menu persistente, pulsante «Inizia» e messaggio di benvenuto tramite l'API Messenger Profile. Con esempi cURL funzionanti e un gestore PHP per i POSTBACK che distingue i click sulle voci del menu.

💡 Panoramica rapida:

  • Configura il menu persistente tramite persistent_menu nell'API Messenger Profile: fino a 20 voci, localizzazione, disabilitazione del compositore
  • Aggiungi il pulsante «Inizia» tramite il parametro get_started: al primo contatto Facebook restituisce il PSID dell'utente
  • Imposta il testo di benvenuto tramite greeting: i template {{user_first_name}} funzionano ancora nel 2026
  • Scrivi un gestore PHP per i POSTBACK: uno switch su payload distingue quale voce di menu l'utente ha cliccato
  • Considera i limiti: 10 chiamate all'API Profile ogni 10 minuti per pagina, fino a 24 ore per l'aggiornamento della cache del menu

Cosa è cambiato: Thread Settings → Messenger Profile API

Prima del 2020, menu, pulsante «Inizia» e messaggio di benvenuto venivano configurati con richieste POST separate all'endpoint /me/thread_settings. Il tipo di impostazione era specificato nel corpo tramite setting_type: call_to_actions per il menu, greeting per il messaggio di benvenuto. Nel 2026, questo approccio non funziona, l'endpoint è stato rimosso dalla documentazione.

Ora tutte le proprietà del bot vengono impostate tramite Messenger Profile API, un endpoint unificato:

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

Il corpo della richiesta è un oggetto JSON con le proprietà necessarie: persistent_menu per il menu, get_started per il pulsante «Inizia», greeting per il messaggio di benvenuto, ice_breakers e whitelisted_domains. Puoi inviarle insieme o separatamente. Il profilo viene sovrascritto, non passare una proprietà se non vuoi modificarla.

Documentazione ufficiale: Persistent Menu su Meta for Developers. La versione dell'API si aggiorna ogni sei mesi, verifica quella corrente tramite il Changelog.

Requisiti per il funzionamento del menu, aggiornati a giugno 2026:

  • La pagina Facebook è pubblicata, il bot è in modalità «pubblico» nelle impostazioni dell'app
  • L'app dispone del permesso pages_messaging
  • L'utente utilizza Messenger versione 106 o superiore
  • Il pulsante «Inizia» è configurato (senza, il menu non viene mostrato)
  • Disponi del ruolo di amministratore della pagina
Codice di programma sullo schermo di un monitor

1. Menu persistente (persistent_menu)

Il menu è posizionato a sinistra del campo di input, l'utente clicca l'icona «hamburger» e vede un elenco di azioni. Questa è la navigazione di primo livello: «Aiuto», «Catalogo», «Assistenza». Fino a 20 voci, ma Meta consiglia di limitarsi a cinque per una migliore UX.

Ogni voce è un oggetto con type (postback o web_url), title (fino a 30 caratteri) e payload oppure url. Le emoji nei titoli funzionano, copiale da getemoji.com.

Configurazione del menu. Invia una POST all'API Messenger Profile:

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"

Risposta di successo: {"result": "success"}. Il menu non apparirà immediatamente, la cache lato client si aggiorna fino a 24 ore. Durante i test, elimina la conversazione e ricomincia per vedere subito le modifiche.

Rimozione del menu. DELETE con il parametro fields:

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

Disabilitazione del compositore. Se il bot funziona solo tramite menu e pulsanti, imposta "composer_input_disabled": true. Il campo di input scomparirà, l'utente interagisce esclusivamente tramite le voci di menu e i pulsanti postback. Utile per bot FAQ e cataloghi.

Localizzazione. Aggiungi oggetti con la chiave locale per ogni lingua. L'oggetto con "locale": "default" è obbligatorio, funge da 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 personalizzato. Tramite l'endpoint /me/custom_user_settings puoi sovrascrivere il menu per un utente specifico tramite PSID. Limite: 10 chiamate per utente ogni 10 minuti. Dopo la rimozione del menu personalizzato, viene ripristinato il menu della pagina.

2. Gestire i POSTBACK in PHP

Quando un utente clicca una voce di menu con type: "postback", Facebook invia un evento messaging_postbacks al tuo webhook. Nel corpo della richiesta, un oggetto postback con un campo payload che hai impostato in fase di configurazione del menu.

Il gestore PHP legge il JSON in ingresso da php://input, estrae payload e tramite switch determina quale azione eseguire. Di seguito, il codice attuale per il 2026 con endpoint v22.0:

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}

Cosa è cambiato. La versione API nell'URL è stata alzata da v2.7 a v22.0. Invece dell'assemblaggio manuale della stringa JSON, si usa json_encode(), meno rischio di errori di escaping. Aggiunto il blocco default nello switch per i payload non riconosciuti. Il costrutto ?? (null coalescing) è più pulito del vecchio isset() con operatore ternario.

Dove inserirlo. Il codice va nel file puntato dall'URL del webhook dell'app Facebook. Di solito è webhook.php nella root del sito. Assicurati che il metodo GET sullo stesso URL gestisca la verifica del webhook tramite hub_challenge.

Importante. Conserva il token di accesso in variabili d'ambiente o file di configurazione, non nel codice. Per lo sviluppo in locale usa un file .env con PAGE_ACCESS_TOKEN=....

3. Pulsante Inizia (get_started)

Il pulsante compare nella schermata di benvenuto al primo contatto con la pagina. Dopo il clic, Facebook invia messaging_postbacks con il payload che hai specificato. In risposta, puoi salutare l'utente per nome o mostrare un menu di pulsanti.

Senza un pulsante "Inizia" configurato, il menu persistente non viene visualizzato: è un requisito obbligatorio della piattaforma.

Configurazione:

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"

Il payload è una stringa arbitraria fino a 1000 caratteri. Nel gestore PHP, aggiungi case 'GET_STARTED_PAYLOAD' nello switch e restituisci un saluto personalizzato.

Rimozione:

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

4. Testo di benvenuto (greeting)

Il messaggio di benvenuto viene mostrato in una chat vuota prima del primo messaggio. Supporta i template {{user_first_name}} {{user_last_name}} e {{user_full_name}}. La personalizzazione con il nome aumenta il coinvolgimento: l'utente vede che il bot si sta rivolgendo specificamente a lui.

Configurazione:

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"

Il testo di benvenuto supporta anche la localizzazione: aggiungi oggetti con la chiave locale.

Rimozione:

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

5. Ice Breakers: domande frequenti prima del primo messaggio

Gli Ice Breakers sono una funzionalità relativamente recente della Piattaforma Messenger. Si tratta di pulsanti con domande predefinite che compaiono prima che l'utente abbia scritto qualcosa. Al clic, inviano il testo per conto dell'utente e avviano il dialogo.

Utile per l'onboarding: invece di una finestra vuota, la persona vede "Cosa sai fare?", "Dov'è il mio ordine?", "Contatta l'assistenza" e avvia il dialogo con un solo tocco.

Configurazione:

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"

Fino a 4 domande, massimo 80 caratteri per domanda. Il payload viene gestito nello stesso handler PHP tramite switch.

⁉️🤔 Domande frequenti

Perché il menu non compare anche se la richiesta ha restituito successo?

Motivi principali: pulsante "Inizia" non configurato, pagina non pubblicata, app in modalità sviluppo, utente che usa una vecchia versione di Messenger o il browser mobile di Facebook. Il menu è salvato in cache localmente, l'aggiornamento lato client può richiedere fino a 24 ore. Per i test, elimina la conversazione con il bot e ricomincia da capo. Se il menu non è ancora visibile, verifica tutti i punti: pagina pubblicata, bot pubblico, permesso pages_messaging ottenuto, pulsante "Inizia" configurato.

Si può creare un menu annidato?

Sì, tramite il parametro call_to_actions all'interno di una voce di menu. L'annidamento supporta un solo livello, il sottomenu si espande cliccando sulla voce padre. Il formato è simile al menu principale: array di oggetti con type, title e payload/url. La voce padre con menu annidato non può essere web_url, solo postback. La profondità massima è di un livello. È una limitazione della piattaforma, non si può aggirare.

In cosa differisce il menu a livello utente da quello a livello pagina?

Il menu a livello pagina è uguale per tutti gli utenti della pagina. Quello a livello utente tramite /me/custom_user_settings permette di mostrare voci diverse a persone diverse: i nuovi utenti vedono "Cosa posso fare", gli utenti ricorrenti "Cronologia ordini". Il menu a livello utente si aggiorna in tempo reale, quello a livello pagina con un ritardo fino a 24 ore. Limite: 10 chiamate per utente ogni 10 minuti. Dopo aver rimosso il menu personalizzato, il menu di pagina si ripristina automaticamente.

Come verificare che il webhook riceva i POSTBACK?

Attiva la modalità debug nelle impostazioni dell'app Facebook e clicca su una voce di menu nella chat con il bot. Nei log comparirà una voce con il campo postback.payload. In alternativa, aggiungi error_log(print_r($input, true)) all'inizio del gestore e controlla i log del server. Per lo sviluppo in locale usa ngrok: crea un tunnel verso un URL HTTPS pubblico con un certificato valido che punta al tuo localhost.

Bisogna aggiornare il codice se cambia la versione dell'API?

Sì, due volte l'anno. Meta rilascia una nuova versione dell'API ogni sei mesi e disabilita quelle vecchie 2 anni dopo l'uscita della versione sostitutiva. Segui il Changelog di Messenger Platform. Nel codice basta sostituire il numero di versione nell'URL, la logica delle chiamate cambia raramente. Deprecazioni pianificate: v19.0, gennaio 2026, v20.0, maggio 2026, v21.0, ottobre 2026. La versione v22.0 resta attiva fino a maggio 2027. Imposta la variabile $api_version nel codice.

Cosa fare con il bot dopo la configurazione: checklist

Menu, pulsante e messaggio di benvenuto sono le fondamenta, non il traguardo. Quando i meccanismi di base funzionano, tre passaggi trasformano il bot da biglietto da visita a strumento utile:

  • Collega l'analisi dei dati. Facebook Messenger Insights mostra aperture, messaggi inviati e ricevuti, dialoghi attivi. Senza questi dati non saprai quali voci di menu vengono effettivamente usate.

  • Configura una risposta di fallback. Quando un utente scrive un testo non previsto dallo scenario, il bot deve rispondere in modo sensato, non restare in silenzio. Aggiungi un ramo predefinito al gestore con la proposta di aprire il menu o contattare un operatore.

  • Aggiorna il menu stagionalmente. Promozioni, nuovi prodotti, saldi festivi: cambia le voci di menu durante l'anno. Tramite l'API Messenger Profile si fa con una sola richiesta POST.

Se il bot gestisce ordini o raccoglie contatti, configura il dominio in whitelisted_domains per il corretto funzionamento della WebView all'interno di Messenger. E non dimenticare i limiti di frequenza: 10 chiamate all'API Profile ogni 10 minuti per pagina. Metti in coda gli aggiornamenti batch del menu per migliaia di utenti con delle pause.