Botones de enlace de WhatsApp
Un botón de enlace coloca un botón interactivo debajo de un mensaje de WhatsApp que abre una URL en el navegador del destinatario. Úsalo cuando el siguiente paso está en la web, como una página de pago o un conjunto de fechas de taller, en lugar de en el propio chat. Para una opción que el destinatario responde dentro de WhatsApp, usa botones de respuesta o menús de lista.
Enviar un botón de enlace
Establece interactive.type en cta_url, con un objeto body_text y un objeto cta_url que contienen el text y el url del botón:
const msg = await bird.whatsapp.send({
to: "+16505551234",
from: "+13124495648",
interactive: {
type: "cta_url",
body_text: "Tap the button below to see the available dates.",
cta_url: { text: "See dates", url: "https://example.com/workshops?click_id=a1b2c3" },
},
});
console.log(msg.id, msg.status);msg = client.whatsapp.send(
to="+16505551234",
from_="+13124495648",
interactive={
"type": "cta_url",
"body_text": "Tap the button below to see the available dates.",
"cta_url": {"text": "See dates", "url": "https://example.com/workshops?click_id=a1b2c3"},
},
)
print(msg.id, msg.status)package main
import (
"context"
"fmt"
"log"
"os"
bird "github.com/messagebird/bird-sdk-go"
"github.com/messagebird/bird-sdk-go/option"
)
func main() {
client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
if err != nil {
log.Fatal(err)
}
msg, err := client.Whatsapp.Send(context.Background(), bird.WhatsappSendParams{
To: "+16505551234",
From: "+13124495648",
Interactive: &bird.WhatsAppInteractiveSend{
Type: "cta_url",
BodyText: "Tap the button below to see the available dates.",
CtaUrl: &bird.WhatsAppInteractiveCtaUrlSend{Text: "See dates", Url: "https://example.com/workshops?click_id=a1b2c3"},
},
})
if err != nil {
log.Fatal(err)
}
fmt.Println(msg.Id, *msg.Status)
}$interactive = (new WhatsAppMessageSendRequestInteractive())
->setType('cta_url')
->setBodyText('Tap the button below to see the available dates.')
->setCtaUrl(
(new WhatsAppInteractiveSendCtaUrl())
->setText('See dates')
->setUrl('https://example.com/workshops?click_id=a1b2c3'),
);
$message = $bird->whatsapp->send(
to: '+16505551234',
from: '+13124495648',
interactive: $interactive,
);
echo $message->getId(), ' ', $message->getStatus();bird whatsapp send \
--from +13124495648 \
--interactive '{"body_text":"Tap the button below to see the available dates.","cta_url":{"text":"See dates","url":"https://example.com/workshops?click_id=a1b2c3"},"type":"cta_url"}' \
--to +16505551234{
"name": "whatsapp_send",
"arguments": {
"from": "+13124495648",
"interactive": {
"body_text": "Tap the button below to see the available dates.",
"cta_url": {
"text": "See dates",
"url": "https://example.com/workshops?click_id=a1b2c3"
},
"type": "cta_url"
},
"to": "+16505551234"
}
}curl -X POST "https://{region}.platform.bird.com/v1/whatsapp/messages" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"to": "+16505551234",
"from": "+13124495648",
"interactive": {
"type": "cta_url",
"body_text": "Tap the button below to see the available dates.",
"cta_url": {
"text": "See dates",
"url": "https://example.com/workshops?click_id=a1b2c3"
}
}
}'from es obligatorio en cada mensaje de servicio: un número que tu espacio de trabajo posee, no uno gestionado por Bird. La forma completa añade un encabezado opcional, un pie y una cita de un mensaje anterior:
Ejemplo de código
{
"to": "+16505551234",
"from": "+13124495648",
"in_reply_to_message_id": "wam_01kya19eknftrs2s6p82asmvnh",
"interactive": {
"type": "cta_url",
"header": {
"type": "image",
"url": "https://cdn.example.com/banners/workshop.png"
},
"body_text": "Tap the button below to see the available dates.",
"footer_text": "Dates are subject to change.",
"cta_url": {
"text": "See dates",
"url": "https://example.com/workshops?click_id=a1b2c3"
}
},
"tags": [{ "name": "campaign", "value": "autumn-workshops" }],
"metadata": { "order_id": "A-4192" }
}in_reply_to_message_id cita un mensaje anterior en la misma conversación. Consulta en el hub citar un mensaje para correlacionar una respuesta para saber cómo funciona la resolución y qué puede omitir.
Este tipo envía exactamente un botón cta_url y no puede incluir buttons, list ni cards junto a él. Consulta la sección de botones del hub para ver la forma compartida de botón, que el botón de enlace propio de una tarjeta de carrusel también reutiliza.
Encabezados y pies
Un encabezado es opcional y tiene una de cuatro formas:
Ejemplo de código
"header": { "type": "text", "text": "New workshop dates" }
"header": { "type": "image", "url": "https://cdn.example.com/a.png" }
"header": { "type": "video", "url": "https://cdn.example.com/a.mp4" }
"header": { "type": "document", "url": "https://cdn.example.com/a.pdf" }Un encabezado multimedia (image, video o document) lleva su archivo como una URL https pública que WhatsApp obtiene en el momento del envío, en lugar de un handle de medio subido. footer_text es opcional y añade una línea debajo del botón.
Límites
| Campo | Restricción |
|---|---|
| Botones cta_url | exactamente uno |
| cta_url.text (etiqueta) | obligatorio, de 1 a 20 caracteres |
| cta_url.url | obligatorio, de 1 a 2000 caracteres |
| body_text | obligatorio, de 1 a 1024 caracteres |
| footer_text | opcional, de 1 a 60 caracteres |
| header.text | de 1 a 60 caracteres |
El límite de 2000 caracteres en url es propio de Bird: Meta no publica un límite de longitud para este campo. url también exige format: uri, una dirección absoluta con esquema, pero Bird no verifica qué esquema: una dirección http:// pasa la validación de Bird, y Meta es el único juez de si se entrega.
Qué reporta un clic
Un toque abre la dirección en el navegador del destinatario y nada regresa a ti a través de la API. El toque de un botón de enlace no es un interactive_reply: el mapeador de entrada que produce interactive_reply solo maneja el toque de un botón de respuesta y el toque de una fila de lista, y un enlace cta_url no tiene forma de entrada equivalente. Lo que sí ves es el ciclo de vida de salida habitual, los estados sent, delivered y read del mensaje, pero read_at te indica que el mensaje fue abierto, no que el botón fue tocado. No hay evento de clic, ni marca de tiempo, ni señal de toque por destinatario de WhatsApp ni de Bird.
Dos formas de recuperar la atribución, ya que el envío en sí no te la dará:
- Instrumenta la página de destino. La única evidencia de clic disponible está en tu propio servidor de destino, a partir de la URL que proporcionaste.
- Varía la URL tú mismo, por destinatario. La url que envías es una cadena literal: Bird la almacena y la pasa a Meta sin cambios, sin sustitución ni sintaxis de variable. Es idéntica para cada destinatario de un envío, así que la atribución por destinatario implica generar tu propio parámetro de consulta, como ?click_id=<value>, y emitir una llamada POST /v1/whatsapp/messages por destinatario. El endpoint ya acepta un único to por llamada, así que esto es contabilidad de tu lado y no una característica faltante de API.
Una tercera opción existe fuera de este tipo por completo: una plantilla con una variable de botón url es personalizada por destinatario por el propio WhatsApp, suministrada a través del componente button del envío. Esa variable debe ubicarse al final de la dirección, escrita como {{1}}, de modo que puede variar un segmento de ruta final o un valor de consulta, pero nunca el host ni la parte media de la URL. La compensación: una plantilla te da URLs por destinatario y entrega fuera de la ventana de servicio al cliente, a cambio de la revisión de Meta y una forma aprobada fija, mientras que un envío cta_url te da envío libre, sin revisión, dentro de una ventana abierta con una URL que tú mismo varías.
Límites y casos extremos
- La ventana de servicio al cliente debe estar abierta. Un botón de enlace es un mensaje de servicio, entregable solo dentro de una ventana abierta; consulta la ventana de servicio al cliente del hub. La verificación de ventana falla abierta, por lo que un 202 no es prueba de que la ventana estuviera realmente abierta cuando se realiza el envío.
- from debe ser un número que tu espacio de trabajo posee. Omitirlo o nombrar un número que no sea un remitente conectado se rechaza antes de crear el envío.
- La URL es estática para todo el envío e idéntica para cada destinatario. No hay variable por destinatario en este tipo. Consulta Qué reporta un clic para saber cómo atribuir clics de todos modos.
- Sin señal de toque, nunca. El toque de un botón de enlace no produce ningún mensaje de entrada ni evento de webhook. No construyas una funcionalidad que prometa métricas de clic solo con este tipo.
- Bird verifica la forma de la URL, no su esquema. url debe ser una dirección absoluta con esquema, pero Bird no requiere https, y Meta tampoco publica restricción de esquema. Contrasta con el url de un encabezado multimedia, que está documentado como obligatorio con https.
- Una URL de encabezado multimedia que WhatsApp no puede obtener falla después de aceptar el envío. WhatsApp obtiene el recurso del encabezado en el momento del envío y lo almacena en caché durante 10 minutos; una URL firmada debe durar más que el envío, y una URL inalcanzable falla de forma asíncrona, con media_rejected en el last_error del mensaje.
Ninguna de las verificaciones de forma que la tabla de errores del hub enumera puede dispararse en este tipo: inspeccionan las filas de una lista, un array buttons o las tarjetas de un carrusel, y un mensaje cta_url no tiene ninguno de los tres. Un error de forma, como una etiqueta text de más de 20 caracteres, regresa como un error genérico de validación de solicitud en lugar de uno de esos códigos. Una cita que no se resuelve hace fallar la solicitud antes de que se cree o cobre nada: 404 E15071 cuando el id nombra un mensaje que este espacio de trabajo no tiene, 422 E15072 cuando nombra uno que no se puede citar. Para los errores que cualquier envío WhatsApp puede encontrar, una ventana cerrada, un remitente faltante o inválido, o un destinatario inválido, consulta los errores del hub y Enviar mensajes WhatsApp.
Próximos pasos
- Mensajes interactivos de WhatsApp: qué comparten los seis tipos interactivos
- Plantillas de WhatsApp: para una variable de botón url que WhatsApp personaliza por destinatario
- Enviar mensajes WhatsApp: el sobre de solicitud, el modelo 202 y reintentos seguros
Recursos relacionados
Continúa con la documentación, guías y ejemplos sobre este tema. Los recursos están en inglés.
Ver la guíaConnecting WhatsApp to Bird: from buying a number to a live channelComprender el conceptoWhat is the 24-hour customer service window on WhatsApp?Usar la herramientaWhatsApp message builderExplorar la funcionalidadWhatsApp
Prueba el ejercicio y obtén un resumen de implementación