Every site owner who is posting fresh, new content frequently wants to have their content read on a regular basis. It does not necessarily matter if it is a returning reader or a brand new one, (though returning readers are awesome!), what matters is that someone is consuming what you have to post about.
We also appreciate our site analytics and statistics. These help us break down what is going on, who is reading what, what sections of the website get the most traffic, and shape our decisions in the future. For that, we tend to go for either Automattic’s Jetpack plugin or Google Analytics.
For the purpose of our post today, we are going to focus on Jetpack and the statistics module that comes with it. With this, we will explore how to query for the site’s popular posts “for the past X days” and some ways you could display results to users. This post assumes that you have some experience with PHP and WordPress theme development, as well as the site you are developing for has had Jetpack stats enabled for at least a little while. That way you will have stats recorded and available to query for. If it is a new install or still in development, results may be slim at first.
Installing our plugin
First things first, we need to get our PHP class installed and activated on your WordPress install. I have made it into a convenient WordPress plugin for easy activation. You can download the plugin, and if you just want to see visually what is in the plugin, you can use this GitHub gist with the same contents.
Creating our object
Once you have installed and activated, we are ready to get to work using it. The first thing we need to do is instantiate a new object with some parameters for what we want the class to fetch.
$popular_post_object = new WDS_JetPack_Popular_Posts( array( 'count' => 5, 'days' => 2, 'transient_affix' => '_mypp' ) );
We have three parameters available for this, and we will want to pass them in as an array. The first parameter is ‘count’ which is for how many posts you want to be returned, and defaults to 5. The second is ‘days’ which is for how many days you want to compare between and it defaults to 2. Last is ‘transient_affix’ that is used as part of the WordPress transient used that will temporarily store the results in, this one defaults to just ‘_popular’ in most places, but adds the “current queried object ID” if one exists. This allows for you to query for multiple things on the same page safely without overwriting your previous results.
Fetching our posts
After we have specified the parameters we want and instantiated the new object, we are ready to fetch our results and display our results.
$popular_post_results = $popular_post_object->get_posts();
This should be the only method you need to call and will assign the results to the variable you specify. If you do not have Jetpack installed and activated the variable will hold a message that lets you know you need Jetpack activated. Otherwise you will receive an array back.
Displaying our posts
If you have stats available, the method will return an array of arrays, each that will have indexes of title, permalink, and post_id that hold the corresponding value for each of your popular posts. If there are no posts to display yet, it will return an empty array. For our example we will display ours in an ordered list.
if ( !empty( $popular_post_results ) ) { $output = '<ol>'; foreach( $popular_post_results as $popular_post ) { $output .= '<li class="popular-post-' . $popular_post['post_id'] . '"><a href="' . $popular_post['permalink'] . '">' . $popular_post['title'] . '</a></li>'; } $output .= '</ol>'; echo $output; }
If all goes well, you should see a list of the top posts from your site, depending on the parameters you used. You can repeat as much as necessary and use as many times as you may need.
As long as Jetpack and this Popular Posts plugin are available and active, you can use them wherever you want in the site you are working on. This could be within your templates, in a custom widget you are creating, or even from a separate plugin. Your imagination is the limit.
Thank you for writing this article! I was using the top posts and pages widget, but I didn’t like that it also showed pages, so this worked out great! You can see it on the top right of my page. Would it be hard to add a featured thumb to it?
Would not be hard at all to get the featured image included. You’ll want to use get_the_post_thumbnail() instead of the_post_thumbnail(), though, since you’ll need one that has a post ID parameter, but after that, it’s smooth sailing.
nested
Hi,
I’m trying to add the thumbnail and I’m struggling to figure it out. Are there any examples?
Thanks in advance!
Jamie
See my comments to Suzette towards the top of the comment list. Should have all you need for post thumbnail display, or at least enough to get you moving a step forward.
Thanks, I’ll give that a try and let you know how it goes! Thanks for your wisdom! 🙂
Looks like the “trick” here is using “stats_get_csv” function. Haven’t heard about that. Thanks for sharing!
Is there a way to exclude categories or post-types from this display?
hello!
thanks for creating this lovely work around
one question: why isn’t it integrated into the larger wordpress Jetpack plugin?
It seems like folks have been trying to push for that for a few years at least…
https://plugins.trac.wordpress.org/ticket/1797
https://wordpress.org/support/topic/popular-post-widget-jetpack
I just found this article and I’m impressed. I already hacked the Jetpack module to keep pages out of the picture, so it’s not an issue right now (but I’m sure it will be if they ever update it).
I use a snippet from outside of WordPress to pull recent posts and save them to a file, then I include them (I keep my cache static). How hard would it be for me to do the same thing with this for popular posts?
I meant to say I use server side includes to include them, not PHP.
Great tip, but you should update the example to check if the class exists first.
if (class_exists('WDS_JetPack_Popular_Posts')) {
}
I love to use top post widget from Jetpack but i hate when i have to exclude certain post/pages by manually add the code. If there is an option to exclude post or pages that will be great.
Hi, can you please help me with my issue.
I installed this plugin, have JetPack turned on and it’s connected to wordpress.org.
Followed the steps from this article and don’t receive the posts. I use var_dump() for created object and have next:
object(WDS_JetPack_Popular_Posts)#595 (3) { [“post_count”]=> int(36) [“days”]=> int(3) [“transient”]=> string(14) “_popular_13465” }
Without any post. Also tried to use the third parameter in the array and checked with a condition if class exists, it does.
Thanks.
It’s possible you don’t have populated data quite yet.
Hi Michael,
Great post. I have a few doubts though.
1. Is it possible to assign days as unlimited. I want to get the popular posts without a time period.
2. Is it possible to remove categories.
I want to query popular posts from a certain category. Is it possible.
Thank you.
According to https://stats.wordpress.com/csv.php which is what’s queried against internally in Jetpack, a “-1” will do unlimited days for the “days” parameter from the post.
Not possible, it appears, for the initial query. You would need to do some post-query processing to check for assigned categories and either display only those, or remove others from the results, etc.
Hi , i am using this construction to display top posts from jetpack.
<?php
if(function_exists('stats_get_csv')){
if ( function_exists('stats_get_csv') && $top_posts = stats_get_csv( 'postviews', "days=90&limit=7")) {
echo '’;
foreach ( $top_posts as $post ) {
if($post[‘post_id’] && get_post($post[‘post_id’]))
echo ‘‘ .
get_the_title( $post[‘post_id’] ) .’ ‘.get_the_date(‘F j, Y’).’
‘;
}
echo ”;
}
}
?>
I would also like to add the date the post was published at, but the problem is that get the date does nothing for me :P.
Is there another way to show that date ?
I think the html tags got stripped 🙁
You need to provide the post ID to the get_the_date() function as well, much like you are for get_the_title(), get_permalink() etc. https://codex.wordpress.org/Function_Reference/get_the_date
I’ve been using this code to display top 5 posts in my sidebar for a while now but all of a sudden the top posts aren’t changing. It’s almost like it’s displaying a cached version…
Jetpack is still showing me the top five posts on my dashboard but they are simply not showing up in the sidebar.
Any ideas on how to fix this?
Not sure it’s a cache issue as it’s doing it on my local install too…
I ended up fixing the issue by changing the ‘transient_affix’ value to something else.
Not sure if this is a long-term solution but it did the trick…
You can try setting the transient_affix value to something dynamic, such as:
‘transient_affix’ => ‘posts’ . date(‘Ymd’)
This would force it to update daily, however, I’m not sure of the implications of cache storage unnecessary growing over time with this method.
Hustle is a great plugin for pop ups and slide in’s etc. They used to provide integration with Jetpack but doesn’t seem that they do anymore, but there is a guide on how to use Hustle with Jetpack subscriptions at https://blog.techygeekshome.info/2019/07/how-to-integrate-hustle-with-jetpack-email-subscriptions that may help people out a little.