Skip to main content
Version: 1.3.0

Sending Messenger Messages

Messenger has become one of the most popular channels between businesses and customers. Most of the messenger bots are designed for 1:1 communication.

Although the document is about "sending messages," in most of the cases, Messenger bots send messages after it receives a user event.

Note:

If you are not familiar with Messenger messages, we would like to recommend a short happy path.

To begin with, please try the basis of communication, Text Messages. Secondly, try Generic Template Messages to help you display a collection of items (e.g., recommended restaurants, songs, or books). Finally, - Quick Replies, which continuously guides your users for the next possible actions.

If you have experienced with Messenger messages, don't miss Rich Media Messages to show the personality of your bots. Rich Media Messages and Media Template Messages are necessary if you are building a media-driven, storytelling bot. Take a look at Persona, if you offer bot auto-reply and human agent customer support at the same time. Finally, if you are making a chatbot for campaign purposes, please dive into Rate Limits to ensure your bot is ready for high traffic.

Sending Text Messages

39993793_311437072745802_2909561891720265728_n

Text message is the most frequent and common message types among all chat channels. It also offers a minimal format while carrying out dynamic data, e.g., stock price and weather info.

async function SendHi(context) {
await context.sendText('Hi!');
}

Sending Rich Media Messages

ezgif-1-ef5b05e9923c

Rich media consist of images, videos, audios, and files.

Rich media is useful when your priority is to catch the user's attention, e.g., limited promotion. Plus, it is also handy to create an immersive experience, e.g., telling a story.

In the following section, you can see four different approaches while sending Rich Media Messages.

If you want to benefit from Facebook's cache, i.e., much faster loader time, then you should jump to section Attaching Saved Assets.

Approach 1: Send by URL

Sending by URL might be the easiest way in terms of implementation. We recommend you to use this approach only for prototyping; the loading speed is probably driving your clients or customers crazy.

await context.sendImage('https://example.com/image.jpg');
await context.sendVideo('https://example.com/video.mp4');
await context.sendAudio('https://example.com/audio.mp3');
await context.sendFile('https://example.com/receipt.pdf');

Approach 2: Attaching Saved Assets

If you want to benefit from Facebook's cache, i.e., a much pleasant loading speed, you should try this a bit complicated approach.

Firstly, you need to get a page-scoped Attachment Id by Attachment Upload API.

Once you get your Attachment Id, you can send rich media messages with the following code.

await context.sendImage({ attachmentId: '<ATTACHMENT_ID>' });
await context.sendVideo({ attachmentId: '<ATTACHMENT_ID>' });
await context.sendAudio({ attachmentId: '<ATTACHMENT_ID>' });
await context.sendFile({ attachmentId: '<ATTACHMENT_ID>' });

Note: > Attachment Id is page-scoped.

A commercial bot project usually involves a staging Page for development and a production Page for production. In this case, before bot release, you have to re-upload all the attachments and update all the Attachment Id.

Approach 3: Attaching ReadStreams

In the following example, you can send rich media by creating a readable stream. The file path is relative to your bot location.

const fs = require('fs');

await context.sendImage(fs.createReadStream('image.jpg'));
await context.sendVideo(fs.createReadStream('video.mp4'));
await context.sendAudio(fs.createReadStream('audio.mp3'));
await context.sendFile(fs.createReadStream('receipt.pdf'));

Approach 4: Attaching Buffers

In the following example, you can send rich media by creating a buffer. The file path is relative to your bot location.

await context.sendImage(imageBuffer, { filename: 'image.jpg' });
await context.sendVideo(videoBuffer, { filename: 'video.mp4' });
await context.sendAudio(audioBuffer, { filename: 'audio.mp3' });
await context.sendFile(fileBuffer, { filename: 'receipt.pdf' });

Sending Template Messages

66391040_700974230346439_7580226164833124352_n

66362686_447994139365537_8885089546354556928_n

In short, Template message is an interactive gallery composed of image, video, title, subtitle, and buttons.

Template message is the key to offer rich media interaction. It usually used in the scenario of display multiple choices and next actions to the user, e.g., applying coupon, booking a room, making a reservation.

Note:

  • If you are familiar with LINE and Messenger, you can find the difference Chat UI approach. While LINE creates an HTML-like, super flexible chat UI, Flex Messages, Messenger tends to focus on common chat UI patterns to offer a consistent user experience.

Generic Template

22880422_1740199342956641_1916832982102966272_n (1)

In a Generic Template, you can create up to 10 items in a row. Each item is composed of a title, subtitle, image, and up to 3 buttons.

Note: Please refer to Messenger's official guide of Generic Template to find out the latest specification.

await context.sendGenericTemplate([
{
title: "Welcome to Peter's Hats",
imageUrl: 'https://petersfancybrownhats.com/company_image.png',
subtitle: "We've got the right hat for everyone.",
defaultAction: {
type: 'web_url',
url: 'https://peterssendreceiveapp.ngrok.io/view?item=103',
messengerExtensions: true,
webviewHeightRatio: 'tall',
fallbackUrl: 'https://peterssendreceiveapp.ngrok.io/',
},
buttons: [
{
type: 'postback',
title: 'Start Chatting',
payload: 'DEVELOPER_DEFINED_PAYLOAD',
},
],
},
]);

Button Template

23204276_131607050888932_1057585862134464512_n (1)

Button Template is similar to Generic Template; the only difference is the removal of the item image.

Note: Please refer to Messenger's official guide of Button Template to find out the latest specification.

await context.sendButtonTemplate('What do you want to do next?', [
{
type: 'web_url',
url: 'https://petersapparel.parseapp.com',
title: 'Show Website',
},
{
type: 'postback',
title: 'Start Chatting',
payload: 'USER_DEFINED_PAYLOAD',
},
]);

Receipt Template

23208289_889588377870772_7170760265053503488_n

Receipt Template is a template designed for order confirmation.

Note: Please refer to Messenger's official guide of Receipt Template to find out the latest specification.

await context.sendReceiptTemplate({
recipientName: 'Stephane Crozatier',
orderNumber: '12345678902',
currency: 'USD',
paymentMethod: 'Visa 2345',
orderUrl: 'http://petersapparel.parseapp.com/order?order_id=123456',
timestamp: '1428444852',
elements: [
{
title: 'Classic White T-Shirt',
subtitle: '100% Soft and Luxurious Cotton',
quantity: 2,
price: 50,
currency: 'USD',
imageUrl: 'http://petersapparel.parseapp.com/img/whiteshirt.png',
},
{
title: 'Classic Gray T-Shirt',
subtitle: '100% Soft and Luxurious Cotton',
quantity: 1,
price: 25,
currency: 'USD',
imageUrl: 'http://petersapparel.parseapp.com/img/grayshirt.png',
},
],
address: {
street1: '1 Hacker Way',
street2: '',
city: 'Menlo Park',
postalCode: '94025',
state: 'CA',
country: 'US',
},
summary: {
subtotal: 75.0,
shippingCost: 4.95,
totalTax: 6.19,
totalCost: 56.14,
},
adjustments: [
{
name: 'New Customer Discount',
amount: 20,
},
{
name: '$10 Off Coupon',
amount: 10,
},
],
});

Media Template

23666967_188506161716866_2869776016224550912_n 23065701_1942345712696886_5686788878908784640_n

You can find the simplicity and elegance of Media Template. Try it if you agree with "A picture is worth a thousand words." The difference between it and Generic Template is the removal of title and subtitle.

Note: Please refer to Messenger's official guide of Media Template to find out the latest specification.

await context.sendMediaTemplate([
{
mediaType: 'image',
attachmentId: '1854626884821032',
buttons: [
{
type: 'web_url',
url: 'https://en.wikipedia.org/wiki/Rickrolling',
title: 'View Website',
},
],
},
]);

Sending with Quick Reply

64375249_668002483666648_541982039046356992_n (1)

We would recommend you to treat Quick Reply as an alternative to user text input.

A Quick Reply consists of up to 13 Quick Reply Buttons. When the user taps a Quick Reply Button, the Quick Reply dismissed. Then, the title of the tapped button is posted to the conversation as a message. Meanwhile, a messages event sends to your webhook that contains the button title and an optional payload.

In the following sections, you can see three different types of Quick Reply.

Note:

  • When we met Quick Reply first time, we were confused about the best practice of using Quick Reply or Button. Finally, we found out Quick Reply is the best solution to guide the user to keep interacting with the bot, while a URL Button brings user outside bot. What's more, the Quick Reply disappears when one of Quick Reply Buttons is tapped, which keeps Quick Reply only live under the present context, while a Button can be triggered even it is in the chat history.
  • Please refer to Messenger's official guide of Quick Replies to find out the latest specification.

Text Quick Reply

27690048_220332918537125_7991605536967622656_n

You can send up to 13 Text Quick Reply Buttons in a Quick Reply. Each Text Quick Reply can add one optional icon next to the button title.

await context.sendText('Hi!', {
quickReplies: [
{
contentType: 'text',
title: '<BUTTON_TEXT>',
payload: '<DEVELOPER_DEFINED_PAYLOAD>',
},
],
});

User Phone Number Quick Reply

23417458_1117232598379764_7436715136921894912_n

The User Phone Number Quick Reply can be treated as an agree button to collect the user's phone number.

Messenger automatically pre-fill the displayed quick reply with the phone number from the user's profile information. Since many CRM (Customer Relationship Management) use the phone number as a unique id, it is handy for future user mapping.

Note: If the user's profile does not have a phone number, the quick reply doesn't show up. Also, the bot only receives the phone number until the user clicks the quick reply.

await context.sendText('Hi!', {
quickReplies: [
{
contentType: 'user_phone_number',
},
],
});

User Email Quick Reply

27807597_203144990422079_3327502058327638016_n

The User Email Quick Reply can be treated as an agree button to collect the user's Email.

Messenger automatically pre-fill the displayed quick reply with the Email from the user's profile information. Since many CRM (Customer Relationship Management) use the Email as a unique id, it is handy for future user mapping.

Note: If the user's profile does not have an Email, the quick reply doesn't show up. Also, the bot only receives the Email until the user clicks the quick reply.

await context.sendText('Hi!', {
quickReplies: [
{
contentType: 'user_email',
},
],
});

Sending with Persona

To give the customer a clear understanding of whether a human agent or a bot representing the Business Page, the Persona API allows a business to introduce a virtual persona into the thread. Please refer to our separate document about Persona.

await context.sendText('Hi!', {
personaId: '<PERSONA_ID>',
});

Rate Limits

If you are making a bot with sudden high traffic, e.g., a campaign bot for Black Friday, you should deal with Rate Limits before you receive error code 613.

Page Rate limits are in place to prevent malicious behavior and poor user experiences. For Pages with large audiences, Messenger recommends a send rate of 250 requests per second.

Rate Limits is various from the size of your Page audience.

Calls within 24 hours = 200 * Total Messenger Audience

To prevent from hit Rate Limits, Messenger also advises us to architect our system to distribute any sudden high amounts of load over time.

Note: Refer to Messenger's official doc, Rate Limiting for the latest Messenger policy.