Most Popular Posts By Category – Dynamic WordPress Hack


A couple days ago I twittered that I’d be share a Dynamic Most Popular Pages By Category WordPress hack. Its been in place on this blog for that time and I’ve noticed a decent improvement in the time people are spending on the site and the number of pages they visit.

Keep in mind, my increase is also a consequence of my categories being listed at the top of the page. People click through it often. I use it as a method to filter traffic and get visitors exactly where they want to be. Arguably, I need to go through some of my first posts and categorize them better, however, I’m sure many of you find yourself in the same position.

Adding a categorical most popular pages on category pages will provide you some relief until you can do that yourself. Either way, its still nice to have a another sorting method. And anything that helps the majority of your visitors improves the bottom line of most website’s goals.


Web Design Category Page:

Plugin & Version Requirements

WordPress.Com Stats WordPress.Com Stats is one of the best, and the least load intensive statistics tracker you can get for WordPress. Why? Because WordPress themselves hosts it! See the graph to the right for an example of how it appears in your dashboard. This is where the data is pulled from to create the popular posts list.

WordPress Popular Post – This “hack” is actually a modification to the WordPress Popular Post Plugin. Perhaps they will update it with this functionality in a future release.

WordPress 2.6 – I’m using this on a WordPress 2.6.x install. I’ve heard that the popular post plugin does not work on WordPress 2.5, but that may be an isolated issue. Give it a try and comment your results below.

WPPP – WordPress Popular Posts Modifications

You can see the code changes below, but here is a link to wppp.php modifications (1.3.4). I modified the 1.3.4 version of WordPress Popular Posts. I’ll try and keep this updated, but you may be able to make changes to future versions of the plugin (with my additions) by using something like winmerge to migrate new/old code

The wppp.php file we’re modifying here can be found in: /wp-content/plugins/wordpresscom-popular-posts/wppp.php (if the plugin is installed).

[UPDATE - 5-13-09] 1.3.5 – changes still apply but some are in slightly different spots. Here is the final file replacement: wppp.php (1.3.5)

  1. //Make changes to wppp.php version 1.3.4 and in this order for line numbers to be accurate
  3. //LINE 20 - ADD AFTER: ,'title_length' => '0'
  4. ,'by_category' => '0'
  6. //LINE 61 - REPLACE: $howmany *= 2;
  7. $howmany *= 5;
  9. //LINE 87 STARTS WITH: $results = $wpdb->get_results("
  12. // category hack
  13. $currentcat = $WPPP_defaults['by_category'];
  14. //Checks and toggle default query usage
  15. if (is_numeric($opzioni['by_category']) && $opzioni['by_category'] > 0) {
  16. $results = $wpdb->get_results("SELECT * FROM {$wpdb->posts} p LEFT OUTER JOIN wp_term_relationships r ON r.object_id = p.ID LEFT OUTER JOIN wp_terms t ON t.term_id = r.term_taxonomy_id WHERE IN (" . implode(',', $id_list) . ") AND p.post_type = '" . ( $opzioni['show'] == 'pages' ? 'page' : 'post' ) . "' AND t.term_id = '" . $opzioni['by_category'] . "'");
  17. } else {
  18. //note ID changed to upper case
  19. $results = $wpdb->get_results("SELECT ID FROM {$wpdb->posts} WHERE id IN (" . implode(',', $id_list) . ") AND post_type = '" . ( $opzioni['show'] == 'pages' ? 'page' : 'post' ) . "'");
  20. }
  22. $valid_list = array();
  23. foreach ( $results as $valid ) {
  24. $valid_list[] = $valid->ID; //note ID changed to upper case
  25. }
  27. //LINE 209 - ADD AFTER: $opzioni['title_length'] = $opzioni['title_length'] !== NULL ? $opzioni['title_length'] : $WPPP_defaults['title_length'];
  28. $opzioni['by_category'] = $opzioni['by_category'] !== NULL ? $opzioni['by_category'] : $WPPP_defaults['by_category'];

Category Template Additions

Now you need to add a function call to WPPP_show_popular_posts in your /wp-content/themes/[themename]/category.php file. I’ve customized it in such a way that if there are less than 5 posts in a category, that it wont display a the popular category widget. You can see it and easily change that functionality in the code you see below.

  1. <?php if (have_posts()) :?>
  2. <h1 id="cat_h1">Category: <?php single_cat_title() ?></h1>
  4. <?php
  5. $numposts = $wp_query->post_count;
  6. if (function_exists('WPPP_show_popular_posts') && $numposts >= 5) { ?>
  7. <div id="popularbycategory">
  8. <h2 style="padding:0;">TOP 5 <?php single_cat_title() ?> Articles</h2>
  9. <div class="alreadyread">
  10. <?php
  11. $category = get_the_category();
  12. WPPP_show_popular_posts("show=posts&by_category={$category[0]->term_id}&title=&number=5&days=360&format=- <a href='%post_permalink%' title='%post_title_attribute%'>%post_title%</a>");
  13. ?>
  14. </div></div>
  15. <?php } ?>

General Popular Posts

As a quick bonus, I thought I’d also give you the parameters of the general WPPP_show_popular_posts call that I’m using in the top left of all the pages on this site.

  1. <?php if (function_exists('WPPP_show_popular_posts')) WPPP_show_popular_posts("show=posts&title_length=45&title=&number=6&days=360&format=- <a href='%post_permalink%' title='%post_title_attribute%'>%post_title%</a>"); ?>

Extending The Idea

Note that the Popular By Categories hack I created was a rather quick fix. There’s more than one way to do it, and ways to make it more efficient/extendable. For example, pulling the popular categories for multiple delimited categories at once. That would come in handy for a those that assign multiple categories to a post and want to display a “Most Popular Posts Within This Posts Categories”. That’s a mouthful, and something I might do if its requested enough.

Leave a comment below with your results, examples, or questions.

Respond: Leave A Comment | Trackback URL

Entrupeners, Subscribe for the lastest tools, tips, and tutorials.

11 Responses to Most Popular Posts By Category – Dynamic WordPress Hack

  1. Hey Rob

    Do you use StatPress? How does it stack up against Stat? I’m still looking for one that’s not heavy on my site…

  2. hosts the stat data. This works just like google analytics. Doesn’t get any less intensive than that.

    Statpress I avoided because of the fact that it logs all the data to your DB. Lots of extra queries depending on how large your site is. Could cripple your server. If you only get say, 100 hits a day though, thats a different story.

  3. How many stats does this tool provide? Right now I use google analytics and the amount of information you can obtain from it is incredible.

  4. The main feature I like about stats is it has a summary of outgoing clicks without having to do anything to those links. Though google has this feature too. stats should not be too heavily relied upon for accurate data. It logs bots/spiders and user refresh/reloads as unique hits (its more of a pageviews hit tracker). Even so, it still keeps with your sites trends well enough that its worthy to have for the “popular pages/categories” plugin alone.

    There isn’t a single way you should view your stats. You should understand the logging that all of them do and review them when necessary. Sometimes you’ll pick up something you didn’t notice before. Also, wordpress and google analytics are the easiest ones to have and have virtually no drawbacks in terms of server efficiency.

  5. Sounds like a great idea. People will surely stay longer once they find the links to the most popular pages on the blog. Nobody like to blindly look through the archives.

  6. Resurrecting past posts from the archives is another important matter though which this doesn’t directly impact enough. Changed to wordpress output and manipulation of its taxonomy would directly help it.

  7. Hi Rob,

    I was googling for many hours searching for a plugin to show the most commented posts for each category for a web site i’m on. As i couldn’t find one, i decided to make it myself ! But i’m not a php nor a sql guru… So i googled again to find a way to access a post’s category id with a sql request, and i found your post. Your sql request on line 16 was exactly what i was looking for, but it didn’t work :(

    After some tries, i asked myself why you were testing wp_terms.term_id = wp_term_relationships.term_taxonomy_id because i thought i had to use the term_taxonomy table to make a link between wp_terms and wp_term_relationships…

    So i tried this :
    SELECT * FROM {$wpdb->posts} p LEFT OUTER JOIN $wpdb->term_relationships r ON r.object_id = p.ID LEFT OUTER JOIN $wpdb->term_taxonomy tt ON tt.term_taxonomy_id = r.term_taxonomy_id LEFT OUTER JOIN $wpdb->terms t ON t.term_id = tt.term_id WHERE p.ID IN (” . implode(‘,’, $id_list) . “) AND p.post_type = ‘post’ AND t.term_id = $cat_id;

    It’s a bit different from your code but then… it worked for me :)

    So, i’m not sure my comment is relevant, as i’m not an expert, but, in case, as you helped me a lot, i wanted to point it out to you…

    Hope it could help. Thanx a lot anyway !


  8. Are you editing the plugin or making your own within the functions.php or theme? That and version of the plugin and/or wordpress install would make the difference there.

    Or… I might have joined an extra table because of the data I wanted to display. This little hack is part of something else I was working on :)

  9. I’m puting the function most_popular_posts() ( inside the functions.php.

    But i had to add an extra parameter, $cat_id, to suit my needs. And then i had to find a sql request to select only the posts from the category wich id was past as the new parameter.

    I’m testing this on a 2.7.1 wordpress install.

    This is the final result :

    function most_popular_posts($no_posts = 5, $before = ”, $after = ”, $cat_id = null, $show_pass_post = false, $duration=”) {
    global $wpdb;
    $request = “SELECT ID, post_title, comment_count FROM $wpdb->posts, $wpdb->comments”;
    $request .= ” WHERE $wpdb->comments.comment_approved = ’1′ AND $wpdb->posts.ID=$wpdb->comments.comment_post_ID AND $wpdb->posts.post_status = ‘publish’”;
    $request .= ” AND $wpdb->posts.post_password =””;
    if($duration !=”")
    $request .= ” AND DATE_SUB(CURDATE(),INTERVAL “.$duration.” DAY) posts.post_date “;
    $request .= ” GROUP BY $wpdb->comments.comment_post_ID ORDER BY $wpdb->posts.comment_count DESC LIMIT $no_posts”;
    $ids_list = $wpdb->get_results($request);

    $id_list = Array();
    foreach ($ids_list as $id) {
    array_push($id_list, $id->ID);
    $request2 = “SELECT * FROM {$wpdb->posts} p LEFT OUTER JOIN $wpdb->term_relationships r ON r.object_id = p.ID LEFT OUTER JOIN $wpdb->term_taxonomy tt ON tt.term_taxonomy_id = r.term_taxonomy_id LEFT OUTER JOIN $wpdb->terms t ON t.term_id = tt.term_id WHERE p.ID IN (” . implode(‘,’, $id_list) . “) AND p.post_type = ‘post’ AND t.term_id = $cat_id”;
    $posts = $wpdb->get_results($request2);
    $posts = $ids_list;

    $output = ”;
    if ($posts) {
    foreach ($posts as $post) {
    $post_title = stripslashes($post->post_title);
    $comment_count = $post->comment_count;
    $permalink = get_permalink($post->ID);
    $output .= $before . ‘‘ . $post_title . ‘ (‘ . $comment_count.’)’ . $after;
    else {
    $output .= $before . “None found” . $after;
    echo $output;

  10. I see what you’re doing now. You’re doing a “popular by number of comments”. I assume you’re passing $cat or using get_the_category() in your theme template to make this dynamic on all pages based on the current category?

    This plugin does the same thing:

    It doesnt work on a categorical basis though. I probably would have modified that plugin before coming up with a new function for it. Though sometimes that’s more efficient. I’d have to look into it more.

    The hack I talk about in this post is a specific edit/hack to the WordPress Popular Post Plugin.

  11. In fact, I modified that plugin but I didn’t knew it ! The plugin you’re pointing me on is 90% the same function !

    Amazing to see how code fragments are reused, transformed and loose the link to their original source…

    I’ll tell the author about these additions to his function !

    Sorry I polluted this post with a different topic comments. But thanx for your enlightments :)

Leave a Reply

Custom Theme by Rob Malon | Content & Design © 2010 - RobMalon.Com - Chicago, Illinois