Here’s the long title for this code snippet —
How to set up an external image as a WordPress featured image and inject it into header as an og:image
meta tag, suitable for LinkedIn and Facebook
Why did I do this? Because Yoast SEO does not add an og:image
tag automatically, if there is no locally hosted featured image. I also did it because in this very specific case, my images were served from a script and generated on the fly based on width, height, quality and cropping URL parameters. Here’s my workaround:
/**
* Use external URL for featured image (helps with social sharing)
*
* Get the cURL effective URL and save it in a custom meta field.
* Output custom Open Graph meta tags based on the saved URL.
*/
function whiskey_thumbnail_external_replace() {
global $post;
if (empty($post->ID) || (string) get_post_type($post->ID) !== 'custom-post-type') {
return;
} else {
if ((string) get_post_meta($post->ID, '_whiskey_featured_image', true) === '') {
$url = 'path/to/image/;
// Use cURL to get the image path if it doesn't exist
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => $url,
CURLOPT_HEADER => true,
CURLOPT_NOBODY => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_ENCODING => ''
]);
$response = curl_exec($curl);
$redir = curl_getinfo($curl, CURLINFO_EFFECTIVE_URL);
curl_close($curl);
//
$url = $redir;
update_post_meta($post->ID, '_whiskey_featured_image', $url);
} else {
$url = get_post_meta($post->ID, '_whiskey_featured_image', true);
}
if ((string) $url !== '') {
add_filter('wpseo_frontend_presenter_classes', 'whiskey_wpseo_frontend_presenters', 10, 1);
// LinkedIn
echo '<meta name="image" property="og:image" content="' . $url . '">';
// Facebook
echo '<meta property="og:image" content="' . $url . '">';
echo '<meta property="og:image:alt" content="' . get_the_title($post->ID) . '">';
if (getimagesize($url)) {
$size = getimagesize($url);
echo '<meta property="og:image:width" content="' . $size[0] . '">
<meta property="og:image:height" content="' . $size[1] . '">';
}
}
}
}
function whiskey_wpseo_frontend_presenters($presenters) {
if ($matches = preg_grep('/Image_Presenter/', $presenters)) {
return array_diff($presenters, $matches);
} else {
return $presenters;
}
}
add_action('wp_head', 'whiskey_thumbnail_external_replace', -1000);
Note that I am storing the final URL in a custom meta field and I am using CURLINFO_EFFECTIVE_URL
to get the last effective URL (after all redirects). Also note that you need CURLOPT_FOLLOWLOCATION
to be set to true
.
After I get the image, I am adding 5 meta tags (one for LinkedIn and 4 for Facebook). Here they are:
<!-- LinkedIn -->
<meta name="image" property="og:image" content="/path/to/image/">
<!-- Facebook -->
<meta property="og:image" content="/path/to/image/">
<meta property="og:image:alt" content="This is the title">
<meta property="og:image:width" content="1920">
<meta property="og:image:height" content="1080">
If you are using an SEO plugin other than Yoast’s, you might not need this workaround.
Photo by Eric Park on Unsplash.