Making Messenger Hunt - An Introduction to Messenger Bots
Since Facebook announced the introduction of bots on Messenger, I knew I had to try making one myself (as I'm a bit obsessed with the idea of bots). So, I decided to make Messenger Hunt, a Messenger bot for Product Hunt.
Here is how I worked with the Messenger API to create the bot. This article if going to be a bit similar to my "An Introduction to Slack Bots" as I'm using the same framework, Botkit to develop it.
The Setup #
The setup process for Messenger Bots can be a bit complicated. Because the Messenger API requires a callback URL hosted on a secure server, we can't work locally alone. We have to start live. I use (and recommend) BeepBoop for hosting bots. They are really easy to use and reliable. These are the steps to setting up a new Messenger bot being hosted through BeepBoop.
Step 1. Create a new Node.js (with Botkit) project. Here is a simple boilerplate code to get started -
var Botkit = require('botkit')
var accessToken = process.env.FACEBOOK_PAGE_ACCESS_TOKEN
var verifyToken = process.env.FACEBOOK_VERIFY_TOKEN
var port = process.env.PORT
if (!accessToken) throw new Error('FACEBOOK_PAGE_ACCESS_TOKEN is required but missing')
if (!verifyToken) throw new Error('FACEBOOK_VERIFY_TOKEN is required but missing')
if (!port) throw new Error('PORT is required but missing')
var controller = Botkit.facebookbot({
access_token: accessToken,
verify_token: verifyToken
})
var bot = controller.spawn()
controller.setupWebserver(port, function (err, webserver) {
if (err) return console.log(err)
controller.createWebhookEndpoints(webserver, bot, function () {
console.log('Ready')
})
})
Step 2. Push to a Github repository and connect with BeepBoop. If you don't already have an account with BeepBoop you'll need to create one.
Step 3. Enable the bot as a Facebook Messenger bot in BeepBoop's Project Settings.
Step 4. Generate a random key to use as the Verify Token (you can use the Random Key Generator) and paste it under the bot project settings.
Step 5. Get the Base Callback URL from the project settings. Note that this is only the base, the actual callback URL we will give to facebook will have the suffix /facebook/receive
.
Step 6. Create a new Facebook Page, or use an existing one. This is the page where people will interact with your bot.
Step 7. Create a new Facebook Application.
Step 8.. Enable "Messenger" for the application. You can find this under "Product Settings".
Step 9. Setup a New Webhook using the Callback Url from BeepBoop (step 5) and the Verify Token (step 4). Make sure to subscribe to the four fields needed (message_deliveries
, messages
, messaging_optins
, messaging_postbacks
).
Step 10. Under the "Messenger" section, generate an Access Token for the Page and save it under the BeepBoop project settings.
Step 11. Restart the bot.
Listening for Events and Keywords #
Next, we can start having the bot interact with users. Similar to Slack bots, a Messenger bot can respond to events that happen, e.g. when a user clicks a Send-to-Messenger button, or to specific keywords.
Listening for Events #
There are four events a Messenger bot can listen for -
message_received
- When a user sends a message to the botfacebook_postback
- When a user clicks a postback button provided by the botmessage_delivered
- When it is confirmed that the user has received a message sent by the botfacebook_optin
- When a user clicks a Send-to-Messenger button
Using this, we can send a welcome message when a user first adds the bot to Messenger -
controller.on("facebook_optin", function(bot, message) {
// Send welcome message
})
We can also listen for postbacks triggered when a user clicks a button -
controller.on('facebook_postback', function (bot, message) {
if ( message.payload === "button_postback_name" ) {
// Do stuff related to this button
}
})
Listening for Keywords #
We can also listen for specific keywords from a user’s message with the controller.hears
method. Unlike Slack bots in which we can listen for keywords from a variety of contexts, there is only one context for Messenger bots, message_received
.
controller.hears(array_of_keywords, "message_received", function(bot, message) {
// do stuff
})
With Messenger Hunt, for example, it listens for the mention of any of the categories on Product Hunt -
controller.hears(['podcasts', 'podcast'], "message_received", function(bot, message) {
// Get products from the Podcasts category
})
controller.hears(['games', 'game'], "message_received", function(bot, message) {
// Get products from the Games category
})
// And so on
Responding to Events #
Messenger bots, like Slack bots, can respond to events using the simple bot.reply
method. This method allows the bot to give a simple text reply to any message.
controller.hears(['hello', 'hi', 'hey'], 'message_received', function (bot, message) {
bot.reply(message, "Hi there!");
})
Structured Messages #
In addition to the simple reply methods, Messenger bots can send what are called Structured Messages. These are messages that follow one of Facebook’s predefined formats and can include attachments such as images and buttons.
For example, the Messenger Hunt bot sends products from a particular category as a Generic Template structured message.
var structured_message = {
attachment: {
type: 'template',
payload: {
template_type: 'generic', // The Generic Template Structured Message
elements: [
// Array of products
{
"title": post.name,
"image_url": post.thumbnail.image_url,
"subtitle": post.tagline,
"buttons": [
// CTAs for each product
{
"type": "postback",
"payload": "postInfo_"+post.id,
"title":"More Info"
},
{
"type":"web_url",
"url": post.redirect_url,
"title":"Hunt This"
},
{
"type":"web_url",
"url": post.discussion_url,
"title":"Discuss/Upvote"
}
]
},
{ ... },
{ ... }
]
}
}
}
// Send the structured message object instead of a simple string
bot.reply(message, structured_message);
Here is the result -
Postbacks #
The Messenger Hunt bot, as you may have noticed, is not really conversational. Instead, the user interacts with the bot mainly through clicking buttons that trigger postbacks. In my opinion, this is more useful as it doesn't force the user to learn how to "speak" with the bot. Postbacks allow us to create defined responses a user can give and, instead of the user having to type out those specifically, they can just click a button.
For example, when users are presented with the list of products from the Messenger Hunt bot, one of the buttons is an option to get more information about the product.
var buttons = [
{
"type": "postback",
"payload": "postInfo_"+post.id,
"title":"More Info"
},
{ ... },
{ ... }
]
Clicking this button triggers a postback, which we can listen for with the controller.on
method and respond accordingly.
controller.on('facebook_postback', function (bot, message) {
if ( message.payload.indexOf('postInfo_') > -1 ) {
var postID = message.payload.split("_")[1];
// Call function to get more information about the product
getPostInfo(bot, message, postID);
}
// Handle other postbacks below
})
Everything Else #
Those are the basics of working with Messenger bots. Everything else is to do with the logic of the particular bot and what it does. If you're interested in seeing the logic behind Messenger Hunt, you can checkout out the full source code at my repository, ireade/messenger-hunt.
You can also chat with Messenger Hunt or discuss/vote on it on Product Hunt.