DiggingIntoWordPress

by Chris Coyier & Jeff Starr

DIY WordPress Popular Posts

Posted by on

Over at my code snippets site, I keep track of the most popular posts and display a list in the sidebar. It's an easy way to highlight the site's best content and share top snippets with visitors. There are numerous plugins available for displaying your site's popular posts, but they tend to be overkill and/or employ weird algorithms that are just unnecessary and not always accurate.

For example, a lot of plugins and techniques calculate popular posts based on number of comments. These days I'm just not sure if that's a relevant measure of popularity. Some sites have comments disabled, and other sites receive very few comments in general, so going the comment-count route just doesn't work.

What I wanted was a simple way of counting hits and displaying a simple list of the most popular posts. This DigWP tutorial explains how to do it with two easy steps.

Example

Here is an example/screenshot of what we're going to build in this tutorial:

DIY Popular Posts Example

This screenshot is taken from my snippets site, WP-Mix.com. You can see an example of the site's "Popular Posts" list in the sidebar of this post. Of course, the list will look different when displayed on your own site, depending on the styles that are applied via your theme's CSS. This tutorial focuses on the PHP/HTML.

I think this technique is awesome because 1) it's very straightforward: popularity is measured by the number of times a post is visited, and 2) it's very flexible, so you can easily change the number of displayed posts, markup, and so forth.

The best part is that it only takes a few steps to implement this technique on any WordPress-powered site. Read on to learn how it's done in 2 copy/paste steps..

Step 1: Counting Hits

Add the following code to your theme's functions.php file:

// DIY Popular Posts @ https://digwp.com/2016/03/diy-popular-posts/
function shapeSpace_popular_posts($post_id) {
	$count_key = 'popular_posts';
	$count = get_post_meta($post_id, $count_key, true);
	if ($count == '') {
		$count = 0;
		delete_post_meta($post_id, $count_key);
		add_post_meta($post_id, $count_key, '0');
	} else {
		$count++;
		update_post_meta($post_id, $count_key, $count);
	}
}
function shapeSpace_track_posts($post_id) {
	if (!is_single()) return;
	if (empty($post_id)) {
		global $post;
		$post_id = $post->ID;
	}
	shapeSpace_popular_posts($post_id);
}
add_action('wp_head', 'shapeSpace_track_posts');

This code contains two functions. The first function checks and sets the hit count for the post. The second function hooks into wp_head and calls the first function whenever a single post is loaded. A simple yet elegant way of counting hits.

To learn more about how these functions work, check out the following resources at the WordPress Codex:

Basically we're using the entire suite of *_post_meta functions to get, check, add, update, and delete the popular_posts Custom Field based on page view and current hit count. It's very bare-bones but perfectly effective. I've been using this technique for several years now at WP-Mix.com. It just works :)

Step 2: Displaying Popular Posts

At this point the base technique is implemented and ready for use. As visitors view your pages, the popular_posts fields will populate with hit-count data. There are numerous ways of querying this information and using it to display a list of the most popular posts, but the best way is to use WP_Query to create a Custom Loop. For example, the following code is clean, compact, and flexible:

<h3>Popular Posts</h3>
<ul>
	<?php $popular = new WP_Query(array('posts_per_page'=>7, 'meta_key'=>'popular_posts', 'orderby'=>'meta_value_num', 'order'=>'DESC'));
	while ($popular->have_posts()) : $popular->the_post(); ?>
	<li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
	<?php endwhile; wp_reset_postdata(); ?>
</ul>

You can add that snippet to your theme via any template that makes sense. For example, at WP-Mix.com, I include that exact code in the sidebar.php template. Essentially, it creates a Custom Loop, which goes something like this:

  1. Query seven posts with the highest numerical value for popular_posts
  2. Loop through the queried posts and display each post title as a link
  3. End the loop and reset the $post variable using wp_reset_postdata()

The trick here is using meta_value_num as the value of the orderby parameter in WP_Query. That's how WordPress orders the chosen number of posts by the value of the popular_posts Custom Field. Check out the WP Codex to learn more about how this works, and how to further customize the query.

Customizing

So that's all there is to it. Two steps and done. Of course, you'll probably want to customize things to suit your needs. Here are a few quick examples demonstrating how to customize your new list of Popular Posts:

  • Change number of posts displayed by changing 'posts_per_page'=>7
  • Display least popular posts by changing 'order'=>'DESC' to 'order'=>'ASC'
  • Order posts by comment count by changing 'orderby'=>'meta_value_num' to 'orderby'=>'comment_count'
  • Modify the markup to display the post title, content, category, author, date, tags, etc.

Much more is possible using the many parameters provided by WP_Query. The technique is very flexible, which is one of the reasons why I prefer "rolling my own" rather than installing a plugin that provides more functionality than I need. This minimalist strategy helps to keep my sites fast and furious.

Bonus! Link to all popular posts

As a bonus, here is a technique that I use to display all popular posts when a user clicks a link. You can see what I'm talking about by clicking this link: display all popular posts at WP-Mix. Here is the code that I add to functions.php:

// DIY Popular Posts @ https://digwp.com/2016/03/diy-popular-posts/
function shapeSpace_display_popular_posts($query) {
	
	$get_pop = (isset($_GET['popular-posts']) && !empty($_GET['popular-posts'])) ? true : false;
	
	if ($get_pop && is_main_query() && !is_admin()) {
		$query->set('meta_key', 'popular_posts');
		$query->set('orderby', 'meta_value_num');
		$query->set('order', 'DESC');
		
		add_action('loop_start' , 'shapeSpace_before_loop');
	}
}
add_action('pre_get_posts', 'shapeSpace_display_popular_posts');

function shapeSpace_before_loop() {
	echo '<h3>Popular Posts</h3>';
}

Here is how this code works:

  1. Check the value of the $_GET variable
  2. If it's a popular-posts query, set our new query variables
  3. Add an action hook that we use to add a bit of markup
  4. Hook the whole thing into pre_get_posts

This technique provides a spiffy way to display a paged archive of all your posts organized according to popularity (page views). As with the previous WP_Query loop, there are many ways to customize this pre_get_posts technique to display exactly the posts that you want to display, popular or otherwise.

3 Responses

  1. Duke Vukadinovic March 24, 2016

    Hi Jeff,

    I really like how you explained in a simple way how to count hits and display them in the form of a simple list of the most popular posts.

  2. thanks, and I guess if you wanted a bit of trend metrics you’d also keep a date associated with each ‘count’? Not sure how that would work.

    And you could zero counts out by?

    • Jeff Starr

      Sure, anything is possible. Once you have the basic technique, you could embellish with all sorts of additional functionality, more Custom Fields, etc. Currently if you want to zero a post count, you can simply change its value directly.

Comments are closed. Contact us with any critical information. Thank you!

Code is poetry