Chatbots are all the hype these days. You can use chatbots to stay updated with current events, order a ride sharing vehicle, or even schedule an appointment. But have you ever considered building your own chatbot?
In this guide, I'll teach you how to create a location-aware chatbot with HERE Location Services and Twilio using Node.js. The chatbot will enable users to search for places near a location. For example, a user could search for "Sandwiches near Central Park New York City" or "Subway near 701 Pike Street Seattle." That's both places and addresses you can search for!
To accomplish this, we're going to be using a few different APIs:
If you get lost during the Twilio setup, give this helpful guide a read.
Part 1: Starter Code & Configuration
To get started, you'll need a few
npm modules installed:
To install these modules, run
npm install package-name in the command line. (Alternatively, give this package.json file a try.)
We're also going to need to install ngrok to run a tunnel providing an externally available URL to our server.
server.js. This file will enable us to send and receive messages. Paste the following code:
Don't forget to paste your HERE and Twilio API credentials into their respective fields.
We'll want to configure our server to reply to messages sent to our Twilio phone number.
Once Twilio is configured correctly, the above code will enable our bot to reply with 'Hello, there!' anytime you text your Twilio phone number.
To get the server up and running, you're going to want to run
node server.js in the command line. In order to make your server publicly accessible, you'll want to run the command
ngrok http 1337 (on macOS a quick way to do this is to run these two commands on different tabs). Port 1337 is now exposed to the public internet.
Copy the forwarding URL (highlighted in the below screenshot) provided by the ngrok console.
Take the copied URL and configure it as a webhook for your phone number. Under the Messaging header, paste this URL followed by /sms in the message comes in field.
Once you've got that configured, try sending a message to your Twilio phone number. You should get a friendly reply saying 'Hello, there!'
Part 2: Integrating HERE Location Services
Now that you've got a functional SMS messaging service, let's make this chatbot location-aware by equipping it with HERE Location Services.
We want our bot to perform the following way:
- User texts the chatbot with two parameters: a search query and a location. For example: Pizza near 701 Pike Street Seattle
- Chatbot geocodes the search query from a POI or an address to coordinates (latitude and longitude)
- Chatbot searches for places based on the search query near the geocoded location
- Chatbot replies with three relevant places and gives the option to learn more about a place
- The user replies to learn more about a certain place
- Chatbot replies with address of the requested place
Let's change the contents of the
app.post block to look like this:
Let's break down the above code.
- The variable
incomingis the plain text sent by the user to the chatbot. We can split this variable into two parts by using
incoming.split(' near '). This by no means is the best way to parse text, but we'll do it this way for simplicity's sake.
searchQuery: the query we'll search for with the Places API
locationString: the string of the location (address or POI) we'll geocode into coordinates
- We'll pass our
hereCodeinto a variable
geocodeURLto create a request URL to the HERE Places API
request.getconstructs the request and gives us back parsed JSON containing our results
Once we've received our reply for the API, we can extract the latitude and longitude from the response. Be sure to place the remaining code examples all within the
Now that we've transformed our location string into coordinates, we can start searching for places that fit the constraint of the search query and location. To do so, we're going to construct a HERE Places API search (within the geocode request).
We provided the geocoding request the following parameters:
at: latitude and longitude of where to search
q: the query to search for. I've added .replace(/ /g, '+') to replace the spaces with plus signs to make a more friendly URL
tf: text format of response
app_code: access credentials for the API
I'd like to return 3 results to the user each time, but sometimes there aren't always 3 results available for a particular query, so I created the variable
resultAmount to show the appropriate amount of available results.
Let's start processing the results from our API response and begin preparing our reply to the user.
responseMessage sets up the first line of our reply message to the user: Here are the 3 closest Mexican restaurants to 701 Pike Street Seattle.
We loop through the amount of appropriate results (determined with the
resultAmount variable) to do the following tasks:
- Add a place's name, category, and address into a dictionary. We'll be using this dictionary later to reference information about a place
- Append additional text onto the reply to the user. We add:
- A number the user can reply with to learn more about a place
- The name of the place
Sometimes the Places API returns subcategories of the search query, not actual places. To avoid and filter out subcategory results, we can add a simple conditional blocking subcategory results. In the event we do come across a subcategory instead of a place, we increment
resultAmount to ensure we return the appropriate amount of results (usually 3).
Now that we've created both our dictionary of places and our text reply to the user, let's go ahead and send something via SMS.
Voila! The user is now sent a list of results relevant to their search query and location! Give it a try with "Sushi near Pike Place Seattle"
Part 3: Additional Information About the Place
We've written code to receive messages, geocode locations, search for places, and send messages. At this point, the user will now receive a message with something along the lines of:
Here are the 3 closest Hamburgers places to you:
(1) Kidd Valley Hamburgers
Reply with # to learn more information
Our service encourages the user to reply with a number to learn more about a particular place. To enable this feature, we're going to want to add some conditionals within our
app.get() block. Modify your code to fit this structure:
if (incoming.length > 1)is designed to accept the user's first message. The initial message to begin the process must contain a search query, the word 'near', and a location string. This will be longer than one character.
else if (places.length > 0 && incoming.length == 1)is designed to accept the user's second message. We check to make sure that the places dictionary is empty and that their incoming message is only one digit in length (the second message is supposed to be an integer between 1 and 3).
There are plenty of additional ways to check this case, but we'll stick with these conditions.
else if statement, let's insert the following code:
We're now able to send the address to the user about the requested place.
Part 4: Error Handling & Advanced Functionality
To ensure messages that don't follow the strict 'near' format don't crash our service, let's add some error handling.
Right below the
if (incoming.length > 1) statement, let's add:
This ensures the user's first message contains a 'near' so we're able to extract the search query and location string.
Additionally, let's add this
if statement right after we create our
son variable in the geocoding request:
In the event no places are returned from the Places API query, we send a message informing the user to try again.
Congratulations, you've created a functioning location-aware chatbot! You can check out the full source code here.
There's no need to stop here! We've created just a simple version of a location-aware chatbot. What additional features could you bring to this chatbot using HERE APIs? Try enhancing this project by giving our Traffic, Routing, Transit, Weather, and Positioning services a shot.
Update: Now you can watch this hands on tutorial on YouTube!