Skip to content

Tudo para WordPress, desenvolvimento web — e não só

🤖 Configurar menu persistente e botões para o bot do Facebook Messenger

🤖 Configurar menu persistente e botões para o bot do Facebook Messenger

Lançou um bot no Facebook Messenger, ele responde a mensagens, mas falta qualquer coisa. Um utilizador abre o chat e vê uma janela vazia. Sem menu, sem dicas, sem botão «Começar». Primeiro toque, e silêncio. As pessoas simplesmente não percebem o que o seu bot pode fazer.

Três componentes transformam um bot sem rosto numa interface compreensível: um menu persistente com ações rápidas, um botão «Começar» para o primeiro contacto e um texto de saudação que dá as boas-vindas ao utilizador pelo nome. Anteriormente, tudo isto era configurado através do parâmetro obsoleto thread_settings. Agora, a Meta transferiu o controlo para a API unificada do Messenger Profile, e as antigas chamadas cURL dos tutoriais de 2017 simplesmente não funcionam.

Neste guia, a abordagem atual para configurar o menu persistente, o botão Começar e a saudação através da API do Messenger Profile. Com exemplos cURL funcionais e um handler POSTBACK em PHP que distingue os cliques nos itens do menu.

💡 Visão geral rápida:

  • Configurar o menu persistente através de persistent_menu na API do Messenger Profile: até 20 itens, localização, desativação do compositor
  • Adicionar o botão «Começar» através do parâmetro get_started: no primeiro toque, o Facebook devolve o PSID do utilizador
  • Definir o texto de saudação através de greeting: os modelos {{user_first_name}} ainda funcionam em 2026
  • Escrever um handler POSTBACK em PHP: um switch sobre payload distingue qual o item do menu em que o utilizador clicou
  • Considerar os limites: 10 chamadas à API do Profile a cada 10 minutos por página, até 24 horas para atualizações da cache do menu

O que mudou: Thread Settings → Messenger Profile API

Antes de 2020, o menu, o botão «Começar» e a saudação eram configurados com pedidos POST separados para o endpoint /me/thread_settings. O tipo de definição era especificado no corpo através de setting_type: call_to_actions para o menu, greeting para a saudação. Em 2026, esta abordagem não funciona, o endpoint foi removido da documentação.

Agora, todas as propriedades do bot são definidas através da Messenger Profile API, um endpoint unificado:

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

O corpo do pedido é um objeto JSON com as propriedades necessárias: persistent_menu para o menu, get_started para o botão «Começar», greeting para a saudação, ice_breakers e whitelisted_domains. Pode passá-las em conjunto ou separadamente. O perfil é sobrescrito, não passe uma propriedade se não a quiser alterar.

Documentação oficial: Persistent Menu no Meta for Developers. A versão da API é atualizada a cada seis meses, verifique a atual através do Changelog.

Requisitos para o menu funcionar, atuais em junho de 2026:

  • A página do Facebook está publicada, o bot está no modo «público» nas definições da app
  • A app tem a permissão pages_messaging
  • O utilizador executa a versão 106 ou superior do Messenger
  • O botão «Começar» está configurado (sem ele, o menu não aparece)
  • Tem a função de administrador da página
Código de programação num ecrã de monitor

1. Menu persistente (persistent_menu)

O menu fica à esquerda do campo de introdução de texto, o utilizador clica no ícone «hambúrguer» e vê uma lista de ações. Isto é navegação de nível superior: «Ajuda», «Catálogo», «Suporte». Até 20 itens, mas a Meta recomenda limitar a cinco para uma melhor experiência de utilizador.

Cada item é um objeto com type (postback ou web_url), title (até 30 caracteres) e payload ou url. Os emojis nos títulos funcionam, copie de getemoji.com.

Configurar o menu. Enviar POST para a 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"

Resposta de sucesso: {"result": "success"}. O menu não aparece imediatamente, a cache do lado do cliente atualiza-se até 24 horas. Ao testar, elimine a conversa e comece de novo para ver as alterações instantaneamente.

Remover o menu. DELETE com o parâmetro fields:

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

Desativar o compositor. Se o bot funcionar apenas através do menu e botões, defina "composer_input_disabled": true. O campo de introdução de texto desaparecerá, o utilizador interage exclusivamente através dos itens do menu e botões de postback. Útil para bots de FAQ e catálogos.

Localização. Adicione objetos com a chave locale para cada idioma. O objeto com "locale": "default" é obrigatório, funciona como 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 personalizado. Através do endpoint /me/custom_user_settings, pode substituir o menu para um utilizador específico por PSID. Limite: 10 chamadas por utilizador a cada 10 minutos. Após remover o menu personalizado, o menu da página é restaurado.

2. Processar POSTBACK em PHP

Quando um utilizador clica num item de menu com type: "postback", o Facebook envia um evento messaging_postbacks para o seu webhook. No corpo do pedido, um objeto postback com um campo payload que definiu ao configurar o menu.

O handler PHP lê o JSON recebido de php://input, extrai o payload e, através de um switch, determina qual a ação a executar. Abaixo, o código atual para 2026 com o 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}

O que mudou. A versão da API no URL foi atualizada de v2.7 para v22.0. Em vez da montagem manual de strings JSON, utiliza-se json_encode(), reduzindo a probabilidade de erros de escape. Foi adicionado um bloco default no switch para payloads não reconhecidos. A construção ?? (null coalescing) é mais limpa do que os antigos ternários com isset().

Onde colocar. O código vai no ficheiro apontado pelo URL do webhook da app do Facebook. Normalmente é o webhook.php na raiz do site. Certifique-se de que o método GET no mesmo URL trata a verificação do webhook através do hub_challenge.

Importante. Guarde o token de acesso em variáveis de ambiente ou num ficheiro de configuração, nunca no código. Para desenvolvimento local, utilize um ficheiro .env com PAGE_ACCESS_TOKEN=....

3. Botão Começar (get_started)

O botão aparece no ecrã de boas-vindas, no primeiro contacto com a página. Após o clique, o Facebook envia messaging_postbacks com o payload que especificou. Em resposta, pode cumprimentar o utilizador pelo nome ou mostrar um menu de botões.

Sem um botão «Começar» configurado, o menu persistente não é exibido, sendo este um requisito obrigatório da plataforma.

Configuração:

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"

O payload é uma string arbitrária até 1000 caracteres. No handler PHP, adicione case 'GET_STARTED_PAYLOAD' no switch e devolva uma saudação personalizada.

Remoção:

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

4. Texto de saudação (greeting)

A saudação é mostrada num chat vazio, antes da primeira mensagem. Suporta os templates {{user_first_name}}, {{user_last_name}} e {{user_full_name}}. A personalização pelo nome aumenta o envolvimento: o utilizador percebe que o bot se está a dirigir especificamente a ele.

Configuração:

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"

O texto de saudação também suporta localização; adicione objetos com a chave locale.

Remoção:

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

5. Ice Breakers: perguntas frequentes antes da primeira mensagem

Os Ice Breakers são uma funcionalidade relativamente recente da Messenger Platform. Trata-se de botões com perguntas prontas que aparecem antes de o utilizador ter escrito algo. O clique envia o texto em nome do utilizador e inicia o diálogo.

Conveniente para integração: em vez de uma janela vazia, a pessoa vê «O que podes fazer?», «Onde está a minha encomenda?», «Falar com o apoio» e inicia o diálogo com um toque.

Configuração:

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"

Até 4 perguntas, máximo de 80 caracteres por pergunta. O payload é tratado no mesmo handler PHP, através do switch.

⁉️🤔 Perguntas frequentes

Porque é que o menu não aparece, mesmo com o pedido a devolver sucesso?

Principais razões: botão «Get Started» não configurado, página não publicada, aplicação em modo de desenvolvimento, utilizador a usar uma versão antiga do Messenger ou o Navegador Móvel do Facebook. O menu é armazenado em cache localmente, a atualização do lado do cliente pode demorar até 24 horas. Para testar, apague a conversa com o bot e comece de novo. Se o menu continuar sem estar visível, verifique todos os pontos: página publicada, bot público, permissão pages_messaging obtida, botão «Get Started» configurado.

É possível criar um menu com submenus?

Sim, através do parâmetro call_to_actions dentro de um item do menu. A hierarquia suporta um nível, o submenu expande ao clicar no item principal. O formato é semelhante ao menu principal: array de objetos com type, title e payload/url. Um item principal com submenu não pode ser web_url, apenas postback. A profundidade máxima é de um nível. Esta é uma limitação da plataforma, não pode ser contornada.

Em que é que o menu ao nível do utilizador difere do menu ao nível da página?

O menu ao nível da página é igual para todos os utilizadores da página. O menu ao nível do utilizador, através de /me/custom_user_settings, permite mostrar itens diferentes a pessoas diferentes: novos utilizadores veem «O que posso fazer», utilizadores recorrentes veem «Histórico de encomendas». A atualização ao nível do utilizador é em tempo real, ao nível da página tem um atraso até 24 horas. Limite: 10 chamadas por utilizador a cada 10 minutos. Após remover o menu personalizado, o menu da página é restaurado automaticamente.

Como verificar se o webhook recebe POSTBACK?

Ative o modo de depuração nas definições da aplicação do Facebook e clique num item do menu na conversa com o bot. Os registos mostrarão uma entrada com o campo postback.payload. Em alternativa, adicione error_log(print_r($input, true)) no início do manipulador e verifique os registos do servidor. Para desenvolvimento local, use o ngrok: ele cria um túnel com um URL HTTPS público para o seu localhost, com um certificado válido.

É necessário atualizar o código quando a versão da API muda?

Sim, duas vezes por ano. A Meta lança uma nova versão da API a cada seis meses e desativa as antigas 2 anos após o lançamento da versão de substituição. Acompanhe o Changelog da Messenger Platform. No código, basta substituir o número da versão no URL, a lógica das chamadas raramente muda. Descontinuação programada: v19.0, janeiro de 2026; v20.0, maio de 2026; v21.0, outubro de 2026. A versão v22.0 está ativa até maio de 2027. Defina a variável $api_version no código.

O que fazer com o bot após a configuração: lista de verificação

O menu, o botão e a saudação são a base, não o fim. Quando a mecânica básica funciona, três passos transformam o bot de um cartão de visita numa ferramenta útil:

  • Ligar a análise de dados. As Estatísticas do Facebook Messenger mostram aberturas, mensagens enviadas e recebidas, diálogos ativos. Sem estes dados, não saberá que itens do menu estão realmente a ser usados.

  • Configurar uma resposta de fallback. Quando um utilizador escreve um texto não previsto no cenário, o bot deve responder de forma útil, não ficar em silêncio. Adicione um ramo padrão ao manipulador com uma oferta para abrir o menu ou contactar um humano.

  • Atualizar o menu sazonalmente. Promoções, novos produtos, vendas de época, altere os itens do menu ao longo do ano. Através da Messenger Profile API, isto é feito com um pedido POST.

Se o bot processar encomendas ou recolher contactos, configure o domínio em whitelisted_domains para o funcionamento correto da WebView dentro do Messenger. E não se esqueça dos limites de taxa: 10 chamadas à Profile API por cada 10 minutos por página. Coloque em fila as atualizações de menu em lote para milhares de utilizadores, com pausas.