Polly Politician is looking to get voted into office. She has teamed up with Selly Celebrity, and together they are running an SMS voter campaign.
This article will explain how to integrate Contentful and the Twilio Programmable SMS API with the Flask microframework for Python. The article will also highlight how to set up webhooks in Contentful, and how to deploy it all to AWS Lambda to make the app genuinely serverless — all in the name of getting Polly Politician as many votes as possible.
We’re putting together a Python Flask app that will send campaign messages like "Vote for Polly — she’s the best" to potential voters via SMS.
We’ll also configure webhooks to make sure that whenever the campaign manager publishes a new campaign message, that message will be sent to Twilio’s Programmable SMS API and subsequently delivered to voters.
By reading this article you will learn how to:
We start by installing the packages for Flask, Contentful and Twilio like so:
And to make sure that we have debugging in place, and to point out our soon-to-be-created Flask app, we’ll run:
The flask app will have a single function called runVoterCampaign(). So the initial version of our Flask app will look like so:
In short - Contentful is content infrastructure. So if you have text, images or any other kind of digital assets that you want to serve to your users, you can use Contentful to edit, manage and deliver content via Contentful’s WebApp and through API-calls.
Contentful stores your data in so-called spaces. You can think of spaces like a project-specific bucket that you fill up with all sorts of assets belonging to your project.
When you create your free Contentful account you will be asked to create a space. While there are examples to get you started, we’re going to create an empty space called Getting More Votes.
With our Contentful space in place, the next step is to create content types that go into that space.
For this implementation to work we need to create two content types: voterMessage and voterNumbers.
Let’s start with creating a voterMessage content type:
Once the content type has been created, we will need to add a field to hold our information:
We’ll go with a single text field:
And name it messageToVoters like so:
With the content type in place, let’s add the message that will be sent out to potential voters by selecting Content/Add entry/ voterMessage.
The message that Polly Politician wants to send out is — "Selly Celebrity supports Polly Politician — you should too", so let’s add just that:
Once we hit the green publish button, Polly’s voter message will get a unique entry ID. We’ll use this entry ID when retrieving the entry via Contentful’s Content Delivery API, or CDA.
To view the entry ID, click the info button:
Our entry is ‘Ykt2v3ixYQwwAekwSKg0A’.
To authenticate against the CDA, we’ll need to create an API key — do this by navigating to Space settings and API Keys:
Then click Add API key and give your key a suitable name:
Now that we have our API key, let’s create a function called getVoterMessage() that utilizes this API key to grab content from Contentful.
Note that Contentful’s Python SDK will convert field name to snake case. That’s why our messageToVoters field is addressed as entry.message_to_voters in the snippet above. All in the name of PEP 8 compliance.
And if we temporarily change our Flask route to echo the content, we would get from Contentful like this:
We would get:
The next step is to connect our app to Twilio’s Programmable SMS API.
So we’ve written the function getVoterMessage() to get our voter message from Contentful. Let’s write another function that takes this message and sends it out as an SMS:
To get the function to execute, we’ll change the Flask route to the following:
Seconds after the function executes, the receiver will see the following SMS:
With the app’s core functionality in place, let’s make our app serverless by deploying it to AWS lambda.
AWS Lambda lets you run code without provisioning or managing servers.
So far we’ve only been running our Flask app locally. To deploy the app to AWS, we’ll be using Zappa.
Install Zappa like so:
We’ll then run zappa init to generate a configuration file:
Now run zappa deploy dev to the app to AWS Lambda:
The deploy was successful and our Flask app now runs serverless at https://bz9zie872g.execute-api.us-east-1.amazonaws.com/dev.
The next step is to configure webhooks in Contentful so that whenever a new campaign message gets published.
We want to set up a webhook so that every time the campaign message changes and the campaign manager pushes the publish button, an HTTP POST requests gets sent to our serverless AWS Lambda app — which in turn will send out a text message.
To configure a webhook we’ll navigate to Space settings and webhooks:
And then click Add webhook.
We’ll configure the target of our webhook to be our AWS lambda function at https://bz9zie872g.execute-api.us-east-1.amazonaws.com/dev.
Also, we’ll set up the webhook to trigger we hit the publish button:
The idea is now that when we change our campaign message and hit publish. The updated message will be delivered to voters via SMS with the push of a button. But before that can happen, we’ll need to return to our runVoterCampaign function.
Contentful’s webhooks are sent as HTTP POST. This means that we’ll have to add POST method support:
Now let’s update our serverless app using Zappa
To test our new webhook we’ll update the campaign message like so:
Hit the big green publish button, and no time later we’ll have the following message on our phone:
Yes!!! It works. Pretty easy right :)
Without too much effort, we’ve built a solution that grabs data from Contentful and sends it to users via Twilio’s programmable SMS API — all while running serverless.
We’ve also seen how webhooks can be configured to trigger on changes made to content stored with Contentful. Webhooks that in turn call AWS Lambda functions.
In this article, we built a Flask app. Now, Getting code deployed to AWS Lambda can be surprisingly complex — but using Zappa makes sending Flask apps to the cloud easier than ever.
A logic flow of what we’ve created looks like so:
Serverless is the way to go. No more having to worry about keeping servers patched — not to mention the burden of keeping perhaps thousands of servers up and running. Going serverless means that you can focus on code, and not on maintenance.