9 min read

One of the trending topics in the tech world this year is conversational interfaces. Everyone from big tech companies to start-ups are putting their bets on it. There is an explosion of virtual assistants and chat bots, and the number is increasing every week.

What is conversational interface and why are companies investing in it? In this post we will learn about it and build a simple bot using the Facebook Messenger Platform.

Conversational Interface

A conversational interface is an interface that allows the users to interact with computers using natural language, instead of commands or clicks and taps. It can be voice-based like Siri, Ok Google, or Microsoft’s Cortana, or it can be text-based like many Slack or Facebook Messenger bots.

Instead of building apps for different platforms, device types, and sizes, companies can now provide a way to interact with their services using voice or text, without the need to download an app or learn how to use it.

Facebook Messenger Bot

Many apps like Slack, Telegraph, and Skype now offer platforms to build virtual assistants or bots. But with more than 1 billion users, Facebook Messenger is definitely the most popular choice.

A Facebook Messenger bot works in the following way:

  1. The user sends a message to the bot using their Facebook Messenger account.
  2. The Facebook Messenger Platform will receive and post the message to the bot’s server using a webhook.
  3. The bot server will receive the message, process it, and send a response back to the Facebook Messenger Platform using HTTP POST.
  4. Facebook will forward the message to the user.

Let’s build a simple Facebook Messenger Bot.

Creating a Facebook App and Page

First we need to create a Facebook Page and a Facebook app:

  1. Create a Facebook account, if you do not have one.
  2. Create a Facebook Page. This page will work as the identity of your bot.
  3. Create a Facebook App. Enter a display name and contact e-mail, and select a category for your bot.
  4. After creating the app, click on ‘Add product’ and then select the ‘Messenger’ option. Click on the ‘Get started’ button, and under the ‘Token Generation’ section, select the page you just created. This will generate a Page Access Token, which the bot server will need to communicate with the Facebook Messenger Platform. Copy this token for later use.
  5. You also need to set up webhook so that Facebook can forward the message to the bot server, but before that, let’s build the server.

Building the Bot Server

You can use any language or framework to build the bot server. For this example, I am using Node.js.

Let’s start by creating an Express.js hello world app. Before we start, we need Node.js and npm installed. Follow the instructions on the Node.js website if you do not have these installed already:

  1. Create a new directory for your application, and inside of the app directory, create the package.json file by using the npm init command.
  2. Install Express and add it as a dependency using the npm install –save express command.
  3. Create a file called index.js with the following code:
    const app = require('express')();
    app.set('port', (process.env.PORT || 5000));
    
    app.get('/', function (req, res) {
        res.send('Helle World');
    });
    
    app.listen(app.get('port'), function () {
        console.log('App running on port', app.get('port'))
    });

Our hello world app is done. Run the node index.js command and open http://localhost:5000 in your browser. If all is good, you will see ‘Hello World’ text on the page.

Now that we have the basic app set up, let’s add the code to be able to communicate with the Facebook Messenger Platform:

  1. Install body-parser and request npm modules using the npm install –save body-parser request command. Body-parser is a middleware to parse incoming request bodies and request is an HTTP client.
  2. Now update index.js with the following code. Replace <fb-page-access-token> with the page access token generated before. You will need the validation token while setting up the webhook. Feel free to change it to anything you like:
    'use strict'
    
    const app = require('express')();
    const bodyParser = require('body-parser');
    const request = require('request');
    
    const VALIDATION_TOKEN = 'super_secret_validation_token';
    const PAGE_ACCESS_TOKEN = '<fb-page-access-token>'; // replace <fb-page-access-token> with your page access token
    
    app.set('port', (process.env.PORT || 5000));
    app.use(bodyParser.urlencoded({ extended: false }));
    app.use(bodyParser.json());
    
    app.get('/', function (req, res) {
        res.send('Helle World');
    });
    
    app.get('/webhook', function (req, res) {
        if (req.query['hub.mode'] === 'subscribe' && req.query['hub.verify_token'] === VALIDATION_TOKEN) {
            res.status(200).send(req.query['hub.challenge']);
        } else {
            res.sendStatus(403);
        }
    });
    
    app.post('/webhook/', function (req, res) {
        // Iterate over each entry
        req.body.entry.forEach(function (entry) {
            // Iterate over each messaging event
            entry.messaging.forEach(function (event) {
                let sender = event.sender.id
                if (event.message && event.message.text) {
                    callSendAPI(sender, `Message received ${event.message.text}`);
                }
            });
            res.sendStatus(200); // Respond with 200 to notify the message is received by the webhook successfully  
        });
    });
    
    function callSendAPI(sender, text) {
        request({
            url: 'https://graph.facebook.com/v2.6/me/messages',
            qs: { access_token: PAGE_ACCESS_TOKEN },
            method: 'POST',
            json: {
                recipient: { id: sender },
                message: { text: text },
            }
        }, function (error, response, body) {
            if (error) {
                console.error('Unable to send message', error);
            }
        });
    }
    
    app.listen(app.get('port'), function () {
        console.log('App running on port', app.get('port'))
    });

Here we have defined two new service endpoints. The first one responds to the GET request and will be used for verification when we set up the webhook. The second endpoint will respond to the POST request. This will process the incoming message and send a response using the callSendAPI method. For now, the server will simply send back the message received from the user.

You can deploy the server anywhere you like. Because of its simplicity, I am going to use Heroku for this tutorial.

Deploying the App to Heroku

  1. If you do not have an account, sign up on heroku.com and then install Heroku CLI.
  2. Initialize a git repository and commit the code to easily push it to Heroku. Use git init to initialise and git add . followed by git commit -m “Initial commit” to commit the code.
  3. Create a Procfile file with the following content. Procfile declares what commands to run on heroku. web: node index.js.
  4. Run the heroku create command to create and set up a new app on Heroku.
  5. Now you can run the app locally using the heroku local command.
  6. To deploy the app on Heroku, use git push heroku master and use heroku open to open the deployed app in the browser.

Setting up the Messenger Webhook

Now that the server is ready, we can set up the webhook:

  1. Go back to the app page; under the Messenger settings page, click on the ‘Setup Webhooks’ button.
  2. Enter the bot server webhook url (https:///webhook), and the validation token, and select all the options under subscription fields.

We are ready to test our bot. Go to the Facebook page you created, click on message, and send a message to the bot. If everything is good, you will see a response from the bot.

The bot is working, but we can update it to send a different response based on the user message. Let’s create a simple bot for Game of Thrones fans, where if a user types in one of the great house’s names, the bot will respond with their house words.

Update index.js with the following code:

'use strict'

const app = require('express')();
const bodyParser = require('body-parser');
const request = require('request');

const VALIDATION_TOKEN = 'super_secret_validation_token';
const PAGE_ACCESS_TOKEN = '<fb-page-access-token>'; // replace <fb-page-access-token> with your page access token

const HOUSE_WORDS = {
    STARK: 'Winter is Coming',
    LANNISTER: 'Hear Me Roar!',
    BARATHEON: 'Ours is the Fury',
    TULLY: 'Family, Duty, Honor',
    GREYJOY: 'We Do Not Sow',
    MARTELL: 'Unbowed, Unbent, Unbroken',
    TYRELL: 'Growing Strong',
    FREY: 'We Stand Together',
}

app.set('port', (process.env.PORT || 5000));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

app.get('/', function (req, res) {
    res.send('Helle World');
});

app.get('/webhook', function (req, res) {
    if (req.query['hub.mode'] === 'subscribe' && req.query['hub.verify_token'] === VALIDATION_TOKEN) {
        res.status(200).send(req.query['hub.challenge']);
    } else {
        res.sendStatus(403);
    }
});

app.post('/webhook/', function (req, res) {
    // Iterate over each entry
    req.body.entry.forEach(function (entry) {
        // Iterate over each messaging event
        entry.messaging.forEach(function (event) {
            let sender = event.sender.id
            if (event.message && event.message.text) {
                callSendAPI(sender, getHouseWord(event.message.text));
            }
        });
        res.sendStatus(200); // Respond with 200 to notify the message is received by the webhook successfully  
    });
});

function callSendAPI(sender, text) {
    request({
        url: 'https://graph.facebook.com/v2.6/me/messages',
        qs: { access_token: PAGE_ACCESS_TOKEN },
        method: 'POST',
        json: {
            recipient: { id: sender },
            message: { text: text },
        }
    }, function (error, response, body) {
        if (error) {
            console.error('Unable to send message', error);
        }
    });
}

function getHouseWord(text) {
    const house = Object.keys(HOUSE_WORDS)
        .find(function (houseName) {
            return text.toUpperCase().indexOf(houseName) !== -1;
        });
    return house ? HOUSE_WORDS[house] : 'No house word found :(';
}

app.listen(app.get('port'), function () {
    console.log('App running on port', app.get('port'))
});

Now if you type one of the family names defined in our code, the bot will respond with the family words. So if you type ‘stark’, the bot will respond ‘Winter is Coming’.

App Review

While you and other page admins can chat with the bot, to make it publicly available, you have to submit the bot for review. This can be done from the app page’s ‘App Review’ option. Fill out the form, and once approved, your bot will be accessible by all Facebook Messenger users.

Although our bot is working, it is not truly conversational. It only responds to a fix set of commands. To build a smarter bot, we need natural language processing. Natural language processors convert natural language text or audio to a format that computers can understand. There are many services that allow us to write smarter bot engines, and one of them is Wit. Wit was acquired by Facebook in 2015. You can read more about Wit and how to integrate it with your bot here.

I hope you enjoyed this post. If you have built any bot on Facebook or any other platform, please share it with us in the comment section below.

Author:

Amit Kothari is a full-stack software developer based in Melbourne, Australia. He has 10+ years experience in designing and implementing software, mainly in Java/JEE. His recent experience is in building web applications using JavaScript frameworks like React and AngularJS, and backend micro services / REST API in Java. He is passionate about lean software development and continuous delivery.

LEAVE A REPLY

Please enter your comment!
Please enter your name here