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 specific facet 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 );

Customize query arguments when specific facet choices are selected

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 );

Customize query arguments when any facet is in use, and/or on specific listing templates

The following example sets the orderby query argument if any facet is currently in use.

It also shows how to apply the code only on specific Listing Builder listing templates, in line 4. And it shows how to add a fallback orderby/order argument, in an array.

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 names you want to target $target_templates = array( 'template1', 'template2', 'template3' ); if ( in_array( $class->ajax_params['template'], $target_templates ) ) { if (! empty( $class->facets ) ) { // If any facet is selected $query_args['orderby'] = array( 'date' => 'DESC', // Order by date, in DESC order 'title' => 'ASC' // Order by post title in ASC order, as fallback order (if dates are the same) ); } } 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 );

Ignore sticky posts

FacetWP does not work well with sticky posts out of the box. To ignore sticky posts in FacetWP Listing Builder listings entirely, you can use the following snippet:

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_listing_name' == $class->ajax_params['template'] ) { // Replace 'my_listing_name' with the name of your Listing Builder listing $query_args['ignore_sticky_posts'] = true; } return $query_args; }, 10, 2);

See our sticky posts tutorial for more code examples and information about ignoring sticky posts in FacetWP listings, and how to make them work if you actually want them.

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,architecture"]

If it does, it uses a taxonomy query to narrow the query to only show posts with the term(s) specified in the attribute, in this example housing and architecture. The code assumes that if there are multiple terms in the attribute, they are comma-separated (with or without spaces).

The first part of the code stores the shortcode attribute values in a JavaScript variable FWP_HTTP.shortcode_atts, so they can also be used after a facet refresh, when FWP()->display->shortcode_atts does not work.

The second part gets the specified shortcode attribute’s values, converts them into an array, and passes them into a tax_query argument. Make sure to adapt the template name, attribute name and taxonomy in L28-30.

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

// Part 1: Store the shortcode attribute values for use after filtering add_action( 'facetwp_scripts', function() { foreach ( FWP()->display->shortcode_atts as $atts ) { if ( isset( $atts['template'] ) && isset( $atts['type'] ) ) { $shortcode_atts = $atts['type']; break; } } if( isset( $shortcode_atts ) ) { ?> <script> (function($) { $(document).on('facetwp-refresh', function() { FWP_HTTP.shortcode_atts = '<?php echo $shortcode_atts; ?>'; }); })(jQuery); </script> <?php } }, 100 ); // Part 2: Get the shortcode attribute values and use them in a tax_query argument add_filter( 'facetwp_query_args', function( $query_args, $class ) { $template = 'publications'; // Change 'publications' to the name of your listing template $attribute = 'project'; // Change 'project' to your custom attribute $taxonomy = 'category';// Change 'category' to the name of your (custom) taxonomy name if ( $template == $class->ajax_params['template'] ) { // Get the shortcode attributes from FWP_HTTP.shortcode_atts for use after filtering $shortcode_atts = isset( $class->http_params['shortcode_atts'] ) ? $class->http_params['shortcode_atts'] : ''; // Get the shortcode attributes before filtering foreach ( FWP()->display->shortcode_atts as $atts ) { if ( isset( $atts['template'] ) && $template == $atts['template'] && isset( $atts[ $attribute ] ) ) { $shortcode_atts = $atts[ $attribute ]; break; } } if ( $shortcode_atts !== '' ) { // Convert the attribute values to an array $terms = array_map( 'trim', explode( ',', $shortcode_atts ) ); $query_args['tax_query'] = [ [ 'taxonomy' => $taxonomy, 'field' => 'slug', 'terms' => $terms ] ]; // Add additional query arguments here } } return $query_args; }, 10, 2 );

Note that there is also the facetwp_shortcode_html hook, which can be used to change the shortcode’s placeholder/container 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

Last updated: November 11, 2024