Hook of the Month: Customizing the Top Posts & Pages Widget

Let’s kick off 2016 with a new series: welcome to the first installment of Hook of the Month!

Hooks are places in WordPress code where you can add your own code or change the default behavior of WordPress. Jetpack includes many of those hooks — 430 at the time of writing. In this series, I’ll introduce you to a new hook every month.

Today, let’s look at hooks help you customize one of our most popular widgets, the Top Posts & Pages widget.

Top Posts & Pages Widget settings

The widget’s default configuration settings.

Jetpack’s Top Posts & Pages widget displays a list of the most popular posts and pages on your site. Here are its default customizing options:

The widget’s settings offer quite a few customization options, but we’ve also added filters and actions to the code — these are the hooks. The hooks allow you to customize things further to build a widget fits your specific needs. In this post, we’ll explore one filter and two actions.

Filter the number of days used to calculate Top Posts

By default, the widget calculates the most popular posts in the past two days. This short timeframe is often more relevant, especially if you post a lot. However, if you post a bit less or have yet to build a large audience, you might want to include more days’ or weeks’ worth of data.

With a filter, you can change this. Let’s update the widget to display a list of the most popular posts in the past month.

To do so, we’ll use the jetpack_top_posts_days filter. To get started, add the following code snippet to a functionality plugin:

function jetpackme_top_posts_timeframe() {
    return '30';
}
add_filter( 'jetpack_top_posts_days', 'jetpackme_top_posts_timeframe' );

We’ve entered “30” as the number of days worth of data to return, but you can enter any number of days. “-1” means unlimited.

Add data before or after each post in the widget

The Top Posts & Pages widget includes two actions:

jetpack_widget_top_posts_before_post
jetpack_widget_top_posts_after_post

These actions will allow you to insert data before or after each post appearing in the widget.

In the example below, I’ve used the jetpack_widget_top_posts_after_post action to insert the post date below each post:

/**
 * Top Posts Widget: add post date below each post.
 */
function jetpackme_add_date_top_posts( $post_id ) {
        $post_date = get_post_time(
                get_option( 'date_format' ),
                true,
                $post_id,
                true
        );
        printf( '<div class="top_posts_date">%s</div>', $post_date );
}
add_action( 'jetpack_widget_top_posts_after_post', 'jetpackme_add_date_top_posts' );

The widget includes six other filters, and five other actions. Do you want to learn more? Check the code here.

Is there a specific filter or module you’d like us to cover in our next Hook of the Month article? Let us know in the comments!

This entry was posted in Code snippets, Spotlight, Tips & Tricks and tagged , , , , , , . Bookmark the permalink.

28 Responses to Hook of the Month: Customizing the Top Posts & Pages Widget

  1. Anything to do with publicize is always welcome! Thanks for this!

  2. Amanda Rush says:

    Thanks for this, and I think this will be a great series. Can you cover how to customize the sharing buttons that are packaged with Jetpack? Because it would be totally awesome to not have to roll your own accessible share buttons and just tell clients, especially non-coding ones, that they can use Jetpack’s share buttons. I think they work with keyboard, anddo OK with screen readers, but not sure about the color contrast stuff, which would obviously be covered in the CSS. If there’s already a guide somewhere, I’d be happy to read that instead.

    Thanks,

    Amanda

    • Jeremy says:

      The sharing buttons are indeed keyboard accessible already, but we have some work to do to fix the contrast when using the “Text only” and “Icon + Text” button styles. Until that’s fixed, the quickest solution is probably to switch to a different button style in your sharing options. “Icon” or “Official Buttons” would do.

      You can of course use CSS code to customize the look of the buttons, but that code will be different depending on how you want the buttons to be displayed. It would be hard to create a general guide for that.

      If you need some help customizing a specific site, or if there are specific changes you’d like to make for all your clients, to all your installations of Jetpack, feel free to send us an email or post in the Jetpack support forums. If you give us some details about what you’d like to achieve, we’ll be happy to help!

  3. I would love to add a hook that adds a tracking parameter to the end of permalinks, like ?ref=topposts. That way we could track how many people are actually using the links in this widget to land on certain posts. This would also be useful for Related Posts.

  4. saniali68 says:

    I’m really interested of this !! The only thing is that I’m a learner , but I’ll try my best to know , even though for tomorrow use.

  5. Joseph says:

    Hi Jeremy,
    Can I directly add the code to my theme’ functions.php file?

    Regards,
    Joseph

    • Jeremy says:

      You can, but I’d recommend against it. Instead, place all code snippets you want to add to your site in a functionality plugin like this one:
      https://wordpress.org/plugins/code-snippets/

      • Joseph says:

        Thanks for your reply. I am trying to avoid using too much of plugins.

      • Jeremy says:

        No worries there!

        While the number of plugins you use on your site is important, the quality of those plugins is even more important. In practice, 10 little plugins with only a few lines of code might have a smaller footprint than a single plugin that would perform a lot of actions on your site.

        I hope this clarifies things a bit. If you’re interested in learning more about this topic, I’d recommend that you read this post!

  6. Joseph says:

    Hi Jeremy,
    Is the current popular posts calculate within the past two days? I see my most popular posts shown are even from the last 10 days ago.

    By the way, can I have the code to show from the last 30 days and beyond? (not to include the last 30 days)

    I place the following code to stop the heartbeat directly in to the functions.php file, and it was suggested to place right after the <?php as follow:

    
    <?php
    add_action( 'init', 'stop_heartbeat', 1 );
    function stop_heartbeat() {
    wp_deregister_script('heartbeat');
    }
    

    How can I place those specific location with the functionality plugin?

    Regards,
    Joseph

    • Jeremy says:

      Is the current popular posts calculate within the past two days? I see my most popular posts shown are even from the last 10 days ago.

      The Top Posts widget does indeed look at your most popular posts in the past 2 days. It doesn’t matter when the posts were published, though. The widget only checks what posts were popular on your site in the past 48 hours.

      By the way, can I have the code to show from the last 30 days and beyond? (not to include the last 30 days)

      I’m not sure I understand. Could you give me more details about this? If you’d like the Top Posts widget to look at the most popular posts for more than 30 days, you can change the number in the code snippet I posted above.

      How can I place those specific location with the functionality plugin?

      You can place the whole code in the functionality plugin I mentioned earlier.

  7. Joseph says:

    Hi Jeremy,
    Would it be possible to show the most popular posts from the previous month (in other words, within the last 30 days)? So that I would call the widget title as “Most Popular Last Month”.

    Regards,

    • Jeremy says:

      If you don’t want the Top Posts widget to display posts that were published more than a month ago, you can use the jetpack_widget_get_top_posts filter to exclude those posts, like so:

      /**
       * Remove all Popular posts that weren't published within the last month
       */
      function jeherve_remove_old_top_posts( $posts, $post_ids, $count ) {
      	foreach ( $posts as $k => $post ) {
      		// Date when the post was published
      		$post_date = strtotime( get_the_date( 'Ymd', $post['post_id'] ) );
      
      		// If the post was published more than 30 days ago, let's remove it from the Top Posts widget
      		if ( $post_date < strtotime( '-30 days' ) ) {
      			unset( $posts[$k] );
      		}
      	}
      	return $posts;
      }
      add_filter( 'jetpack_widget_get_top_posts', 'jeherve_remove_old_top_posts', 10, 3 );
      
  8. Joseph says:

    Hi Jeremy,
    So sorry, but I should have asked you that would it be possible to show the most popular posts between the last 30 to 60 days? So that it will be “Most Popular Last Month”.

    Regards,
    Joseph

    • Jeremy says:

      Sure thing. You can change the values in the code I posted above to change the timeframe to fit your needs.

      • Joseph says:

        Could you please amend the code for me to show between the last 30 to 60 days? I am afraid, I can’t amend by myself😦

      • Jeremy says:

        Something like this should work:

        /**
         * Remove all Popular posts that were published within the last month, and more than 2 months ago.
         * That leaves us with posts that were published between the last 30 to 60 days.
         */
        function jeherve_remove_old_top_posts( $posts, $post_ids, $count ) {
        	foreach ( $posts as $k => $post ) {
        		// Date when the post was published
        		$post_date = strtotime( get_the_date( 'Ymd', $post['post_id'] ) );
        
        		// If the post was published less than 30 days ago and more than 60 days ago,
        		// let's remove it from the Top Posts widget
        		if ( $post_date > strtotime( '-30 days' ) || $post_date < strtotime( '-60 days' )  ) {
        			unset( $posts[$k] );
        		}
        	}
        	return $posts;
        }
        add_filter( 'jetpack_widget_get_top_posts', 'jeherve_remove_old_top_posts', 10, 3 );
        
  9. Joseph says:

    Thanks Jeremy, but still couldn’t load it correctly. It shows me this message “There are no posts to display. Want more traffic?”

    • Jeremy says:

      In this case, you’ll need to get more views on the posts that you published between 30 and 60 days, so that some of them become popular posts.

  10. Vienda Maria says:

    Hi Jeremy, I would really like to put this widget into my footer, in a vertical line across the bottom of the page, instead of vertical down the side. How can I can I change that? Or can you recommend a plugin that does this for me? Thank you.

  11. Brian Ball says:

    Is there a way to display popular forum posts from bbpress using this plugin?

    • Jeremy says:

      Sure thing! When both Jetpack and bbPress are active, you can change the Top Posts widget options to display popular forum threads as well. Go to Appearance > Widgets to access your widget options.

  • Recent Comments

    Jeremy on Jetpack 4.3 and 4.3.1: A faste…
    Jeremy on Jetpack 4.3 and 4.3.1: A faste…
    Jeremy on Jetpack 4.3 and 4.3.1: A faste…
    Jeremy on Jetpack 4.3 and 4.3.1: A faste…
    Jeremy on Jetpack 4.3 and 4.3.1: A faste…
  • Archives

  • Enter your email address to follow this blog and receive notifications of new posts by email.

  • Install Jetpack to see our lineup of features.

    Install Jetpack Now

    Don’t need all Jetpack’s features? No problem. Only activate what you need!

    %d bloggers like this: