Jetpack: how to deal with missing images in the Related Posts module

in WordPress

Jetpack Related Posts are great. You should use them!

They are also customizable; we added a lot of filters to allow you to customize the output of the Related Posts. You can find a lot of examples here: Customize Related Posts (Kudos to Xiao for all the great work he’s done with Jetpack Related Posts).

The module also includes an option to “use a large and visually striking layout”. When that option is active, Jetpack will look for a large image (at least 350*200px) in your posts, and use that image when displaying Related Posts. It looks great, and I use it on this site:

Related Posts

What doesn’t look that good, however, is when some of the Related Posts don’t have any image.

Missing Related Image

There are 2 ways to solve this small issue.

Add a default image that will be used by all Related Posts that don’t include an image

You can use the jetpack_images_get_images filter (reference) to define a default image that will be used by the Related Posts and by other services like Facebook or Twitter.

Here is how you could define your own default image:

function jeherve_custom_image( $media, $post_id, $args ) {
    if ( $media ) {
        return $media;
    } else {
        $permalink = get_permalink( $post_id );
        $url = apply_filters( 'jetpack_photon_url', 'YOUR_LOGO_IMG_URL' );
     
        return array( array(
            'type'  => 'image',
            'from'  => 'custom_fallback',
            'src'   => esc_url( $url ),
            'href'  => $permalink,
        ) );
    }
}
add_filter( 'jetpack_images_get_images', 'jeherve_custom_image', 10, 3 );

Note that this image has to be at least 350*200px to be used by the Related Posts module. Feel free to use a larger image, it will be resized thanks to Photon!

Here is the result on this very site (the third post uses the default image):

Default Related Image

Edit: if you’re wondering why there isn’t an option in your dashboard allowing you to define a default image, you can follow the conversation in this GitHub issue to find out more.

Exclude all posts without an image from Related Posts

Another alternative would be to exclude all posts without an image from Related Posts. To do so, we’ll check all Related Posts for an image, and if we find a post without an image we’ll add that post to a “blacklist” of excluded posts.

Here is how you could do so, thanks to 2 filters, jetpack_relatedposts_filter_hits and jetpack_relatedposts_filter_exclude_post_ids:

function jeherve_find_related_posts_without_image( $hits, $post_id ) {

	// Grab any existing list of post IDs to exclude
	$related_posts_ids_to_exclude = get_transient( 'jeherve_posts_without_images' );
	if ( ! $related_posts_ids_to_exclude ) {
		$related_posts_ids_to_exclude = array();
	}

	foreach ( $hits as $k => $hit ) {
		if ( class_exists( 'Jetpack_PostImages' ) ) {
			// Check if Jetpack can find an image in a post
			$post_image = Jetpack_PostImages::get_image(
				$hit['id'],
				apply_filters(
					'jetpack_relatedposts_filter_thumbnail_size',
					array( 'width' => 350, 'height' => 200 )
				)
			);
			// If Jetpack cannot find an image, add the post ID to $related_posts_ids_to_exclude
			if ( ! is_array( $post_image ) ) {
				if ( ! in_array( $hits[$k], $related_posts_ids_to_exclude ) ) {
					array_push( $related_posts_ids_to_exclude, $hit['id'] );
				}
			}
		}
	}
	// Save the list of Post IDs to exclude in a transient, for a day
	set_transient( 'jeherve_posts_without_images', $related_posts_ids_to_exclude, DAY_IN_SECONDS );

	return $hits;

}
add_filter( 'jetpack_relatedposts_filter_hits', 'jeherve_find_related_posts_without_image', 20, 2 );

function jeherve_exclude_posts_without_image( $exclude_post_ids, $post_id ) {

	/*
	 * let's check if another code snippet or plugin already defines posts to exclude.
	 * If not, get our transient and exclude these posts.
	 * If yes, add our posts to the existing list.
	 */

	// Get a first list of posts to exclude
	if ( ! $exclude_post_ids ) {
		$exclude_post_ids = array();
	}

	// Get the data from our transient
	$related_posts_ids_to_exclude = get_transient( 'jeherve_posts_without_images' );

	// Merge any existing list of posts to exclude with the values from our transient
	if ( ! false == $related_posts_ids_to_exclude ) {
		$exclude_post_ids = array_merge( $exclude_post_ids, $related_posts_ids_to_exclude );
	}

	return $exclude_post_ids;

}
add_filter( 'jetpack_relatedposts_filter_exclude_post_ids', 'jeherve_exclude_posts_without_image', 20, 2 );

Note: when you start using that code, you might still notice some posts without an image. Each post needs to be checked once before to be added to the blacklist. Refresh the page, and you should be all set!

That’s it! Do you have other questions about the Related Posts module? Check the support docs, or ask me in the comments!

  1. Bonjour,
    je cherchais un module de billets relatifs pour un blog qui tourne avec S2member. J’ai l’impression que ce code me permettrait de changer les miniatures du module en testant si le visiteur est connecté ou pas. Je me trompe ou pas ?

    • Vous devrez utiliser le filtre jetpack_relatedposts_filter_options pour contrôler l’affichage des images, comme ceci :


      function jeherve_no_related_images_connected( $options ) {
      // Ne pas afficher les images si l'utilisateur est connecté
      if ( is_user_logged_in() ) {
      $options['show_thumbnails'] = false;
      }
      return $options;
      }
      add_filter( 'jetpack_relatedposts_filter_options', 'jeherve_no_related_images_connected' );

      • Merci beaucoup. Mais je veux afficher une image “alternative” – toujours la même – pour les non connectés pour avoir une présentation plus homogène ?

        • Dans ce cas jetpack_images_get_images devrait faire l’affaire, et vous permettra de changer l’image utilisée suivant le statut de l’utilisateur !

  2. I have a similar problem with the Twenty Fifteen theme. I’ve been trying to use a default image behind the next and previous links when there’s no featured image in a post (which can be the case if the post is an aside or an image). Your post here has motivated me to try and solve it this weekend! Any hints would be greatly appreciated.

  3. Line 21 of jeherve_find_related_posts_without_image is

    if ( ! in_array( $hits[$k], $related_posts_ids_to_exclude ) ) {

    Should this not be checking for $hits[‘id’] instead?

Comments are closed.