Images are important when someone shares a link to your blog because it is displayed in a larger and more eye-catching type of card. This is great for blogs with great photography like fashion, travel or cooking blogs, or if you have an artist on its payroll.
An alternative is using text on an image. You can include the title and other information about the post with a design that matches the blog’s brand. A good example of this is GitHub‘s current images when you share a repository: it includes the repository name and owner, some numbers, the owner’s avatar, and two very recognisable brand assets: GitHub’s logo and the colour-coded bar with a breakdown of the languages used in the repository.

They made a post — A framework for building Open Graph images — explaining how these images are created. GitHub creates an HTML representation of the image and then uses Puppeteer to screenshot it and save it as an image. This is a very popular approach, as HTML offers a lot of flexibility, and Puppeteer runs on Node which is very convenient if it is already in your stack.
However, a WordPress site requires third-party services to generate — and sometimes host — the image using this method. This fits larger projects, but what about smaller projects?
A simple solution is using PHP’s built-in GD library. It allows us to create images dynamically, including shapes, other images, and text. Unlike the Puppeteer option, GD is very rigid and limited for text layout. For example, it does not have the option to create multi-line text. But making use of string manipulation, we can create some interesting images using text from our post.

These images are created with a plugin, which also adds the Open Graph meta tags necessary. I am creating and destroying the images as they are requested because this is a very small blog, but images can be saved after being generated the first time to improve performance.
The GD library is perfect for simple image manipulation, maybe not so much for image creation. For complex designs is better to have a base image to add the text on top of it, instead of trying to generate the whole design programmatically.
I do not think it is a useful plugin to share, as it will only replicate my design. But I’ll share some bits in case you want to try.
I used wp_head
hook to add the meta tags.
add_action('wp_head', array($social_cards, 'add_social_cards_meta_tags'), 999);
I created different arrays for each text size — the final design uses two, but I used up to five different sizes when testing — so font size, line height, and maximum line length are tied to each other.
$sizes = array(
'small' => array(
'fontSize' => 40,
'lineHeight' => 60,
'lineLength' => 34
),
'large' => array(
'fontSize' => 55,
'lineHeight' => 72,
'lineLength' => 27
)
);
For multi-line text, I split strings into strings shorter than the maximum line length using wordwrap()
and then printed each line in reverse order to vertically align text to the bottom calculating the new line position.
$yTitlePosition = $yInitialPosition - ($currentTitleLine * $sizes['large']['lineHeight']);
And I split URLs by either /
or -
using strrpos()
to find the next breakpoint in reverse order starting at the maximum line length.
strrpos($link, '/', $offset)

Even if it is a straightforward solution, I think it is a good fit for a small blog like this one.