Continued from Develop Facebook chat bot using Javascript – Part 1
Basic verification is complete, Now lets test webhook and see if we are receiving messages sent to bot page to our webhook or not.
Receiving messages
Add the following code to server.js
app.post('/',handleMessage);
This code tells express to run handleMessage function whenever a POST request is made.
And add handleMessage function
function handleMessage(req, res) { messaging_events = req.body.entry[0].messaging; for (i = 0; i < messaging_events.length; i++) { event = req.body.entry[0].messaging[i]; sender = event.sender.id; if (event.message && event.message.text) { text = event.message.text; console.log(text); } } res.end('received!'); }
Note: Dont forget to restart server after making changes in code everytime. Use Nodemon if you want to restart server automatically on file change
Messages sent to bot page are sent in an array named messaging with sender Id and message. Sender Id will be used to reply to the sender. Messenger platform may queue the messages sometime and send multiple messages in same POST request, so we make sure that all messages are captured by looping through the messaging array.
We are using console.log(text) to log the message to console for testing.
Subscribe to bot page in app dashboard and you should start receiving messages to webhook as shown in gif below.
We are building a wiki bot which searches wikipedia and sends relevant results. We will be using wikipedia REST API to search wikipedia and return results. Read more about wikipedia API here
If user sends wiki space ‘search query’ then bot should make a request to wikipedia API with search query, return results and send them to user using Facebook send API.
If user sends anything else then bot should reply with a help message Send Wiki space ‘Search query’ to search wikipedia.
Send a basic Message to user
Messages can be sent using send API by making a POST request to https://graph.facebook.com/v2.6/me/messages?access_token=PAGE_ACCESS_TOKEN
Page Access token can be accessed in messenger platform dashboard.
I’m using request
, a NodeJS module which helps in making HTTP requests easier. As we have to make GET requests to wikipedia API and POST requests to messenger send API. Read more about request module here
In command line type npm install request --save
This will install request module and adds it as a dependency in Package.json file. Now lets write some code to send a simple message to user.
Note: Make sure to import request module wherever you are using it.
var request = require('request');
var url = "https://graph.facebook.com/v2.6/me/messages?access_token=<PAGE_ACCESS_TOKEN>" //replace with your page token function sendHelp(id) { var options = { uri: url, method: 'POST', json: { "recipient": { "id": id }, "message": { "text": "Send wiki space 'Your query' to search wikipedia" } } } request(options, function(error, response, body) { if (error) { console.log(error.message); } }); };
This function takes a sender id as parameter and sends a JSON to send API. Read more about FB send API here
Now replace the line console.log(text);
with sendHelp(sender);
Now whenever someone sends a message to your bot page, bot replies them with a help message.
Structured messages in chat bot
Messenger platform allows 2 types of messages – Normal text messages and Structured messages. There are 3 types of templates in structured messages allowed by messenger platform. They are Button template, Generic template and receipt template.
Read more about different templates here
Code examples for structured messages are availabe here
I’m using generic template for wiki bot as shown in the demo video. Generic template can contain title, description and some buttons which is perfect for this case.
To send a structured message, we just have to send JSON to send API in a specific format.
Send wikipedia results
The final part where bot searches wikipedia and sends results. We’ll be making a GET request to https://en.wikipedia.org/w/api.php?format=json&action=query&generator=search&gsrnamespace=0&gsrlimit=10&prop=extracts&exintro&explaintext&exsentences=5&exlimit=max&gsrsearch=searchquery
After getting response fron API, results are stuffed into generic template and send to user using messenger bot send API.
function wikibot(query, userid) { var queryUrl = "https://en.wikipedia.org/w/api.php?format=json&action=query&generator=search&gsrnamespace=0&gsrlimit=10&prop=extracts&exintro&explaintext&exsentences=5&exlimit=max&gsrsearch=" + query; var myTemplate = { recipient: { id: userid }, message: { attachment: { type: "template", payload: { template_type: "generic", elements: [] } } } }; var options = { url: url, method: 'POST', body: myTemplate, json: true } request(queryUrl, function(error, response, body) { if (error) { console.log(error); } try { body = JSON.parse(body); var pages = body.query.pages; for (var i = 0 in pages) { var myelement = { title: "", subtitle: "", buttons: [{ type: "postback", title: "Read more", payload: "Nothing here, Please view in browser" }, { type: "web_url", url: "", title: "View in browser" }] }; myelement.title = pages[i].title; myelement.subtitle = pages[i].extract.substr(0, 80).trim(); myelement.buttons[1].url = "https://en.wikipedia.org/?curid=" + pages[i].pageid; if (pages[i].extract != "") { myelement.buttons[0].payload = pages[i].extract.substr(0, 1000).trim(); } myTemplate.message.attachment.payload.elements.push(myelement); } options.body = myTemplate; } catch (err) { console.log("error : " + err.message); options = { uri: url, method: 'POST', json: { "recipient": { "id": userid }, "message": { "text": "Something went wrong, please try again." } } } } request(options, function(error, response, body) { if (error) { console.log(error.message); } console.log(body); }); }) };
Code Explanation
- This function takes search query and sender id as parameters. Makes a GET request to wikipedia API and returns an array of page results which are saved to
pages
variable. -
generic template JSON is saved to
mytemplate
variable. generic template containselements
in which page results should be pushed. -
Element’s format is saved in
myelement
. Loop through each page inpages
, add title sub-title, description to payload buttonRead more
and page URL toView in browser
button and pushmyelement
toelements
array in mytemplate. -
Generic template with search results is ready. Now just send it using send API.
-
If any error occurs with Wikipedia API then send a regular help message.
Character Limits
Sending message using Send API has few limits. They are as follows :
Normal message : 320 character limit
Generic Template limits :
Title: 80 characters
Subtitle: 80 characters
Call-to-action title: 20 characters
Call-to-action items: 3 buttons
Bubbles per message (horizontal scroll): 10 elements
Note : Message won’t be sent if these limits are exceeded, so make sure to trim messages to appropriate character limits before they are sent.
Chat bot payload button
Payload button is used when bot has to be notified with some data when user clicks a button. In wikibot, payload button is used to let the bot know that user wants to read more information about the search result when he clicks read more button.
When user clicks read more button, a postback is sent to webhook. To identify whether the request is a message or post back, we can check the properties in messaging event. If its a message then there would be a message property else there would be a post back property in messaging event.
Utiliity functions
A format message function which is used to trim down page description to 320 characters.
function formatmsg(msg){ msg = msg.substr(0,320); if(msg.lastIndexOf(".") == -1) { return msg; } return msg.substr(0,msg.lastIndexOf(".")+1); }
One more sendMessage function which takes in sender id and message as parameters and sends message to that sender id. It is same as sendHelp function but takes message as a paramter. This function is used to reply to postbacks.
Putting it all together
Final handleMessage
function looks like this
function handleMessage(req, res) { var messaging_events = req.body.entry[0].messaging; for (i = 0; i < messaging_events.length; i++) { event = req.body.entry[0].messaging[i]; var sender = event.sender.id; console.log(sender); if (event.message && event.message.text) { var text = event.message.text.toLowerCase().trim(); console.log(text); if (text.toLowerCase().substr(0,4) == 'wiki') { wikibot(text.replace("wiki ", ""),sender) } else { sendHelp(sender); } } else if(event.postback && event.postback.payload){ sendMessage(sender,event.postback.payload) ; } } res.end('replied!'); }
I’ll be uploading complete source code soon. Meanwhile, try building this chat bot and think about what else can be built using this technology. The same code can be used in hook.io to deploy the bot with some changes.
Read how to deploy chat bot to hook.io
You can start using wiki bot by clicking on Message Us button below!
Wrapping up
I’ve neither optimised this bot for best use nor handled all the errors. This was built just to get started with chat bots for facebook messenger. There’s always lot more that can be done, read official documentation and build better bots.
We can use wit.ai which provides full API with artificial intelligence for interacting with users. It is also free. We can build full conversational bots using wit.ai
A paid alternative to wit.ai is api.ai which also has inbuilt integration for facebook messenger platform. Try it too, It has a free plan with limitations.
Chat bots for facebook messenger can also be used for business but has few limitations, so start building bots for your business too.
If you have and questions or feedback, comment below.
- Flutter lookup failed in @fields error (solved) - July 14, 2023
- Free open source alternative to Notion along with AI - July 13, 2023
- Threads API for developers for programmatic access - July 12, 2023
Great tutorial. Would love to see how it comes together with hook.io
Thanks, I’ll be writing another post on that soon.
Here it is – https://codingislove.com/free-microservice-hosting-hook-io/
I cannot get my bot to send back messages?
What am I doing wrong?
Bot can send messages only to you until your bot has been approved and has permission to use send message API
Hi! Thanks for the Tutorial! I have one problem: I think Facebook didn’t match to my webhook and if I want to run the post I only have errors. Where is the decleration of the messaging_event?
I only use Cloud9!
I think you forgot to setup webhooks. Did you read first part of this tutorial? Its here – https://codingislove.com/build-facebook-messenger-bot-javascript/
No…I setuped the webhook. I am only an amateur coder, so maybe I forgot something in settings or something to install?Now I got this error (The code is the same of you
re code here in the tutorial):
TypeError: Cannot read property ‘entry’ of undefined
at handleMessage (/home/ubuntu/workspace/server.js:41:30)
at callbacks (/home/ubuntu/workspace/node_modules/express/lib/router/index.js:161:37)
at param (/home/ubuntu/workspace/node_modules/express/lib/router/index.js:135:11)
at pass (/home/ubuntu/workspace/node_modules/express/lib/router/index.js:142:5)
at Router._dispatch (/home/ubuntu/workspace/node_modules/express/lib/router/index.js:170:5)
at Object.router (/home/ubuntu/workspace/node_modules/express/lib/router/index.js:33:10)
at next (/home/ubuntu/workspace/node_modules/express/node_modules/connect/lib/proto.js:190:15)
at Object.expressInit [as handle] (/home/ubuntu/workspace/node_modules/express/lib/middleware.js:31:5)
at next (/home/ubuntu/workspace/node_modules/express/node_modules/connect/lib/proto.js:190:15)
at Object.query [as handle] (/home/ubuntu/workspace/node_modules/express/node_modules/connect/lib/middleware/query.js:44:5)
Thanks for yu’re help!!!!!
Can you share your cloud9 workspace with me?
https://ide.c9.io/ajstoever/facebooktestbot
I don’t think your webhook is setup yet. Your verifyFacebook function has a problem. change this line “res.send(verify_TOKEN);” to res.send(req.query[‘hub.challenge’]);
You got an email (Email which is written by the newsletter of this page)!
Hello,
Thanks Ranjith for this awesome tutorial.
I can run the code on cloud9.
But when I deployed the code on hook.io, it seems like request module is not working.
Do we need to do anything to ask HOOK.io to install this dependency?
Code:
console.log(‘before calling api’);
request(url,options, function(error, response, body) {
if (error) {
console.log(error.message);
}
});
Hi Arpit, Request module is pre-installed in hook.io Check your hook logs to find the error.
Hi Ranjith,
Great tutorial!!! Everything is almost working. There is a small issue that when I press Read more it is not doing anything. I don’t get a reply. If I press “View in Browser” it works. Can you please help me why am I not getting a reply when I press “read more” button? Thank you.
Hi Gauhar,
Make sure that you have selected messaging_postbacks in your webhook settings and check your postbacks by logging them to console.
Also, Have you added sendMessage function which I haven’t added in the code samples above?
Join our gitter channel, I can share some code there – https://gitter.im/codingislove/Lobby
Hi sir, great article!But I need your help. I want to send the messages longer than 320 characters using facebook messenger. what should i do? Please suggest me a suitable solution. (I have created a facebook bot using node.js running on ubuntu 14.04.)
You can divide a message into 2 messages if it is more than 320 characters. There’s no other option to send a messag longer than 320 characters.
For me the bot just answer myself… Any thoughts on it?
https://gist.github.com/augustovictor/02d2d6b02828fe9d4cadb98181240533
Hi Victor,
Bot can send messages only to you until your bot has been approved and has permission to use send message API.
Go to messenger settings in your app and start a submission for pages_messaging permission as shown in this image –
Hello,
Thanks for the great tutorial!
I would like to host my bot on my own server, at OVH https://www.ovh.com/ .
Could you explain what would be the differences?
Many thanks!
Vianney
Hi Vianney, The process remains the same. Just run an express server on your VPS, point a domian to your VPS IP address and use that domain URL to setup webhooks.
Hi Ranjith,
Great tutorial, thank you so much. For unknown reasons the first two codes on top of this page (for receiving messages) are not being recognized in the c9 server.js tab. When I load the page on the right side i get: Error, wrong validation token!
Although i typed verifycode.
Also i get yellow marks in the line of code which say i need to include “global”. but when i do that i do not get any result and it says that global cannot be used. Would appreciate your help.
Hi Lewi, can you share your c9 workspace with me? I’ll have a look.
hi, i figured it out already. Thanks!