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:
To this:
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
:
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 );
Add the new Related Posts
In your theme's index.php
(or wherever else you like) you can add this code to insert the new related posts functionality:
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.
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.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?
Ernie Smith said on writing.exchange:
@Edent I enjoy that you used “the algorithm” here. Heh.
One of these days I may just find my way back to WordPress. Craft CMS is good, but I’m finding the plugin ecosystem to be a real limitation over time.
More comments on Mastodon.