Social media is a great way to engage your audience and drive traffic to your website. We can’t ignore the impact of social proof when it comes to business.
But how do you get the most out of your social media efforts into your blog posts that impact your business?
In this tutorial, I’ll show you how to embed a tweet in a blog post using the Twitter API and ButterCMS to get the most out of your Twitter marketing efforts.
But first, let’s get started by knowing what Tweepy is and why is it best paired with a headless CMS .
What is Tweepy API? and Why a Headless CMS?
Tweepy is a Twitter API Python wrapper that allows you to access Twitter data easily with Python.
We use it in this tutorial and pair it with a headless CMS, more specifically ButterCMS , because it’s they both are great backend tools; the headless ButterCMS is a great tool to build a blog, and Tweepy is a great tool to get data from Twitter.
You might ask, why would you want to embed a tweet on your website?
Benefits of Embedding a Tweet on Your Website
By embedding a tweet feed on your website/blog, you can make your customers feel more connected to your brand and let them engage more on your Twitter. Embedding tweets have many benefits, some of which are:
-
It adds visual appeal and beauty to your website
-
It brings good browsing experience to your website
-
It helps you win your audience trust
-
It boosts user-generated content
-
It provides the visitor with relevant information like hashtags, mentions, and accounts that are related to your brand.
-
It increases brand awareness and might increase your twitter followers
-
It drives interactions and communication with your audience
Tweepy + ButterCMS + Flask
ButterCMS has SDKs in many different languages; Python is one of them. You can integrate it with your Python web framework like Django and Flask. In this tutorial, we will use Flask as it is a lightweight microframework and easy to set up and configure especially in the application we’re building here which is a blog that has a tweet embedded in a post. To get that tweet, we need to use Twitter API; that’s why we’ll use Tweepy which is a Twitter API wrapper that is easy to use its API methods.
Let’s now get started in our tutorial prerequisites.
Prerequisites
To follow along with this tutorial, I assume no knowledge of whatsoever of Tweepy and ButterCMS. It’s good to have a basic knowledge of Flask and how to change routes to configure endpoints of a Flask app, and a basic knowledge of how to deal with Jinja templates to be able to customize the views of HTML.
I also assume that you have your Twitter credentials from Twitter Developer Portal ; I mean the consumer API key and secret, and access token and secret.
Without further ado, let’s jump into the installation part.
Installation Guide
We only need three packages to install: Tweepy, ButterCMS, and Flask.
Let’s include that in the requirements.txt
file used in this
tutorial:
buttercms-python==1.3
Flask==2.0.3
tweepy==4.6.0
and it’s preferred to use Python 3.6.9. Let’s create a virtual environment first and activate it. Also upgrade pip to be 21.3.1 version.
$ python3 -m venv venv
$ . venv/bin/activate
$ pip install --upgrade pip
Let’s now install the dependencies using the following commands:
$ pip install -r requirements.txt
Project Structure
In this tutorial, the project we’re going to build is structured as follows:
.
├── app
│ ├── __init__.py
│ ├── routes.py
│ ├── templates
│ │ └── blog
│ │ ├── author.html
│ │ ├── blog.html
│ │ ├── category.html
│ │ ├── post.html
│ │ └── tweet.html
│ └── tweepy_api.py
├── venv/*
├── embed_tweet.py
└── requirements.txt
Disclaimer: Don’t worry! There is a repo for this project, check it out here .
Note that venv/
directory is trimmed here because it has too many
subdirectories and files that are not of help to be shown in this
demonstration.
Here is a breakdown of these files:
app/__init__.py
: The init file of the Flask app that can be used to package the application. It’s also useful if you want to import something easily to the parent directory. We will see that later in this tutorial.app/routes.py
: The routes file which includes the endpoints of our Flask appapp/templates/blog/author.html
: The template HTML used to view the author informationapp/templates/blog/blog.html
: The template HTML used to view the blog informationapp/templates/blog/category.html
: The template HTML used to view the category informationapp/templates/blog/post.html
: The template HTML used to view the blog post informationapp/templates/blog/tweet.html
: The template HTML used to view the tweet feed informationapp/tweepy_api.py
: The file that uses Tweepy API to retrieve the desired tweet that we want to demonstrate in this tutorialvenv/*
: The directory that has the environment filesembed_tweet.py
: The main entry point to our Flask apprequirements.txt
: The requirements file that we used to install the dependencies
We’re now ready to start configuring the tweet feed that we will add to our blog post.
It’s important to separate the business logic from the presentation logic. That’s why in the following two sections, we will see how to embed the tweet feed and then how to present that tweet feed in our blog post.
Exploring the Oembed Object - Business Logic
In the following two sections, we will focus on two files:
app/tweepy_api.py
- and this one
app/templates/blog/tweet.html
Let’s start with this tweepy_api.py
file:
import tweepy
import os
def get_api(**kwargs):
"""Gets the API object after authorization
and authentication.
:keyword tweepy_api_key: The consumer API key.
:keyword tweepy_api_key_secret: The consumer API key secret.
:keyword tweepy_access_token: The access token.
:keyword tweepy_access_token_secret: The access token secret.
:returns: The Tweepy API object.
"""
auth = tweepy.OAuthHandler(
kwargs["tweepy_api_key"],
kwargs["tweepy_api_key_secret"]
)
auth.set_access_token(
kwargs["tweepy_access_token"],
kwargs["tweepy_access_token_secret"]
)
return tweepy.API(auth)
api = get_api(
tweepy_api_key=os.getenv("TWEEPY_API_KEY"),
tweepy_api_key_secret=os.getenv("TWEEPY_API_KEY_SECRET"),
tweepy_access_token=os.getenv("TWEEPY_ACCESS_TOKEN"),
tweepy_access_token_secret=os.getenv("TWEEPY_ACCESS_TOKEN_SECRET")
)
resp = api.get_oembed(
"https://twitter.com/ButterCMS/status/1521867388882649089"
)
The get_api()
function authorizes and authenticates the Tweepy API
with the credentials you have from Twitter Developer.
Finally, the resp
is the response we get from the get_oembed
Tweepy method which is a wrapper method for the oembed Twitter
endpoint
. As indicated from Twitter doc, it returns a single Tweet, specified by
either a Tweet web URL or the Tweet ID, in an
oEmbed -compatible format. The returned HTML
snippet will be automatically recognized as an Embedded
Tweet when
Twitter’s widget JavaScript is included on the
page .
If you want to experiment with this resp
object, you can import json
library and do the following:
print(json.dumps(resp, indent=4))
When you cd
into app
and run this file separately with python tweepy_api.py
, you will see the following:
{
"url": "https://twitter.com/ButterCMS/status/1521867388882649089",
"author_name": "ButterCMS",
"author_url": "https://twitter.com/ButterCMS",
"html": "<blockquote class=\"twitter-tweet\"><p lang=\"en\" dir=\"ltr\">In most situations, the benefits of a <a href=\"https://twitter.com/hashtag/SaaS?src=hash&ref_src=twsrc%5Etfw\">#SaaS</a> CMS solution will vastly outweigh those of its <a href=\"https://twitter.com/hashtag/OnPremise?src=hash&ref_src=twsrc%5Etfw\">#OnPremise</a> counterparts. But why is this case? And when is it not? Check out our latest blog post to find out. <a href=\"https://t.co/mWnlt95OIB\">https://t.co/mWnlt95OIB</a> <a href=\"https://twitter.com/hashtag/contentmanagement?src=hash&ref_src=twsrc%5Etfw\">#contentmanagement</a> <a href=\"https://twitter.com/hashtag/headlesscms?src=hash&ref_src=twsrc%5Etfw\">#headlesscms</a> <a href=\"https://t.co/3YYIluF4sr\">pic.twitter.com/3YYIluF4sr</a></p>— ButterCMS (@ButterCMS) <a href=\"https://twitter.com/ButterCMS/status/1521867388882649089?ref_src=twsrc%5Etfw\">May 4, 2022</a></blockquote>\n<script async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\n",
"width": 550,
"height": null,
"type": "rich",
"cache_age": "3153600000",
"provider_name": "Twitter",
"provider_url": "https://twitter.com",
"version": "1.0"
}
So that
tweet is
from ButterCMS Twitter account. The object that is returned from the get_oembed
method may have too much information that we need for the
embedded tweet; its URL, author name, author URL, the html blockquote
tag, and more.
What we need from this object is the value of that html
key which
contains the html blockquote
tag that we want to embed into our blog
post.
Now, let’s remove the print statement that we wrote to see what that object looks like and move into the next section to configure how that tweet would be viewed in Jinja template for our Flask app.
Embedding the Tweet in a Jinja Template - Presentation Logic
Let’s now see this file: app/templates/blog/tweet.html
and know what
it actually does:
{% block content %}
{% include "post.html" %}
<center>{{ response.get("html")|safe }}</center>
{% endblock %}
First, it’s an HTML file. But… it has kind of Python code in it! That’s what Jinja actually is. Simply put, Jinja2 is a templating engine that shows the text of the response.
So we want to show the value of the html
object that is returned
from the get_oembed()
method. That’s why we get this response.get("html")|safe
. Note that we use the |safe
filter here
to avoid automatic HTML
escaping
and mark the coming Python object to the template as safe.
We wrap that object with double curly braces {{ ... }}
because this
is a variable expression in Jinja2. And then we want the tweet to be
centered using the <center>
HTML tag.
We include the post.html file before that tweet feed. It’s up to you where to put the tweet feed though.
This is all wrapped in a Jinja2 block code.
Now, what we need to know is where that response
variable is and how
to pass it from a Flask endpoint.
Pointing to the Embedded Tweet Response in Flask
You need yourself where do you want to render the tweet feed. In our
case, we will render it at the end of a specific blog post. This post is
the example post that you have when you first get started with
ButterCMS. So our focus in the app/routes.py
file will be on the show_post()
function:
...
from .tweepy_api import api
...
@blog.route('/<slug>')
def show_post(slug):
response = client.posts.get(slug)
try:
post = response['data']
except KeyError:
# Post was not found
abort(404)
if slug == "example-post":
resp = api.get_oembed(
"https://twitter.com/ButterCMS/status/1521867388882649089"
)
return render_template('tweet.html', post=post, response=resp)
return render_template('post.html', post=post)
Note, that we import api
object from the tweepy_api.py
file that
exists in the same level. We could have imported the resp
object
directly though.
We retrieve the post from this function through the ButterCMS client and
we check if the slug of that post is the example-post
that we
firstly have in our ButterCMS portal, we render the tweet.html template
and pass two variables. Note, that response
variable here is what we
see in the tweet.html Jinja2 template and now it’s assigned to resp
variable. We also pass post
to the post
variable which is needed
in the post.html
template that we included in the tweet.html
template.
The logic here is just to demonstrate how to make point to the oembed object. You can do whatever you want depending on your use case.
Is it time to run the Flask application? Yes, except for one thing we need to learn.
Running the Flask Application
The main entry point to our Flask application is the embed_tweet.py
script. One of the imports of this file is this:
from app import blog
So we import the blog
instance to register a
blueprint
. But here we import it directly from app
which is somehow weird in
the structure of our project. Shouldn’t it be imported from app.routes
? Actually, yes it could be but we import it directly from app
because we included the routes
module in the __init__.py
script
as the following:
from .routes import blog
Now, let’s run the app. Assuming you’re at the parent directory of our repo, configure the flask application first:
$ export FLASK_APP=embed_tweet.py
and now:
$ flask run
If you open your browser and head over to localhost:5000, you’ll see the following:
which indicates the home page of our Flask app. Now, let’s turn into the
blog/
endpoint:
and then click on the example post link:
and if scroll down at the bottom of that page, we’ll see our embedded tweet is shining like this:
Other Use Cases of Tweepy API
Finally, you can do a lot of things with Tweepy API. To name a few:
- You can get trending hashtags in tweets
- You can get trending tweets in any country
- You can create a bot that retweets tweets or favorites another tweet
- You can search for specific keywords on the whole Twitter platform
- You can create a list for a specific user account
and you can do more and more. Just check out the documentation , you’ll see tons of values out there that can be use cases for your project.
Conclusion
In this tutorial, we’ve seen how to embed a tweet feed and put it in a blog post using Tweepy API and a headless CMS; ButterCMS. This blog is deployed as a Flask app. We covered what Tweepy API is and why we need a headless CMS in general.
We also covered the benefits of embedding a tweet on websites and then we dived into our tutorial in which we showed a use case of embedding a tweet and explore the oembed object and build our business logic for that task.
We’ve introduced to a basic understanding of a Jinja2 template to provide our presentation layer. We then learned how to point to our embedded tweet response in the Flask app and finally we were able to run our Flask application and explore the endpoints we’re interested in.
We’ve also touched some use cases of Tweepy API so that you can explore it more if you need it for your next project.