The purpose of this repo is to provide instructions for how to setup a Facebook Messenger Chatbot using API.AI, Node.js and Mongo.db. If you have any question or suggestions, feel free to create an issue.
In this tutorial the API.AI is used as your NLP (Natural Language Processor) and Node.js for backend operations that can't be done with API.AI. If you don't have any backend operation, just ignore the Node.js/Mongo.db sections.
The following picture shows an architectural overview of how the full example will operate. The API.AI interacts directly with the Facebook Messenger Platform, while the Node.js server will only interact directly to the Messenger Platform if notification messages are required.
-
Create your Facebook App at https://developers.facebook.com/apps
-
Go to the Messenger tab and select your Facebook Page to generate an Page Access Token. Make sure to save it somewhere, as it will be used in your Node.js sever.
-
After you have an Page Access Token, you have to configure your API.AI webhook to explore the messenger platform. Head over to API.AI and follow the steps at Section Setup API.AI for how to setup the Facebook messenger One-click integration.
-
Setup the webhook with the Callback URL and Verify Token from the Facebook messenger One-click integration at your API.AI agent. Make sure to check the Subscription Fields required for your bot interaction (check messages and messaging_postbacks at least).
-
Select a page to subscribe your webhook to the page events
-
Create an account at API.AI, and create your first Agent. For more info about API.AI, check their documentation.
-
Go to Integrations tab and setup the Facebook messenger One-click integration. The Verify Token can be any string, and the Page Access Token is the token generated at your Facebook App.
-
Go to Fulfillment tab and setup the Webhook with your Heroku app url endpoint. After this setup, your can now enable the Webhook option at your intentions.
If you don't want to follow this whole section, you can download this repo and update the environment variables and Heroku informations.
-
First things first. We will use Heroku platform for deployment. As so, you will need a Heroku account and Heroku toolbelt installed locally. You will also need MongoDB to run the server locally.
-
Install Node. If you already have it installed, update npm to the latest version.
sudo npm install npm -g
-
Create your project folder and init a Node project.
npm init
-
Install the extra dependencies. Express for the server, Request for easy html requests, Body-Parser for message processing, and Mongoose for data storage.
npm install express request body-parser mongoose --save
-
Create an index.js file and copy the following code:
'use strict' var express = require('express'); var app = express(); var port = process.env.PORT || 5000; var mongoose = require('mongoose'); var database = require('./configs/database'); // Pull information from HTML POST (express4) var bodyParser = require('body-parser'); // Mongoose connection mongoose.connect(database[process.env.NODE_ENV].url); // Parse application/x-www-form-urlencoded app.use(bodyParser.urlencoded({'extended':'true'})); // Parse application/json app.use(bodyParser.json()); // Parse application/vnd.api+json as json app.use(bodyParser.json({ type: 'application/vnd.api+json' })); // Routes require('./routes/api-ai.js')(app); // Listen (start app with node index.js) app.listen(port);
-
Create an database.js file with the following code inside the directory /configs. This file uses environment variables to provide the url for the database.
module.exports = { development: { url: process.env.MONGODB_URI }, staging: { url: process.env.MONGODB_URI }, production: { url: process.env.MONGODB_URI } }
-
Create an api-ai.js file with the following code inside the directory /routes. This file contains the webhook endpoint for API.AI, and the index endpoint.
module.exports = function(app) { // Index route app.get('/', function (req, res) { res.send('Welcome to the Index Route'); }); // API.AI webhook route app.post('/webhook/apiai/', function(req, res) { // Your code for different actions sent by API.AI res.status(200).json('Sucessfull'); }); }
-
Create an Procfile to tell Heroku where the server is.
web: node index.js
-
Setup your local environment variables(MongoDB, Node.js and Facebook Page Access Token) to test the server locally.
export MONGODB_URI = mongodb://localhost/your-bot-database export NODE_ENV = development export FB_PAGE_ACCESS_TOKEN = YOUR-FACEBOOK-PAGE-ACCESS-TOKEN
-
Commit all code, install mLab MongoDB, and deploy to Heroku:
git init git add . git commit --message "first commit" heroku create app-name heroku addons:create mongolab:sandbox heroku config:set FB_PAGE_ACCESS_TOKEN=YOUR-FACEBOOK-PAGE-ACCESS-TOKEN git push heroku master
-
Install MongoDB on your local environment using your favorite installer: https://docs.mongodb.com/manual/administration/install-community/
-
Install mLab MongoDB on your Heroku app, if you haven't done it before:
heroku -a app-name addons:create mongolab:sandbox
-
Configure your MONGODB_URI on your local environment you haven't done it before:
export MONGODB_URI = mongodb://localhost/your-bot-database
-
In this project we are using Mongoose, as so, we need to define the model's that we will persist. For simple demonstration we will persist the Facebook User data of every user that interacts with our Chatbot. Create an user.js file inside /models with the following code:
// Load mongoose since we need it to define a model const mongoose = require('mongoose'); module.exports = mongoose.model('User', { facebookId: { type: String, required: true }, firstName: String, lastName: String });
-
Create an user.service.js file inside /services with the following code:
const User = require('../models/user'); const request = require('request'); module.exports = { getFacebookData: getFacebookData, saveUser: saveUser } // Get user data Messenger Platform User Profile API and save it on the MongoDB function saveUser(facebookId, firstName, lastName) { getFacebookData(facebookId, function(err, userData){ let user = { facebookId: facebookId, firstName: firstName || userData.first_name, lastName: lastName || userData.last_name }; User.collection.findOneAndUpdate({facebookId : facebookId}, user, {upsert:true}, function(err, user){ if (err) console.log(err); else console.log('user saved'); }); }); } // Get User data from Messenger Platform User Profile API **NOT GRAPH API** function getFacebookData(facebookId, callback) { request({ method: 'GET', url: 'https://graph.facebook.com/v2.8/' + facebookId, qs: { access_token: process.env.FB_PAGE_ACCESS_TOKEN } }, function(err, response, body) { let userData = null if (err) console.log(err); else userData = JSON.parse(response.body); callback(err, userData); }); }
-
Update your api-ai.js file with the following code to to call the saveUser function from user.service and save every user that interacts with the Chatbot:
const userService = require('../services/user.service'); module.exports = function(app) { // Index route app.get('/', function (req, res) { res.send('Welcome to the Index Route'); }); // API.AI webhook route app.post('/webhook/apiai/', function(req, res) { // Your code for different actions sent by API.AI res.status(200).json('Sucessfull'); // Save User to MongoDB userService.saveUser(req.body.originalRequest.data.sender.id); }); }