Overview

With this hook you can change the raw WP_Query arguments before the query is executed, and before facets are processed in the rendering process. The query argument array is the input for the query: it tells WordPress which posts to retrieve from the database, in which order, how many per page, etc.

The hook works similarly to WP’s pre_get_posts hook, but unlike that hook, it only runs on pages with facets, and it has access to information about the page, listing template and facets used, via the FacetWP_Renderer class. This can be used to let the code run only in certain conditions. For example, you can check:

  • if a specific Listing Builder template is used (with $class->ajax_params['template']).
  • if the page has a specific URI (with $class->http_params['uri']). Note that the “URI” is the part of the URL without the domain name and the query variables, and without beginning or ending slashes.
  • if specific facets or facet choices are currently in use (with $class->facets[ $facet_name ]['selected_values']).

See the code examples below for ways to use this.

Where to use this hook

In Listing Builder listing templates, this hook changes the results on the first page load and after facet filtering. For performance reasons, in other types of listing templates (like WP archives and custom WP_Query templates), this hook is prevented from changing the query on the first page load and will only affect the results after facet filtering.

To make this hook also run on the first page load in these other listing types, you can combine it with the following hook in 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

add_filter( 'facetwp_preload_force_query', '__return_true' );

Parameters

  • $query_args | array | An associative array of query arguments (see below)
  • $class | object | The FacetWP_Renderer class (see /includes/class-renderer.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

// Based on WP_Query. $query_args = [ 'post_type' => 'post', 'posts_per_page' => 15, // ... ];

Usage examples

Change the listing order

This example sorts the results by post title if the Listing Builder listing template is named “books”. The listing template name is available in the ajax_params object within the FacetWP_Renderer class:

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 ) { if ( 'books' == $class->ajax_params['template'] ) { // Change 'books' to the name of your listing $query_args['orderby'] = 'title'; $query_args['order'] = 'ASC'; } return $query_args; }, 10, 2 );

Remove posts

This example removes specific posts from the query on a page where the URI is events/festivals. The URI is available in the http_params object within the FacetWP_Renderer class:

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 ) { if ( 'events/festivals' == $class->http_params['uri'] ) { // Change 'events/festivals' to your page URI $query_args['post__not_in'] = [42,43,44]; // Remove these posts } return $query_args; }, 10, 2);

Customize query arguments when a facet or facet choice is in use

The facets and their selected values are available via $class->facets. The following example uses that to change the orderby and order query arguments only if a specific facet is in use:

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 ) { $facet_name = 'my_facet_name'; // Replace 'my_facet_name' with the name of your facet if ( isset( $class->facets[ $facet_name ] ) ) { // If this facet is present $selected = $class->facets[ $facet_name ]['selected_values']; if ( ! empty( $selected ) ) { // If this facet has any selected choices $query_args['orderby'] = 'title'; $query_args['order'] = 'DESC'; } } return $query_args; }, 10, 2 );

You can go even further and only change the query arguments if one or more specific facet choices are selected:

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 ) { $facet_name = 'my_facet_name'; // Replace 'my_facet_name' with the name of your facet if ( isset( $class->facets[ $facet_name ] ) ) { // If this facet is present $selected = FWP()->facet->facets[ $facet_name ]['selected_values']; $facet_values = array( 'my_facet_choice', 'my_other_facet_choice' ); // Replace with one or more facet choices. Use the facet value (as displayed in the URL when that choice is selected). if ( count( array_intersect( $selected, $facet_values ) ) > 0 ) { $query_args['orderby'] = 'title'; $query_args['order'] = 'DESC'; } } return $query_args; }, 10, 2 );

Add a taxonomy query

This example filters the query with a tax_query, which makes it return only posts that have one of the specified terms selected for the specified taxonomy types. Because of the checks in line 2, the filter only runs on the Listing Builder listing template with name gluten_free, and only if the URI is gluten-free/recipes:

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 ) { if ( 'gluten_free' == $class->ajax_params['template'] && 'gluten-free/recipes' == $class->http_params['uri'] ) { $query_args['tax_query'] = array( array( 'taxonomy' => 'types', // Change 'types' to your (custom) taxonomy name 'field' => 'slug', 'terms' => array( 'breakfast', 'lunch', 'dinner' ) // Change to your term slugs to filter ) ); } return $query_args; }, 10, 2 );

Add a taxonomy query based on a shortcode attribute

The following example checks if a Listing Builder listing template shortcode has an custom attribute project:

How to use shortcodes?

Shortcodes can be placed directly in post/page edit screens. You can also add them in text/HTML widgets. The WordPress Block Editor has a Shortcode block to place them in. And most Page builders have a dedicated shortcode module/widget. In PHP templates, shortcodes can be displayed with WP's do_shortcode() function: echo do_shortcode('[my-shortcode]');. More info

[facetwp template="publications" project="housing"]

If it does, it uses a taxonomy query to narrow the query to only show posts with the term specified in the attribute:

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 ) { foreach ( FWP()->display->shortcode_atts as $atts ) { if ( isset( $atts['template'] ) && isset( $atts['project'] ) ) { // Narrow results by the given project $query_args['tax_query'] = [ [ 'taxonomy' => 'project', 'field' => 'slug', 'terms' => $atts['project'] ] ]; break; } } return $query_args; }, 10, 2 );

Note that there is also the facetwp_shortcode_html hook, which can be used to change the shortcode’s HTML output (for example set a custom class) based on a custom shortcode attribute .

Using the current post or page ID or queried object

If you are using a Listing Builder listing template on a single post or page, be aware that the listing query does not have any page/post context during the AJAX refresh (when filtering). This allows these types of listings to load faster, but has the side effect that any info about the queried object, like the post ID of the page itself, is unknown during the refresh. The usual methods to get the post ID, like get_the_ID(), or global $post with $post->ID, and functions like get_queried_object(), will not work after filtering.

For example, if you want to get the post ID of the post/page itself to set certain query arguments (for example in a taxonomy query argument), you will notice that this only works on the first page load, but not after filtering.

The solution is to store the post ID in a JavaScript variable with the facetwp-refresh event:

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_action( 'wp_footer', function() { if ( is_singular() ) : ?> <script> document.addEventListener('facetwp-refresh', function() { FWP_HTTP.post_id = <?php echo get_the_ID(); ?>; }); </script> <?php endif; }, 100 );

Or, similarly, to store the current term slug on a term archive page:

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_action( 'wp_footer', function() { if ( is_tax() ) : ?> <script> document.addEventListener('facetwp-refresh', function() { FWP_HTTP.current_term_slug = <?php echo get_queried_object()->slug; ?>; }); </script> <?php endif; }, 100 );

Then, within the facetwp_query_args hook, you can retrieve the stored post ID or current term slug as follows:

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 ) { if ( 'my_template_name' == $class->ajax_params['template'] ) { // Replace 'my_template_name' with the name of your facet. Or use $class->http_params['uri'] as conditional $post_id = isset( $class->http_params['post_id'] ) ? $class->http_params['post_id'] : get_the_id(); // Do something with $post_id $current_term_slug = isset( $class->http_params['current_term_slug'] ) ? $class->http_params['current_term_slug'] : get_queried_object()->ID; // Do something with $current_term_slug } return $query_args; }, 10, 2 );

If you are using other hooks that do not have access to $class->http_params (like a pre_get_posts hook), or if you need to use the post ID or queried object info directly in the Query tab of the Listing Builder in Dev mode, you can access the stored post ID or queried object info with this code instead:

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

$post_id = isset( FWP()->facet->http_params[ 'post_id' ] ) ? FWP()->facet->http_params[ 'post_id' ] : get_the_id(); // Do something with $post_id $current_term_slug = isset( FWP()->facet->http_params[ 'current_term_slug' ] ) ? FWP()->facet->http_params[ 'current_term_slug' ] : get_queried_object()->ID; // Do something with $current_term_slug

More examples

See also