I am sticking this out here just in case any other WordPress bloggers find the information useful.
(Edit: It’s funny how quickly one goes from “not knowing anything” to “being an expert” these days…)
I have said it before and I’ll say it again — there’s nothing more frustrating than randomly noticing something around here has quit working, usually due to a change either Facebook or Twitter has made.
This week’s frustration? Deciphering (and coding around) the logic behind Facebook’s default thumbnail code.
If you’ve ever posted a link in Facebook you may have noticed that Facebook will, at least usually, insert a small thumbnail from the site as well. Pictures are really key in driving people to your web site. They used to say a picture is worth a thousand words. Today that means a picture is worth a thousand clicks.
The old WordPress plug-in I used to use passed pictures over to Facebook. Then Facebook did that thing the occasionally do where they randomly change enough code to where everyone’s plug-ins break, so I had to find another way to push updates to Facebook. I’m now using Jetpack which works pretty well, but if it worked great I wouldn’t have anything to complain about.
To find those thumbnails Facebook searches for a picture with an “og:image” value. The old plug-in I used to push updates to Facebook didn’t set the og:image, so I found another plug-in that did. THAT plug-in found the first picture in each post and added the og:image property, which Facebook saw and used as the default thumbnail. Oh, those were such good times back when everything worked! Have I mentioned Facebook appears to change their site at will for no other reason than to break people’s plug-ins and send us all back to the drawing board? Well, that’s what happened. My old plug-in that I used to push data to Facebook quit working and that’s when I changed to Jetpack. So far, so good.
The problem is, Jetback also sets the og:image tag, and as far as I can tell, there’s no way to disable that! That makes Facebook cry and display no picture. (Edit: The reason this doesn’t work is because the two plug-ins set meta tags in two different parts of the html code. Why this matters is anyone’s guess, but it does. It confuses WordPress to the point where no thumbnail is diplayed.) To get any thumbnail to show up, I had to disable the other image plug-in I was using. Happy day, right? Oh no. What this did was cause Facebook to show thumbnails for posts that had at least one picture linked in them, and show NO thumbnail for any post where no picture was embedded. You could probably file this under “working as designed,” but the end result wasn’t very desirable. And if you think this was an easy fix, then har har, you have never stayed up drinking generic energy drinks from Aldi’s while pouring over WordPress code like I did.
The solution, I thought, was to set the og:image property in functions.php. I found some random code on the net and inserted this near the end of functions.php:
It’s very easy to cut/paste code from the web. It’s more difficult to understand what it’s doing. What this code did was show a default thumbnail (http://www.robohara.com/200×200.jpg) on Facebook for any WordPress post I made that didn’t have a picture in it. Success! Unfortunately, it also began showing that same thumbnail for every post I posted that did have a picture in it. Fail! But why??
After dissecting the code it’s pretty obvious; this particular code is looking for featured images, and if it doesn’t find one, it uses the default thumbnail instead. Featured images are specific images that get uploaded and attached to posts; linked images (like the ones I use) don’t count. So because I have no featured images, the array is blank and the code inserts the default 200×200 thumbnail for every single post. When I said this code is working as advertised, I meant it; it’s doing exactly what it’s supposed to do. It’s just not doing what I hoped it would do.
I’ve spent the past two three evenings trying random plug-ins and bits of code to circumvent this behavior. I even tried writing some custom code to pull all the .jpg images from a post, stick them into an array, and write them back out as og:images. (Edit: I returned to the drawing board, built upon this idea, and got it working. The final solution has been appended to this post.)
The solution I thought was working is below. I added the following line to header.php near the other meta tags:
I thought this brute force approach would solve the problem by adding the default thumbnail as an og:image to every single post. In a way, it did; unfortunately, because of where it appears in the html code (at the very top), Facebook always picks it as the image. Grrrr.
What follows I discovered on my own, and it works for me. If there are any side effects, I haven’t run across them yet.
After returning all the files I have modified back to their original form, I turned my attention toward the Jetpack plug-in. From what I could find on Google the problem was coming from the opengraph module, so I searched my Jetpack plug-in directory and found “functions.opengraph.php”. That seemed like a good place to start.
I’m not a PHP expert, but I understand script logic.
Inside the functions.opengraph.php file there is an array called $tags. Each meta property has its own array, and the one I was looking for was the og:image one. I found it here:
$tags['og:image'] = jetpack_og_get_image( $image_width, $image_height );
That code calls a function that builds an array from all the pictures on the page. (I won’t cut/paste that function; you can see it at the bottom of the file if you want.)
My first thought was to just add another entry to the array; that failed and I ended up simply overwriting it.
My second thought was to append the default thumbnail to the array.
array_push($tags['og:image'], "http://www.robohara.com/200x200.jpg");
This was almost right. The problem I ran into was, on posts where there are no linked photos, no array is created and you cannot append to an array that doesn’t exist.
THIS IS THE FINAL WORKING SOLUTION:
if (empty($tags['og:image'])) {
$tags['og:image'] = 'http://www.robohara.com/200x200.jpg';
}
I inserted this just below the line I posted above (the one that calls the function that builds the array). Simply put, if the array is blank, set the $tags og:image to the default thumbnail.
If you click on the following page (http://www.robohara.com/?p=6048), one that has pictures, view source, and search for og:image, you will find the following two entries:
meta property="og:image" content="http://i.imgur.com/KMupiYQ.jpg"
meta property="og:image" content="http://i.imgur.com/EH2ym1J.jpg"
If you click on the following page (http://www.robohara.com/?p=6031), a page that has no pictures, view source, and search for og:image, you will find the following entry:
meta property="og:image" content="http://www.robohara.com/200x200.jpg"
GAH. I believe this one has been solved… until Facebook changes their code again.
Thank you for this! I found that you could also use the jetpack_images_get_images filter in Jetpack to apply a default image for posts that fall under “is_singular”. Here is a pastebin as example: http://pastebin.com/h8VTBGqK
Never mind, I found a better solution: http://pastebin.com/g5Fwd4yZ
Sir, thanks for the great explanation. Seriously, with all my respect. You are the hero of my day.