Build a Travel Recommender with Twilio MMS, Flask, and Airtable

July 26, 2022
Written by
Reviewed by
Dainyl Cua
Twilion

Build a Travel Recommender with Twilio MMS, Flask, and Airtable

Are you looking for your next travel destination, but can't decide on where to travel to? For National Anti-Boredom Month, consider building this travel recommendation bot to make the decision for you.

In this tutorial, you will use Twilio's Programmable Messaging API, Python, Flask, and Airtable to build a travel recommendation bot. After messaging the bot, the bot will reply with an image and location of your next travel destination.

Prerequisites

To continue with this tutorial, you will need:

Set up your project environment

Before you can dive into the code, you will need to set up the project environment on your computer. First, you should create a parent directory that holds the project. Open the terminal on your computer, navigate to a suitable directory for your project, type in the following command, and hit enter.

mkdir travel-bot-project && cd travel-bot-project

As a part of good practices for Python, you should also create a virtual environment. If you are working on UNIX or macOS, run the following commands to create and activate a virtual environment. The first command creates the virtual environment, and the second command activates it.

python3 -m venv venv
source venv/bin/activate

However, if you are working on Windows, run these commands instead:

python -m venv venv
venv\bin\activate

After activating your virtual environment, you should install some Python packages. For this tutorial, you will use the following packages:

To install these packages, run this command:

pip install flask python-dotenv twilio pyairtable

As a part of good programming practices, you should store sensitive information inside a secure location. To do this, you will store values in a .env file as environmental variables. In the travel-bot-project directory, open a new file named .env (notice the leading dot) and paste the following lines into the file:

AIRTABLE_BASE_ID=XXXXXXXXXXXXXXXX
AIRTABLE_API_KEY=XXXXXXXXXXXXXXXX

If you are using GitHub, be sure to include the .env file into your .gitignore file.

Your project environment is now set up, but you must first configure your environmental variables in the .env file. "XXXXXXXXXXXXXXXX" are simply placeholder values for the Airtable base ID and API Key. The next section will cover how to get these values.

Set up the Airtable base

Airtable is a useful service for collaboration, as well as managing data and spreadsheets. For this project, I used Airtable to create a spreadsheet of travel destinations, including name, location, and an image URL. You can set up your own Airtable base by importing a CSV file or using my Airtable base instead. If you don't plan on changing the data, I recommend skipping to the section ahead, titled Use my Airtable base, to save some time.

Set up your own Airtable base

To set up your own Airtable base, you can import the data as a CSV. First, go to the copy of the CSV file that I used on my GitHub repository of the project. Then, left click on Raw. After the raw file displays, right click on the page, select Save As, and save the file as a CSV.

Github webpage of Travel Destinations CSV File with raw button highlighted

After creating your Airtable account, go to Airtable's Homepage and click Add a base to create an empty base. After the empty base is initialized, click Add or Import to make an options menu appear. Under QUICK IMPORT FROM click on CSV file to import a CSV file.

Empty initialized Airtable base. CSV File is highlighted in a dropdown menu labeled Add or Import

After selecting and uploading the CSV file, a window labeled Import your file will appear. Select Create a new Table from the dropdown menu and click Next to continue.

Afterwards, another window will appear, labeled Create a new table in Untitled Base.

Create a new table preview window with column headers highlighted

Click on the column headers for Name and Location and change their data types by selecting Single Line Text. Then, click on the column header for Image and change its data type by selecting URL. Your data in the preview should now look like this:

Data type in for columns in Create a new table preview window is changed

Lastly, rename Untitled Base to Travel Destinations and Imported table to Travel. You can also delete Table 1 if you would like. The base should look similar to my Airtable base in the section below.

Use my Airtable base

Alternatively, you can check out the Airtable base that I used for this project (be sure to click the link, so you can accept the invitation and access its contents).

Below is a sample of what the spreadsheet looks like, with columns for Name, Location, and Image:

Data in Airtable base labeled Travel. Columns are labeled Name, Location, and Image

After that, continue to the next steps to get the Airtable base ID and API key.

Access the Airtable base ID and API Key

To access the Airtable base ID, simply go to the Airtable base that you are using. The Airtable base ID part of the URL for the Airtable base. The URL should be formatted along the lines of "https://airtable.com/AIRTABLE_BASE_ID/…", with the actual Airtable base ID beginning with "app".

So, using the example of Airtable base used for this project, the Airtable base ID is app6P8MkJ7TgjQ0ys:

URL to Airtable base

If you had set up your own Airtable base, your Airtable base ID would be different. Afterwards, replace the "XXXXXXXXXXXXXXXX" placeholder for AIRTABLE_BASE_ID in the file named .env you created earlier with the Airtable base ID you had just obtained.

To get an Airtable API key, navigate to the Account Overview page. Scroll down to the section labeled <> API, click Generate API key, and copy your API key.

Clicking on "Generate API Key" on the Accounts Overview page creates a read-only API Key

Afterwards, replace the "XXXXXXXXXXXXXXXX" placeholder for AIRTABLE_API_KEY in the file named .env you created earlier with the Airtable API key you had just copied.

You are now ready to begin coding the application.

Create your application

Here is the expected flow of the application:

  • A user messages the Twilio phone number.
  • The Twilio phone number responds with a randomly chosen travel destination, providing the user an image, name, and location.

In the travel-bot-project directory, create a new file named app.py. To follow the expected flow, copy and paste the following code into app.py:

import os
from pyairtable import Table
from flask import Flask
from twilio.twiml.messaging_response import MessagingResponse
import random

app = Flask(__name__)
AIRTABLE_BASE_ID = os.environ["AIRTABLE_BASE_ID"]
AIRTABLE_API_KEY = os.environ["AIRTABLE_API_KEY"]

@app.route('/send-travel-rec', methods=['POST', 'GET'])
def sms_reply():
  """ Access Airtable base here """

  """ Pick destination and initialize name, location, image here """

  # Initialize TwiML response
  resp = MessagingResponse()

  # Add a text message
  msg = resp.message('Looking for a place to travel? '\
    f'Consider going to {name} in {location}!')

  # Add a picture to the message
  msg.media(image)

  return str(resp)


if __name__ == "__main__":
    app.run(debug=True)

This code serves as an outline of the application. The necessary modules are imported at the top, environmental variables loaded in, and the Flask application is initialized with the /send-travel-rec endpoint.

Notice that name, location, and image haven't been initialized yet. In order to initialize these variables, you first need to access the Airtable base. Replace """ Access Airtable base here """ with the code below:

  # Access and format Airtable base
  table = Table(AIRTABLE_API_KEY, AIRTABLE_BASE_ID, "Travel")
  destinations = table.all()

In the code snippet above, the table is initialized with the environmental variables AIRTABLE_API_KEY and AIRTABLE_BASE_ID from the .env file, and the name of the table, "Travel", is provided. table.all() returns a list of dictionary objects for each entry in the spreadsheet.

Next, the application should randomly choose a destination from destinations and acquire its name, location, and image url. To do this, replace """ Pick destination and initialize name, location, image here """ with the code below:

  # Randomly choose destination and obtain values
  destination_pick = random.choice(destinations)['fields']
  name = destination_pick['Name']
  location = destination_pick['Location']
  image = destination_pick['Image']

In the code snippet above, the destination is randomly chosen from destinations with random.choice(destinations). Since random.choice(destinations) is a dictionary object, the name, location, and image url is accessed with the dictionary key, 'fields'. The resulting variable destination_pick is also a dictionary object. Afterwards, the variables name, location, and image are also initialized with their respective dictionary keys. You can learn more about Python data structures, such as dictionaries, with this link to documentation on Python data structures.

Your code should look something like this:

import os
from pyairtable import Table
from flask import Flask
from twilio.twiml.messaging_response import MessagingResponse
import random

app = Flask(__name__)

AIRTABLE_BASE_ID = os.environ["AIRTABLE_BASE_ID"]
AIRTABLE_API_KEY = os.environ["AIRTABLE_API_KEY"]

@app.route('/send-travel-rec', methods=['POST', 'GET'])
def sms_reply():
  # Access and format Airtable base
  table = Table(AIRTABLE_API_KEY, AIRTABLE_BASE_ID, "Travel")
  destinations = table.all()

  # Randomly choose destination and obtain values
  destination_pick = random.choice(destinations)['fields']
  name = destination_pick['Name']
  location = destination_pick['Location']
  image = destination_pick['Image']

  # Initialize TwiML response
  resp = MessagingResponse()

  # Add a text message
  msg = resp.message('Looking for a place to travel? '\
    f'Consider going to {name} in {location}!')

  # Add a picture to the message
  msg.media(image)

  return str(resp)


if __name__ == "__main__":
    app.run(debug=True)

However, the application is not quite done yet. Continue to the next section to figure out how to configure the webhook and how to run the application.

Set up the ngrok tunnel and webhook

If you were to run the program prematurely, you would not receive a message from the phone number. There are two things that need to be addressed. First, you need to connect your local server to a publicly accessible URL by opening up a ngrok tunnel to your local machine. Second, you need to connect the Twilio phone number to the application by using a webhook.

After having installed and authenticated ngrok on your machine, open another command prompt window, and run this command to open a tunnel to port 5000.

ngrok http 5000

Afterwards, your command prompt should something look like this:

Running ngrok in the command prompt, a list of session statuses is displayed, including a forwarding URL.

 

Next to the word Forwarding there should be a URL that points to https://localhost:5000. Your URL should be different than the one shown above. Copy that URL, as it will be used to set up the webhook. Leave this command prompt open.

On the left-hand side of your Twilio console, navigate to Phone Numbers > Manage > Active numbers. Clicking Active numbers will take you to the Active numbers page. Click the link for the phone number that you will be using for this application.

This will take you to the configure page for the phone number. Scroll down to Messaging and paste the URL you copied from before to the A MESSAGE COMES IN section, and add “/send-travel-rec” at the end of the URL. This is the Flask application's endpoint that the TwiML response is sent to. So your URL should be something like https://your-ngrok-url.ngrok.io/send-travel-rec  and should be pasted like the example below:

Twilio Phone Number configuration form where the phone number is configured to send text messages to a webhook with the ngrok Forwarding URL.

Click Save at the bottom of the page to update the number’s settings. You are now finally ready to run the application.

Run the application

To run the application, run this command in the travel-bot-project directory where the virtual environment is activated.

flask run

Afterwards, your application should be working properly. Whenever someone sends a text message to your Twilio phone number, the Flask application will receive a request at the /send-travel-rec endpoint, fetch data from Airtable, and return a recommendation to the user. Go ahead and text the Twilio phone number and you should receive a travel recommendation along with a photo. Use it to find your next travel recommendation or learn more about the world. Have a friend test it out, and make plans!

Conclusion

Congratulations on building an application with Twilio's Programmable Messaging API. In this tutorial, you learned how to build an application that gives indecisive users travel recommendations. The application also uses Airtable to store the travel destination, location, and image URL. It then uses these fields to reply to the user with an image and travel destination. Feel free to customize this application to your liking. For example, you could add more travel destinations to the Airtable base or include a visited column to have it only recommend unvisited destinations. You can also reference my GitHub repository of the project.

Ready to take off with Twilio and Python? There's so much more you can do with Twilio and Python. To get you started, you can check out the Twilio Python Quickstart or the Twilio Python Helper Library. Even a beginner can make exciting applications using Python and Twilio SMS, such as building a sentiment analyzer for slang and emojis or learning how to forward SMS messages.

Animation of man waving in a plane

Johnny Nguyen is an intern developer on Twilio’s Developer Voices Team. He enjoys creating ironic coding projects for others to learn and enjoy. When he’s not napping or watching TikTok, he can be reached at ngnguyen [at] twilio.com.