Random ordering in FacetWP
How to order by random
To sort results randomly in a listing template query, you can set the orderby
query argument to rand
, and order
to ASC
. Make sure to also add a secondary, fallback order (as shown in line 11 in the example below).
If you are using a custom WP_Query for your listing template, you can set the argument directly in its query arguments. When using a WP archive template, you can add it with a pre_get_posts filter.
If you are using a Listing Builder listing, you can use the facetwp_query_args hook. And if you are using a Listing Builder template in dev mode, you can add it to the query arguments like this:
How to use custom PHP code?
PHP code can be added to your (child) theme's functions.php file. Alternatively, you can use the Custom Hooks add-on, or a code snippets plugin. More info
<?php return [ 'post_type' => [ "post" ], 'post_status' => [ 'publish' ], 'posts_per_page' => 10, 'orderby' => [ 'rand' => 'ASC', // Order by random 'title' => 'ASC' // Use post title as a fallback order ] ];
See the official WP_Query documentation for more info about query arguments and other values to sort posts by.
Fix duplicate posts and pagination issues
Since FacetWP is AJAX-based, the problem with random ordering is that the results will be re-randomized on each facet interaction that fetches posts (including paging and sorting), which will lead to duplicate posts and other issues.
This can be fixed by adding the following code to your (child) theme’s functions.php. It adds a so-called “seed” to the random order.
The code creates a new random seed every set time interval, set in seconds line 2. In this example, we set the interval to 10800
, which is three hours. This means that every three hours, the order will re-randomized (so not on every page load).
How to use custom PHP code?
PHP code can be added to your (child) theme's functions.php file. Alternatively, you can use the Custom Hooks add-on, or a code snippets plugin. More info
<?php function preserve_random_order( $orderby ) { $seed = floor( time() / 10800 ); // Re-randomize after this time (in seconds). 10800 means every 3 hours. $orderby = str_replace( 'RAND()', "RAND({$seed})", $orderby ); return $orderby; } add_filter( 'posts_orderby', 'preserve_random_order' );
Using the facetwp_query_args hook
The following example shows how you can use the facetwp_query_args hook to add random ordering (and a fallback order) to specific (or all) Listing Builder listing templates:
How to use custom PHP code?
PHP code can be added to your (child) theme's functions.php file. Alternatively, you can use the Custom Hooks add-on, or a code snippets plugin. More info
add_filter( 'facetwp_query_args', function( $query_args, $class ) { // Define an array of Listing Builder listing template names you want to target $target_templates = array( 'template1', 'template2', 'template3' ); if ( in_array( $class->ajax_params['template'], $target_templates ) ) { // Remove this condition to apply the code to all Listing Builder listings $query_args['orderby'] = array( 'rand' => 'ASC', // Order by random 'title' => 'ASC' // Use post title as a fallback order ); } return $query_args; }, 10, 2 );
Note that you still need to add the above extra snippet to fix duplicate posts and pagination issues.
To apply the random ordering only when facets are in use, you can adapt the above snippet as follows. The random ordering will only be applied when there are actual facet selections, so not when using a Pager facet.
How to use custom PHP code?
PHP code can be added to your (child) theme's functions.php file. Alternatively, you can use the Custom Hooks add-on, or a code snippets plugin. More info
add_filter( 'facetwp_query_args', function( $query_args, $class ) { // Define an array of Listing Builder listing template names you want to target $target_templates = array( 'template1', 'template2', 'template3' ); if ( in_array( $class->ajax_params['template'], $target_templates ) ) { // Remove this condition to apply the code to all Listing Builder listings $in_use = array_filter( $class->facets, function( $value, $key ){ return !empty( $value['selected_values'] ); }, ARRAY_FILTER_USE_BOTH ); if ( ! empty( $in_use ) ) { // If any facet has selections $query_args['orderby'] = array( 'rand' => 'ASC', // Order by random 'title' => 'ASC' // Use post title as a fallback order ); } } return $query_args; }, 10, 2 );