Random Product Sorting with Pagination

In this tutorial – not only how to display products in a random order but also how to prevent randomly displayed products from being duplicated if they run over pagination.

Here is what we are going to create in this tutorial:

Sort products in a random order with pagination
I hope it is clear what happens on the screenshot 😁

When a visitor choose “Sort in a random order” – the products are going to be displayed randomly and every time the Shop page is loaded, products will be randomized BUT when the visitor clicks on the pagination links, the product order remains the same! So, no products will be repeated twice.

Step 1. Add a New Sorting Option

add_filter( 'woocommerce_catalog_orderby', 'misha_random_sorting_option' );
 
function misha_random_sorting_option( $options ){
 
	$options['rand'] = 'Sort in a random order';
	return $options;
 
}
Add sort in a random order option

When we added sorting options in the original tutorial, we also used a filter hook woocommerce_get_catalog_ordering_args to make the ordering work, but in this example we do not need it, because our sorting will happen on another level, with posts_orderby hook.

Step 2. Sort Products in a Random Order with a Seed to Retain Pagination

First of all – just a small introduction into SQL RAND() syntax. The thing is that RAND() accepts the only parameter, once provided RAND( N ) returns the same value each time.

WordPress orderby works on the base of RAND() of course and yes, there are a couple filter hooks which allow you to modify SQL statements in WordPress before their execution. These hooks are posts_orderby (that’s what we need), posts_where, posts_join etc.

session_start();
 
add_filter( 'posts_orderby', 'misha_rand_order_with_seed' );
 
function misha_rand_order_with_seed( $orderby ){
 
	if( !is_shop() ) return $orderby;
 
	// do the magic only when "Sort in a random order" is selected
	if( isset( $_GET['orderby'] ) && 'rand' === $_GET['orderby'] ) {
 
		// reset the order each time the 1st page is visited
		if( ! is_paged() && isset( $_SESSION['seed'] ) ) {
			unset( $_SESSION['seed'] );
		}
 
		$seed = false;
		if( isset( $_SESSION['seed'] ) ) {
			$seed = $_SESSION['seed'];
		}
 
		// Set a new seed if not exists
		if ( ! $seed ) {
			$seed = rand();
			$_SESSION['seed'] = $seed;
		}
 
		// pass it to an SQL query
		$orderby = 'RAND(' . $seed . ')';
 
	}
 
	return $orderby;
 
}

Keep in mind that posts_orderby is triggered everywhere, even in WordPress admin, so don’t forget about conditional statements, I uses is_shop() which means the Shop page, for WooCommerce you can also use is_product_category() or is_product_tag() depending on the page where youre going to implement the random posts order.

And yes, the code can be used not only for WooCommerce products but for any post types.

Very related posts

Misha Rudrastyh

Misha Rudrastyh

I love WordPress, WooCommerce and Gutenberg so much. 10 yrs of experience.

Need some custom developer help? Let me know

Follow Misha

Need some help with WooCommerce?

If you need some professional developer help, I will be happy to assist you.

Contact me Who I am?

Leave a comment

php js HTML CSS Code