How To Make Sticky Posts Even Stickier In WordPress

Some ambivalent sticky things

As WordPress becomes more of a content management API and framework there are times when some of its legacy features are too mired in the context of “blog” to really be useful when it’s in use as a full content management system. Sticky posts are a great example. They only work on the index page (or custom blog page if you set your site up that way). ‘Stickiness’ isn’t just useful for the home page of a WordPress site but useful on individual category lists or archive pages, and even in the admin area.

If you want sticky posts to stick everywhere then adding the following code snippet to your functions.php file will work for you:

You can always add some extra conditional logic into the sticky_posts_query() function to restrict stickiness to the admin only, or to a certain category or archive. Go forth and play.

Image credit: pineapple9995

Comments
  • Jason 4 / Jun / 2016 at 4:02 am

    Hi All,
    Great post Robert! Thank for pointing me in the right direction.
    For those wanting to make this work in more recent WP versions, I’m running WP 4.5.2 and the following updates make it work:
    – First of all, change the menu order of the sticky posts from -1 to 1. The order is descending order so you want the 1’s first then the 0’s.
    – Second, update sticky_posts_query function to not check whether year isset because it’s always set and the $q is passed by reference, so no return needed and I’m using the updated set function to set the orderby:
    `function sticky_posts_query( $q ) {
    if ( ! is_admin() && ( ! isset( $q->query_vars[ ‘ignore_sticky_posts’ ] ) || ( isset( $q->query_vars[ ‘ignore_sticky_posts’ ] ) && ! $q->query_vars[ ‘ignore_sticky_posts’ ] ) ) && ! $q->query_vars[ ‘year’ ] && ! $q->query_vars[ ‘monthnum’ ] && ! $q->query_vars[ ‘day’ ] && ! isset( $q->query_vars[ ‘orderby’ ] ) ) {
    $q->set(‘orderby’, ‘menu_order date’);
    }
    }`
    Enjoy!

  • Mary 13 / May / 2016 at 12:20 pm

    Trisha
    Hi Robert – Glad I found this post but wondering if you’ve had a chance to look at updating this for current version of WP? I’m facing this problem of needing sticky posts on archive pages as well as CPT archives, but this code above is not working…..no errors, just doesn’t put the sticky posts at the top.

    Same here 🙁

  • Trisha 3 / May / 2016 at 11:08 pm

    Hi Robert – Glad I found this post but wondering if you’ve had a chance to look at updating this for current version of WP? I’m facing this problem of needing sticky posts on archive pages as well as CPT archives, but this code above is not working…..no errors, just doesn’t put the sticky posts at the top.

    • Mim McNeela
      Mim 4 / May / 2016 at 9:34 am

      Hi Trisha, thanks for your comment. We haven’t tested this recently, so it may well need some updating. I’ll open a case for someone to look at it if we ever get some spare time, but as we’re fully booked with paid work I can’t promise it will be any time soon.

  • Dave baldwin 17 / Jul / 2014 at 10:07 pm

    Hi, I am assuming this code now no longer works on wordpress version 3.6+ – as added the code to functions.php, but the ordering of posts in categories with stickies is the same as before – no change.

    • Robert O'Rourke
      Robert O'Rourke 18 / Jul / 2014 at 10:03 am

      I’ve not tested it recently so it may need a refresh. Thanks for letting us know.

  • WordPress without plugins | Pearltrees 27 / Feb / 2013 at 9:15 pm

    […] How To Make Sticky Posts Even Stickier In WordPress | Interconnect IT – WordPress Consultants, Web D… […]

  • Emil Ellerbek 30 / Jul / 2012 at 12:40 pm

    Works great – but is there a way to make this work for custom post types? 🙂

    • Robert O'Rourke
      Robert O'Rourke 30 / Jul / 2012 at 12:58 pm

      The filter doesn’t care what post type something is so it should work for custom ones too. Is that not the case for you?

      • Emil Ellerbek 30 / Jul / 2012 at 1:04 pm

        No, it only shows up in posts. Is there a way of register it in register_post_type?

        Thanks for the fast reply! 🙂

        • Robert O'Rourke
          Robert O'Rourke 30 / Jul / 2012 at 2:08 pm

          Is your post type added by a plugin or is it code that’s part of your theme? Just wondering if there might be some code that’s setting the ‘orderby’ part of the query.

          • Emil Ellerbek 31 / Jul / 2012 at 8:54 pm

            It’s a part of my theme.
            Looks like this: http://codepad.org/8SNMxaSD

          • Emil Ellerbek 1 / Aug / 2012 at 12:40 pm

            Just tried with the “Custom Post Type UI” plugin and it still didn’t work :/

          • Robert O'Rourke
            Rob 1 / Aug / 2012 at 2:25 pm

            I’ll do some more testing here and see if I can work it out. Might be worth putting a var_dump() or print_r() in the pre_get_posts filter t see if it’s actually running on your post type list. Sorry it’s not working for you :/

          • Emil Ellerbek 4 / Aug / 2012 at 8:12 am

            Nothing happens :/

  • Anton 15 / May / 2012 at 9:02 am

    one “}” missing to close the fix_sticky_posts function.

    I pasted the code as I wanted to make sure sticky posts are at the top of their own category page but it doesn’t work yet. Maybe it wasn’t the purpose. thx for your work though !

    • Robert O'Rourke
      Robert O'Rourke 15 / May / 2012 at 11:21 am

      Hey Anton,

      Thanks, there was a typo in the gist that I’ve fixed now. You should see the ordering take effect as soon as you’ve put the code in, and then made a post sticky/unsticky. Definitely should work on category pages etc… too.

  • Simon Fransson 30 / Jan / 2012 at 3:44 pm

    Great solution! I’ve run in to this problem of a number of occasions and haven’t this is by far the best way to solve it IMO.

    I noticed how ever that posts are still sticky (i.e. menu_order = -1) even after I make them un-sticky. To account for this I made a slight modification to you function, checking which posts are missing from the new list of sticky posts and resetting the menu_order of these posts.

    
    function fix_sticky_posts( $stickies ) {
        
        $old_stickies = array_diff(get_option( 'sticky_posts' ), $stickies);
        
    	foreach( $stickies as $sticky ) {
    		wp_update_post( array( 'ID' => $sticky, 'menu_order' => -1 ) );
    	}
    	
    	foreach ($old_stickies as $sticky) {
    		wp_update_post( array( 'ID' => $sticky, 'menu_order' => 0) );
    	}
    	
    	return $stickies;
    }
    add_filter('pre_update_option_sticky_posts', 'fix_sticky_posts');
    
    • Robert O'Rourke
      Robert O'Rourke 30 / Jan / 2012 at 3:48 pm

      D’oh! Great catch – thought I’d tested that… oops :/

      I’ll update the code, thanks Simon.

  • Adam 30 / Jan / 2012 at 3:15 pm

    Where in functions.php?

    • Robert O'Rourke
      Robert O'Rourke 30 / Jan / 2012 at 3:38 pm

      Anywhere really, for simplicities sake just paste it in at the bottom of the file before the ‘?>’