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
.
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.
Fortunately, this can be fixed by adding the following code to your (child) theme’s functions.php:
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 ); // randomize 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 );