A couple weeks ago, an introduction post on Condé Nast bot efforts mentioned an SDK undergoing development. That SDK is ready for bot builders and we've released it to open source community. You can find it on npm and GitHub. In this post, we will walk through building a bot using the Launch Vehicle FBM SDK.

If this is your first time building a Messenger bot, read through Facebook's Quick Start Guide. You will need access to a Facebook page and will need to create a Facebook application through the developer portal. This post is not going to cover all the ins and outs of setting up a page and application since there are a wealth of existing articles that dive in that process. The rest of this post is going to assume that these things are setup and ready to go.

To get started, some basic project setup.

mkdir messenger-bot
cd messenger-bot 
npm init
// accept the default values
npm i --save launch-vehicle-fbm
// the SDK is installed!

The Launch Vehicle SDK uses node-config for application configuration. This necessitates a config directory at the top level of the code base. The SDK ships with a base config to get started. Copy it to the top level of the application; it will not need any modifications to get a bot running with this guide.

cp -r node_modules/launch-vehicle-fbm/config .

Messenger requires that the web hook is publicly accessible address. For development, localtunnel provides a means to expose a local port with such an address. Install localtunnel globally with npm i -g localtunnel. By default, localtunnel generates random subdomain names each time it runs. Use the subdomain option to specify a desired subdomain during development. This removes the need to update the web hook address if localtunnel stops or restarts.

lt --port 3000 --subdomain mytunnel 

On a successful startup, localtunnel will output the public URL: your url is: https://mytunnel.localtunnel.me. We'll use this to update the bot's webhook in just a moment.

Another tool that will help make development more efficient is nodemon. Nodemon monitors the codebase for changes and restarts the application when needed.

npm i -g nodemon

To get the full benefit of nodemon, add two new scripts to the packages.json file:

"dev": "DEBUG=* nodemon -x npm start",
"start": "node index.js",

Now npm run dev will watch for code changes and make sure the application is running the latest updates. This removes the need to manually restart the bot each time a code change is made.

The last setup step before we get to code is to initialize the environment values. This is where the application's identifiers and secrets will be kept. There are four keys items from the setup process that the SDK looks for in the environment:

  • Facebook application ID
  • Facebook page ID
  • Messenger application secret
  • Messenger page access token

Add these items to an .env file at the top level of the application. Also add the .env file to the project's .gitignore, as saving these values to the git repository is ill advised. A fifth value, the Messenger validation token, is also required. This is the string that populates the Verify Token field for the application’s web hook.

Here is an example .env file:

FACEBOOK_APP_ID=1234567890123456
FACEBOOK_PAGE_ID=1029384756
MESSENGER_APP_SECRET=0123456789abcdef0123456789abcdef
MESSENGER_VALIDATION_TOKEN=validate-me
MESSENGER_PAGE_ACCESS_TOKEN=ThatsAReallyLongStringYouGotThere

Export these values into the environment where the application will run via export $(cat .env | xargs).

Now we're ready to write some bot code! Getting started with an application only a few lines. Create an instance of the SDK and call the start function. This will spin up an Express server with a few endpoints, including the webhook for Messenger.

const { Messenger } = require('launch-vehicle-fbm');    

const messenger = new Messenger();
messenger.start();

Once the bot is running, open http://localhost:3000/, or your localtunnel URL, in a web browser. You should see a thumbs up indicating the server is running.

At this point, make sure to update your Facebook application's web hook. Use the localtunnel public URL and the same string specified in the .env file for the Messenger validation token. As long as localtunnel and npm run dev are still running, the webhook should successfully validate.

Next, we will add some code to have the bot to respond to greetings. The SDK checks messages from users against common greetings with a regular expression. Matching messages emit as greeting events which the application catches and responds to.

// update the SDK import to:
const { Messenger, responses } = require('@condenast/launch-vehicle-fbm');

// EVENT HANDLERS
/////////////////    

messenger.on('text.greeting', ({senderId, session, firstName, surName, fullName}) => {
  const greeting = new responses.Text(`🤖  beep bop boop. Hello ${fullName}, I am a bot.`);
  return messenger.send(senderId, greeting);
});

Restart the application and the bot will now respond to a user sending it a hello or what’s up.

Along with greetings, responding to help requests is a common best practice for all bots. The SDK enables this in a similar manner to the greetings support, with only a few lines of code. Add the code below and send a help message to the bot.

messenger.on('text.help', ({senderId}) => {
  const help = new responses.Text(`🤖  I am here to offer my services to assist you.`)
  return messenger.send(senderId, help);
});

To enable wider conversational support, the bot needs to handle text events. The text event emits with any part of user conversation outside of greetings or help. This includes postbacks and quick replies. Oftentimes users will see the contents sent with a postback or quick reply and mimic it via text. Emitting a consistent text event for these cases ensures consistent handling.

messenger.on('text', ({senderId, text, source}) => {
  const echo = new responses.Text(`Echo echo: "${text}"`);
  return messenger.send(senderId, echo);
});    

messenger.on('message.text', ({senderId, text, source}) => {
  debug(`message.text event processed: ${text}`);
});

The message.text event is broader than text and emits for any text that the user sends. The message.* events serve edge cases where response logic depends on the input method.

For image support, the SDK emits message.image with the URL of the image. Adding a simple handler and using the Image object enables the bot to echo the sent image back to the user.

messenger.on('message.image', ({senderId, url}) => {
  const imageEcho = new responses.Image(url);
  return messenger.send(senderId, imageEcho);
});

Before we wrap up, let's briefly review the example bot in its entirety. It contains handlers for the common events the SDK emits based on user input. It responds to greetings, requests for help, images, and other text input in less than forty lines of code. If you are looking for the entire example, the enterprise-fbm GitHub repo contains the entire bot example available to clone or download. Using the example as a starting point, the sky's the limit. Try expanding the logic in the text handler to vary responses based on the user input.

Next time we'll cover more built-ins for logging & analytics the SDK provides to help make your bot awesome.