Backend processing
Conversational tasks usually need to be backed up by backend tasks. For instance, booking a table in a restaurant is not just a conversation, it also involves the action of booking a table. This is a backend task where the information concerning the booking is sent over to a booking server as an HTTP request. In this section, we will explore how to use the JSON API card to enable backend tasks.
Before we start using a JSON API card, we need a URL that can take a few parameters and carry out a backend task. Let's build a dummy backend service that can book a table given the restaurant name, number of people, and the time. To do this, we have to build a Node.js web app and host it on the cloud:
- Create a directory called Eddie-bot. In this directory, we need three files: index.js, package.json, and Procfile.
- Create the package file, package.json, which declares the packages necessary for the app, as shown here:
{
"name": "eddie-server",
"version": "1.0.0",
"description": "Eddie - Chatfuel",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Srini Janarthanam",
"license": "ISC",
"dependencies": {
"body-parser": "^1.15.2",
"express": "^4.14.0",
"request": "^2.72.0"
}
}
- Create Procfile. Procfile is a special file used by our cloud service, called Heroku, to tell the application dynos what command to run to get the app started. It should contain the following code:
web: node index.js
- Create the index.js file. Finally, we need the program that will process the request in the backend. Paste the following code:
// EddieBot webhooks
const express = require('express')
const bodyParser = require('body-parser')
const app = express()
app.set('port', (process.env.PORT || 5000))
// Process application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({extended: false}))
// Process application/json
app.use(bodyParser.json())
app.use(express.static('public'))
// Spin up the server
app.listen(app.get('port'), function() {
console.log('running on port', app.get('port'))
})
// Index route
app.get('/', function (req, res) {
res.send('Hello world, I am EddieBot webhook.')
})
app.post('/booktable/', function (req, res) {
console.log(JSON.stringify(req.body));
// YOUR BOOKING CODE GOES HERE!!
var out = {
"messages": [
{"text": "Thanks for your booking!"},
{"text": "See you soon!!"}
]
}
var outString = JSON.stringify(out);
console.log('Out:' + outString);
res.send(outString);
})
In the preceding program, we have a handle called booktable, which we will call when the user wants to book a table at a particular restaurant. To this handle, we will send a number of parameters that are necessary to make a table booking such as restaurant name, number of people, and time. Once the booking is made, the app returns a success message to the bot, which is then forwarded to the user. In the preceding code, we are not actually making the booking. We are simply assuming that the booking is made.
- To get this app operational, we need to push it on to a cloud server. To do so on Heroku, type the following commands in the console:
C:\Eddie-bot> git init
C:\Eddie-bot> git add .
C:\Eddie-bot> git commit -m "Backend Eddie Bot v1"
C:\Eddie-bot> heroku create eddie-bot-backend
C:\Eddie-bot> git push heroku master
The last command pushes the app onto the cloud, builds it, and executes the index.js program which starts a web server. We will learn more about how to build web apps in Node.js and Java in the subsequent chapters. Now, we can call the https://eddie-bot-backend.herokuapp.com/booktable URL, with the necessary parameters, to make a booking.
- Now that the dummy booking server is set up, let us call it and make a booking from the chatbot. This involves creating a flow using a number of card types. Let's assume that the user clicks the More information button on a certain restaurant, Tajmahal, for example. This needs to take the user to the block where we display information about the restaurant such as cuisine, menu, and location, with an option to book a table if the user is interested. Let's, therefore, build a basic block for Tajmahal:
- We need to add a couple more cards to this block. To set the context, we need to add a user attribute card where we set the name of the restaurant:
- We then transfer the conversation to a generic table-booking block where other necessary information can be gathered. To do this, let's create a new Table_booking_form block:
In this block, we have added a user input card where information concerning the number of people and time are sought from the user. These are stored in appropriate variables.
- Finally, to this block, we add the JSON API card, which makes the chatbot call an external server for backend processing:
In this card, we need to mention the kind of request (GET/POST), the URL to call, and the parameters to send along. The response from the backend server is returned to the user.
Great! Let's test it out in Messenger:
Notice how the text message returned from the backend server ends up in Messenger. The response from the backend server needs to be in a specific format. In index.js, we sent back a simple text message. However, other types of messages can be sent as well. For instance, the following is an example of how you can send a text block with buttons:
{
"messages": [
{
"attachment": {
"type": "template",
"payload": {
"template_type": "button",
"text": "Here are my recommendations!",
"buttons": [
{
"type": "show_block",
"block_name": "TajMahal",
"title": "TajMahal (5 stars)"
},
{
"type": "show_block",
"block_name": "SpicyTandoori",
"title": "Spicy Tandoori (4 stars)"
}
]
}
}
}
]
}
Explore the other types of messages that you can send to create more dynamic conversational cards at https://help.chatfuel.com/facebook-messenger/plugins/json-plugin/.