Hugh Lashbrooke

Product manager by day, tabletop game designer by night.

WordPress: Random post order with correct pagination

, ,

Randomising the order of the returned posts in a WordPress query is easy – simply add  'orderby' => 'rand' to the arguments and you’re good to go – this is great, until you need to paginate the results. As soon as you navigate to the second page of the results, the posts are returned randomly once again and you get an entirely different set of posts that may or may not contain posts that you have already viewed – if you’ve experienced this before then you’ll know exactly how frustrating it can be. After having this problem numerous times myself I decided to find a way around it.

The first thing we need to do is make sure our PHP session is initiated. You will see the reason for this in the function itself, which is where the magic happens – here we will use MySQL’s RAND() function and supply it with a seed value so it uses the same random order on every subsequent page load. To do this we will store a random string as a PHP session variable so it can be used by MySQL as a reference for the order to use for each page. All we need to do is add this snippet to our theme’s functions.php file:


View this gist on GitHub

You will notice one extra operation on line 7 of this snippet – we also reset the seed value every time the first page of the posts are loaded. This means that as long as someone stays on the paginated pages they will see a consistent set of results, but once they go back to the first page the randomisation will reset and they will see the posts in a completely different order.

Note that in this example I have limited the ordering to the front page only (that is, the home page of the site when the front page is set to show your latest posts), but you can change the conditional to target any page or post type archive that you like.

36 responses to “WordPress: Random post order with correct pagination”

  1. Francisco Avatar
    Francisco

    Hi, I have very little knowledge of this, but I’ve seen the example page and change http://publicbeta.co/library/ but after a time and kept fixed the pagination, try adding it to a page I’m developing http://www.vidajarocha.com/orizaba/placecategory/directorio-completo/ paste the code you give and did not see any change, any suggestions? I would greatly appreciate your help. thanks

    1. Peterborough Design Avatar
      Peterborough Design

      We’re trying to implement this on the same WordPress theme that Francisco is using. One thing to note about Francisco’s link is that it points to a custom post type. Is there something we need to do to your code in order to make it work for custom post types?

      1. Hugh Lashbrooke Avatar
        Hugh Lashbrooke

        All you need to do is change the is_front_page() conditional and this will work on any pages you specify. What would be best for your use case would be to change it something like is_post_type_archive( ‘post_type_name’ ) – that should handle all the archive pages for the given post type. Basically, when you’re using the posts_orderby or pre_get_posts filters you can do almost anything to modify the query based on any conditional you like. This page should help you understand all the conditional tags that you can use: http://codex.wordpress.org/Conditional_Tags

  2. Cristian O. Balan Avatar
    Cristian O. Balan

    Hi man, thanks for your code but on the “library” demo I see the GET PAST THAT BRICK WALL AND START BUILDING YOUR FIRST WEB APP same on the first page (2nd position) and on the second page (at first position).
    !?

    1. Hugh Lashbrooke Avatar
      Hugh Lashbrooke

      It seems to be sorted out now – could possibly have just been a caching issue on the server. Have a look again and it should be handling things correctly now.

  3. Ami Avatar
    Ami

    Thank you for this! Saved me a lot of headache.

  4. olivier Avatar
    olivier

    Hi thanks for the snippet which work’s perfectyl on front end for me. I only have a problem in backend. Now the post list in the admin also display randomly.. any idea why ?

    1. Hugh Lashbrooke Avatar
      Hugh Lashbrooke

      That depends what conditions you replaced is_front_page() with. That conditional should make sure it only affects the correct pages. The best bet to make sure you only ever affect the frontend would be to add if( is_admin() ) return $orderby; as the first line of the function – that will make sure it never affects anything in the dashboard.

      1. olivier Avatar
        olivier

        Hi thanks,
        I’ve put is_archive condition. it seems to work partially now with the is_admin code added. the strange thing is that affects only one CPT list in admin, not the regular post.

        1. olivier Avatar
          olivier

          Correction, it works now … i made a typo.. thanks a lot and have a nice day.

  5. Manuel Avatar
    Manuel

    Hi thanks for the snippet!!! I have read the code and I’m trying to do with woo commerce. I’m using this code but the pagination problem appears… if I change the condition is_front_page por is_woocommerce_default_catalog works on the sorting function?

    thanks in advance
    /* sorting */
    add_filter( ‘woocommerce_get_catalog_ordering_args’, ‘custom_woocommerce_get_catalog_ordering_args’ );

    function custom_woocommerce_get_catalog_ordering_args( $args ) {
    $orderby_value = isset( $_GET[‘orderby’] ) ? woocommerce_clean( $_GET[‘orderby’] ) : apply_filters( ‘woocommerce_default_catalog_orderby’, get_option( ‘woocommerce_default_catalog_orderby’ ) );

    if ( ‘random_list’ == $orderby_value ) {
    $args[‘orderby’] = ‘rand’;
    $args[‘order’] = ‘desc’;
    $args[‘meta_key’] = ”;
    }

    return $args;
    }

    add_filter( ‘woocommerce_default_catalog_orderby_options’, ‘custom_woocommerce_catalog_orderby’ );
    add_filter( ‘woocommerce_catalog_orderby’, ‘custom_woocommerce_catalog_orderby’ );

    function custom_woocommerce_catalog_orderby( $sortby ) {
    $sortby[‘random_list’] = ‘Random’;
    return $sortby;
    }

  6. Manuel Avatar
    Manuel

    Hi thanks for the snippet!!! I have read the code and I’m trying to do with woo commerce. I’m using this code but the pagination problem appears… if I change the condition is_front_page por is_woocommerce_default_catalog works on the sorting function?

    thanks in advance
    /* sorting */
    add_filter( ‘woocommerce_get_catalog_ordering_args’, ‘custom_woocommerce_get_catalog_ordering_args’ );

    function custom_woocommerce_get_catalog_ordering_args( $args ) {
    $orderby_value = isset( $_GET[‘orderby’] ) ? woocommerce_clean( $_GET[‘orderby’] ) : apply_filters( ‘woocommerce_default_catalog_orderby’, get_option( ‘woocommerce_default_catalog_orderby’ ) );

    if ( ‘random_list’ == $orderby_value ) {
    $args[‘orderby’] = ‘rand’;
    $args[‘order’] = ‘desc’;
    $args[‘meta_key’] = ”;
    }

    return $args;
    }

    add_filter( ‘woocommerce_default_catalog_orderby_options’, ‘custom_woocommerce_catalog_orderby’ );
    add_filter( ‘woocommerce_catalog_orderby’, ‘custom_woocommerce_catalog_orderby’ );

    function custom_woocommerce_catalog_orderby( $sortby ) {
    $sortby[‘random_list’] = ‘Random’;
    return $sortby;
    }

  7. Marcos Avatar
    Marcos

    Can this be used on woocommerce? i would like my products showing random with the pagination, actualy there is no plugin that do this… thanks!

  8. Marcos Avatar
    Marcos

    Can this be used on woocommerce? i would like my products showing random with the pagination, actualy there is no plugin that do this… thanks!

  9. Argumentum Avatar
    Argumentum

    Thank you for this great snippet. I’ve been using it for a few months.

    But now it stopped working, I don’t know why. The posts are still displayed in a random order, but the pagination doesn’t work anymore — pages 2, 3 etc. will often show repeated posts.

    I’d be glad if you could update the snippet (if it’s possible to correct this behaviour with an update, that is).

    Thanks again.

    1. argumentum0 Avatar
      argumentum0

      Actually, it seems the issue is with caching. I tested the snippet with W3 Total Cache disabled, and it worked perfectly. Once I enabled W3 Total Cache, the pagination stopped working properly.

      1. argumentum Avatar
        argumentum

        I did some additional tests. Yes, it’s a caching issue. But the problem is Varnish, not W3 Total Cache. My bad.

  10. Argumentum Avatar
    Argumentum

    Thank you for this great snippet. I’ve been using it for a few months.

    But now it stopped working, I don’t know why. The posts are still displayed in a random order, but the pagination doesn’t work anymore — pages 2, 3 etc. will often show repeated posts.

    I’d be glad if you could update the snippet (if it’s possible to correct this behaviour with an update, that is).

    Thanks again.

    1. argumentum0 Avatar
      argumentum0

      Actually, it seems the issue is with caching. I tested the snippet with W3 Total Cache disabled, and it worked perfectly. Once I enabled W3 Total Cache, the pagination stopped working properly.

      1. argumentum Avatar
        argumentum

        I did some additional tests. Yes, it’s a caching issue. But the problem is Varnish, not W3 Total Cache. My bad.

  11. linslleisio Avatar
    linslleisio

    Brilliant and works well. I have a custom field (Featured) that I’d like to come first in a randomised order… then everything else random. Any ideas how to do this? Many thanks for any pointers.

  12. linslleisio Avatar
    linslleisio

    Brilliant and works well. I have a custom field (Featured) that I’d like to come first in a randomised order… then everything else random. Any ideas how to do this? Many thanks for any pointers.

  13. Lucy Avatar
    Lucy

    I have pasted your code in functions.php and it doesn’t work for me. The only change I made is I commented out the line if( is_front_page() ) { and line 31 }. Do we need to put in a condtional statement for it to work?
    I’m using the ‘search and filter’ plugin together with relevanssi. Would these plugins cause conflict with the code?

    1. Lucy Avatar
      Lucy

      With the code:
      session_start();
      add_filter(‘posts_orderby’, ‘randomise_with_pagination’);
      function randomise_with_pagination( $orderby ) {
      if( !is_admin() ) {
      $seed = $_SESSION[‘seed’];
      if (empty($seed)) {
      $seed = rand();
      $_SESSION[‘seed’] = $seed;
      } $orderby_statement = ‘RAND(‘.$seed.’)’; }
      return orderby;
      }
      there is no longer a repeat on the pagination page but if I go to the first page again and reload it doesn’t randomise the first page again.

  14. Lucy Avatar
    Lucy

    I have pasted your code in functions.php and it doesn’t work for me. The only change I made is I commented out the line if( is_front_page() ) { and line 31 }. Do we need to put in a condtional statement for it to work?
    I’m using the ‘search and filter’ plugin together with relevanssi. Would these plugins cause conflict with the code?

  15. phatmann Avatar
    phatmann

    Safari will often pre-fetch pages. If one of these pages is the front page, this prefetching will cause the session seed to be invalidated. So do not clear the session seed when hitting the front page. If you need to clear the seed, either expire it or find a more opportune moment to do it.

  16. phatmann Avatar
    phatmann

    Safari will often pre-fetch pages. If one of these pages is the front page, this prefetching will cause the session seed to be invalidated. So do not clear the session seed when hitting the front page. If you need to clear the seed, either expire it or find a more opportune moment to do it.

  17. Stewart Avatar
    Stewart

    Hi Hugh, I saw on a wp.org topic, you mention a change in WP 4.5 (https://wordpress.org/support/topic/random-12/) the allows us to not use the posts_orderby filter. Any chance I could get you to post an updated snippet?

  18. Stewart Avatar
    Stewart

    Hi Hugh, I saw on a wp.org topic, you mention a change in WP 4.5 (https://wordpress.org/support/topic/random-12/) the allows us to not use the posts_orderby filter. Any chance I could get you to post an updated snippet?

  19. Rodolfo Avatar
    Rodolfo

    My Problem is that randomize not only the first page where the different publication are showing, that’s great, but also the widgets that are installed…. for exemple “Last post” and that should not happen….

  20. Rodolfo Avatar
    Rodolfo

    My Problem is that randomize not only the first page where the different publication are showing, that’s great, but also the widgets that are installed…. for exemple “Last post” and that should not happen….

  21. Brad Dalton - wpsites.net Avatar
    Brad Dalton – wpsites.net

    Works well. I tried pre_get_posts but it didn’t work properly even though the method has been posted all over the internet.

  22. Brad Dalton - wpsites.net Avatar
    Brad Dalton – wpsites.net

    Works well. I tried pre_get_posts but it didn’t work properly even though the method has been posted all over the internet.

Leave a Reply

Your email address will not be published. Required fields are marked *