Rewriting WordPress's JetPack Related Posts Shortcode


I like the JetPack related post functionality. But I wanted to customise it far beyond what the default code allows for.

So here's how I went from this:

The old layout has three items, with small images and indistinct text.

To this:

The new layout has 4 items, each boxed off, with a larger image and more distinct text.

Documentation

The complete documentation for related posts is pretty easy to follow.

This is an adaptation of "Use Jetpack_RelatedPosts_Raw to build your own list of Related Posts".

Remove the automatic placement

You can turn off the original "related posts" by adding this to your theme's functions.php:

PHP PHPfunction jetpackme_remove_rp() {
    if ( class_exists( 'Jetpack_RelatedPosts' ) ) {
        $jprp = Jetpack_RelatedPosts::init();
        $callback = array( $jprp, 'filter_add_target_to_dom' );
        remove_filter( 'the_content', $callback, 40 );
    }
}
add_filter( 'wp', 'jetpackme_remove_rp', 20 );

In your theme's index.php (or wherever else you like) you can add this code to insert the new related posts functionality:

PHP PHPif ( is_single() ) {
    echo "<section>";
        echo do_shortcode( '[jprelp]' );
    echo "</section>";
}

Create the new functionality

And this goes in your theme's functions.php file. I've commented it as best I can. Let me know if you need more info.

PHP PHPfunction jetpackme_custom_related() {
    //  Check that JetPack Related Posts exists
    if (
            class_exists( 'Jetpack_RelatedPosts' )
            && method_exists( 'Jetpack_RelatedPosts', 'init_raw' )
    ) {
            //  Get the related posts
            $related = Jetpack_RelatedPosts::init_raw()
                ->set_query_name( 'edent-related-shortcode' )
                ->get_for_post_id(
                    get_the_ID(),   //  ID of the post
                    array( 'size' => 4 )//  How many related items to fetch
                );
            if ( $related ) {
                //  Set the container for the related posts
                $output = "<h2 id='related-posts'>The Algorithm™ suggests:</h2>";
                $output .=   "<ul class='related-posts'>";

                foreach ( $related as $result ) {
                    $related_post_id = $result['id'];

                    // Get the related post
                    $related_post = get_post( $related_post_id );

                    //  Get the attributes
                    $related_post_title = $related_post->post_title;
                    $related_post_date  = substr( $related_post->post_date, 0, 4 ); // YYYY-MM-DD
                    $related_post_link  = get_permalink( $related_post_id );

                    //  Get the thumbnail
                    if ( has_post_thumbnail( $related_post_id) ) {
                        $related_post_thumb = get_the_post_thumbnail( $related_post_id, 'full',
                            array( "class"   => "related-post-img",
                                   "loading" => "lazy" //   Lazy loading and other attributes
                            )
                        );
                    } else {
                        $related_post_thumb = null;
                    }

                    //  Create the HTML for the related post
                    $output .= '<li class="related-post">';
                    $output .=    "<a href='{$related_post_link}'>";
                    $output .=       "{$related_post_thumb}<p>{$related_post_title}</p></a>";
                    $output .=    "<time>{$related_post_date}</time>";
                    $output .= "</li>";
                }
                //  Finish the related posts container
                $output .="</ul>";
            }
        //  Display the related posts
        echo $output;
    }
}
add_shortcode( 'jprel', 'jetpackme_custom_related' );   //  Shortcode name can be whatever you want

Bit of CSS to zhuzh it up

Feel free to add your own styles. This is what works for me.

CSS CSS.related-posts  {
    list-style: none;
    padding: 0;
    display: inline-flex;
    width: 100%;
    flex-wrap: wrap;
    justify-content: center;
}

.related-posts > * {
    /* https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_flexible_box_layout/Controlling_ratios_of_flex_items_along_the_main_axis#combining_flex-grow_and_flex-basis */
    flex: 1 1 0;
}

    .related-post {
        min-width: 10em;
        max-width: 20em;
        text-align: center;
        margin: .25em;
        border: .1em var(--color-text);
        border-style: solid;
        border-radius: var(--border-radius);
        position: relative;
        display: flex;
        flex-direction: column;
        min-height: 100%;
        overflow: clip;
    }

        .related-post h3 {
            font-size: 1em;
            padding-top: .5em;
        }

        .related-post img {
            object-fit: cover;
            height: 9em;
            width: 100%;
            border-radius: 0 1em 0 0;
            background: var(--color-text);
            display: inline-block;
        }
        .related-post p {
            margin: 0 .25em;
        }
        .related-post time {
            font-size: .75em;
            display: block;
        }

ToDo

  • Use transients to store the data to prevent repeated slow API calls?
  • Perhaps some teaser text?
  • Adjust the layout so the date always floats to the bottom?

Share this post on…

  • Mastodon
  • Facebook
  • LinkedIn
  • BlueSky
  • Threads
  • Reddit
  • HackerNews
  • Lobsters
  • WhatsApp
  • Telegram

One thought on “Rewriting WordPress's JetPack Related Posts Shortcode”

What are your reckons?

All comments are moderated and may not be published immediately. Your email address will not be published.

Allowed HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <p> <pre> <br> <img src="" alt="" title="" srcset="">