Building a Facebook Messenger Chat Bot with Node.js

In this tutorial, we’re building a Facebook messenger chatbot that will respond to users with images of cute cats and dogs. We’ll call it Aww Bot. We need to create a Facebook page for our bot to give it an identity. Our page visitors will be able to interact with it and it will respond to them.

Getting Started

Let’s start by creating a Facebook page, give it a name and username.  Also, create a Facebook app and add a Messenger product. Go to your app settings and choose your page from the drop-down in Token Generation settings. It will ask your permissions and generate a page access token for you. Our bot will use this token to make calls to Facebook messenger API to respond to users.

Setting up WebServer

We’re using Expressjs to run an HTTP server. Run  npm install express body-parser request config --save. Add this code to your index.js file to run a basic HTTP server.

Now if you visit in your browser, you’ll see a Hello World! response.

Workaround for HTTPS

Before moving on to WebHooks, we need to configure HTTPS for our dev environment. Messenger won’t accept your WebHook URL if you’re using a self-signed SSL certificate. The only way to get a free trusted signed certificate is to use Letsencrypt. Letencrypt only issues certificates to domains and not IP addresses. Instead, we’ll use ngrok to expose our local dev environment through NAT and access it from ngrok public HTTPS URL.

Setup ngrok

Setting up ngrok is easy. All you have to do is to download a zipped binary from their site, unzip and run it. Run

./ngrok http 80

to expose your HTTP port. Make sure you forward port 80 to 8989 in your router WAN settings. ngrok will generate a public HTTP and HTTPS URL for your local dev environment.

Creating WebHooks

Messenger uses WebHooks to authenticate and pass event data to our application. They are simple HTTP callbacks that will receive incoming events data like received messages from messenger bot. We’ll use Node.js body parsing module to parse out data from GET and POST requests. Now add this route to your application to handle WebHook verification request.

Now open Messenger product settings and setup WebHook for your application. Copy your ngrok HTTPS URL and paste it in Callback URL.  Paste your randomly generated VERIFY_TOKEN in Verify Token field. You should be able to verify and save it if your WebHook is accessible and your verification token matches with the one in your code.

After saving, select your page from the drop-down to subscribe your webhook to the page events.

Now create a post webhook route to handling post events from messenger app. Add following code to your application.

We’ve configured our app to handle two types of events to our webhook events, messages, and postback. To test your webhook, open messenger and send a message to your page. You’ll see PSID of the sender and web_event logged to console along with the payload. Now we’ll write handlers to handle these events.

handleMessage() method will handle incoming messages and handlePostback()  method will handle incoming postbacks. Update your webhook and call these methods.

Whenever we’ll receive a message or postback, data will be passed to these handlers along with the PSID of the sender.

Configuring Welcome Screen and Get Started Postback Event

When a new user starts a conversation with Messenger bot, it shows them a Get Started button. We can configure a custom postback event for it. We can use this get started postback to tell the user about our bot and how they can interact with it. To set a custom greeting for your page run this curl command from your terminal.

We’re configuring Aww Bot to show this message to users asking them if they are ready to see the cutest cats and dogs? To set a custom postback run this command from your terminal.

App Configuration

We’re using config npm module to store page access token in a separate config file. Create a config directory in your project. Also, create a default.json file in it.

Add your page access token to config and add this file to .gitignore. We’ll retrieve page access token in callSendAPI()  method by calling  config.get('').

Handling Get Started Postback Event

We’ll write a method askTempate() that will return a valid response object for our messenger API. callSendAPI() will send that message template to the user. Add these methods to your app.

We’ll send our user a message with two buttons with custom postback payload. When they will select an option, a postback event will be sent back to our webhook and we’ll handle them within our event handlers.

Handling Custom Postback Events

Update your postback handler function with this code.

When a user will click on Cats option, our webhook will receive a postback event with CAT_PICS payload. Dogs option will send back a postback with DOG_PICS payload. We’ve added another method imageTemplate() that will return an image template with an image URI of a cat or dog.

Creating a Mock API

Let’s create a mock API to return images of cats and dogs for our image template. Create a pics.js file and add this code to it.

Now require it in your app.

images = require('./pics');

Add this method to return image template.

We’ll iteratively retrieve images from the array and send them to requesting user until we run out of images. We’ll start the count from 0 in case we run out of images. Add this method to keep a record of requesting users.

We’ll store every user’s PSID in users object as a key. If it doesn’t exist, we’ll create a new user. We’ll update count of user object every time a user requests an image of a cat or dog. We’ll then return an absolute path to the image which will be used in the image template. We’ll send image template as a response to Cat and Dog button postbacks.

We’re also passing a callback to callSendAPI() method to send ask template after sending them an image. On success, we’ll invoke this callback, which will send user an ask template. We’re doing this because of asynchronous nature of callbacks, we’re making sure that user receives ask template after receiving an image.

I’ve created a Github repository for you guys. If you are getting any errors, please mention them in comments. Read Github repository file for instructions on how to install and configure it. To make your messenger bot accessible to everyone, your Facebook apps need to be approved. If your app is not approved, your bot will only be accessible to administrators and testers of your app.

Here’s a working demo of Aww Bot.

Share this post

10 thoughts on “Building a Facebook Messenger Chat Bot with Node.js”

  1. hi this is great 🙂 . but I am following you at the moment.

    I have a problem.

    I tried to greet welcome message such as below

    curl -X POST -H “Content-Type: application/json” -d ‘{
    “get_started”: {“payload”: “GET_STARTED”}
    }’ “

    I got this message

    {“error”:{“message”:”Unsupported post request. Object with ID ‘me’ does not exist, cannot be loaded due to missing permissions, or does not support this operation. Please read the Graph API documentation at https:\/\/\/docs\/graph-api”,”type”:”GraphMethodException”,”code”:100,”error_subcode”:33,”fbtrace_id”:”AXnPdRl+qyf”}}

    What should I do?

    1. Hey Maggie ,

      How did you fixed this error . As I am getting same error but couldn’t able to solve it .
      Can you please guide me the fixing steps.

  2. Thanks for the tutorial

    minor error above

    const askTemplate …blah….
    should be
    function askTemplate …blah….

    const callSendAPI

    should be a function

    the git repo is correct

  3. Thanks for writing this.

    hung up with not able to see output of function askTemplate(text)
    as in : I never see the Cat or Dog buttons appear.

    have been adding console.log outputs to trace progress.

  4. Hi, I don’t know how to “Configuring Welcome Screen and Get Started Postback Event” in node.js coding. Can we setting the Welcome Screen in index.js?
    Can you give an example?

  5. Can you please guide on how to open “Messenger product settings”? I am not able to find that option.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.