Using Bannerbear in a Batch Generation Process
Contents
Need to batch-generate lots of social media images for a website you run? Here's an example of using Bannerbear in a command-line script that you can run anytime.
A common use-case for Bannerbear is generating bespoke og:image and twitter card images for every page on your website. When automated, this is a simple and zero maintenance way to drive more traffic to your pages from social media.
There are various ways to implement this in your projects using Bannerbear. Since Bannerbear is a REST API, one popular method is employing an event-driven approach, pinging Bannerbear whenever your platform generates new content.
But another method would be a batch approach, where you auto generate images in large batches at once and save them to your own filesystem.
Advantages of Batch Generation
- Zero brittleness as the images are pre-generated
- Simple to manage expiry / regeneration; just delete the images and rerun the script
- Keeps image generation code separate from your core
Disadvantages of Batch Generation
- You have to "remember" to run the script*
- Less suitable when there is new content being published constantly
*could easily be automated though!
Batch generation is ideal for sites that are built via a static site generator where you want static image assets and no code running on-the-fly.
The Bannerbear marketing site (this website) is run on a static site generator called Middleman and all the social media og:image files are generated by batch using a Rakefile. Whenever I add new content to the site I simply run:
rake bannerbear:generate
Which runs the following process:
- Fetch a json feed of all pages of the site
- Then, for each page…
- Checks for a pre-existing og:image in a specified folder
- If the image file already exists, move on
- If the image file doesn't exist, send a request to Bannerbear
- Wait for the image to get generated, then save it to the specified folder
- Move to the next page in the json feed
And that's it! This is written in Ruby since that's what I know best, but you could write something similar to this in any programming language :)
require 'httparty'
require 'open-uri'
namespace :bannerbear do
task :generate do
puts "Starting json request"
response = HTTParty.get(ENV['LOCAL_BB_SITE_ALL_POSTS'])
begin
json = JSON.parse response.body
puts "Number of pages: #{json.size}"
json.each_with_index do |page,i|
puts "#{i} ---------------------------------------"
puts "Checking file exists for"
path = './source/images/opengraph/' + page['filename']
puts path
if !File.file?(path)
puts "File doesn't exist, lets create!"
general_template_id = ENV['BB_SITE_GENERAL_OG_TEMPLATE']
blog_template_id = ENV['BB_SITE_BLOG_OG_TEMPLATE']
template = general_template_id
mods = [
{
:name => "title",
:text => page['title']
}
]
if page['blog_date']
template = blog_template_id
mods = [
{
:name => "title",
:text => page['title']
},
{
:name => "date",
:text => page['blog_date']
}
]
end
payload = {
:template => template,
:modifications => mods,
}
puts "Creating Bannerbear API request"
puts payload
response = HTTParty.post("https://api.bannerbear.com/v2/images", {
body: payload,
headers: {"Authorization" => "Bearer #{ENV['BANNERBEAR_SOCIAL_MEDIA_PROJECT_API_KEY']}"}
})
image_json = JSON.parse response.body
counter = 1
#poll for image to complete
5.times do |attempt|
puts "Attempt #{attempt}"
counter = counter+1
response = HTTParty.get(image_json['self'], {
headers: {"Authorization" => "Bearer #{ENV['BANNERBEAR_SOCIAL_MEDIA_PROJECT_API_KEY']}"}
})
image_json = JSON.parse response.body
if image_json['image_url_png']
puts "Image generated!"
puts image_json['image_url_png']
download = open(image_json['image_url_png'])
IO.copy_stream(download, path)
break
end
sleep 1
end
end
puts "Moving to next page..."
end
rescue => e
puts "Rescued #{e.inspect}"
end
end
end