WPFilters is designed to work with WordPress’s main query on standard archive pages, category pages, and blog home pages. However, when you create a custom page template with your own WP_Query, the posts you want to filter come from your custom query rather than WordPress’s main query (which represents the page itself).
To make WPFilters work with a custom WP_Query, you need to mark the query with a special flag and use specific HTML markup. This tells WPFilters to apply filtering logic to your custom query and allows the frontend JavaScript to update the correct parts of the page when users interact with filters.
Required Setup
Query Flag
You must add ‘wpfilters’ => true to your WP_Query arguments. This marks the query so WPFilters applies its filtering logic, reads filter parameters from the URL, calculates which post IDs match the selected filters, and updates the query accordingly.
Without this flag, WPFilters treats your query as a regular unfiltered query and ignores it completely.
Note: Do not use ‘suppress_filters’ => true in your query arguments. WPFilters treats suppressed queries the same way WordPress treats get_posts() calls and skips them entirely.
Your query must allow filters to run for WPFilters to work properly.
Required HTML Markup
WPFilters relies on specific CSS classes and HTML structure so the frontend JavaScript can locate and update the correct page elements during AJAX filtering:
Results Wrapper: Your post loop output must be wrapped in an element with the class wpfilters-results. After a filter AJAX request, WPFilters replaces the content inside this wrapper with the filtered results.
Pagination Wrapper: Your pagination links should be wrapped in an element with the class wpfilters-pagination. This allows the JavaScript to find and update pagination after filtering.
Without these wrapper classes, the AJAX updates may fail or target the wrong page elements, causing the filter interface to malfunction.
Example Template
The following example shows a complete custom page template that works with WPFilters. This template is designed for classic WordPress themes that use get_header() and get_footer(), such as Twenty Twenty or custom child themes.
How the Template Works
The wpfilters Query Flag
The ‘wpfilters’ => true argument in the WP_Query marks this query for WPFilters processing. When this flag is present, WPFilters applies its filtering logic by reading filter parameters from the URL, calculating which post IDs match the selected filters, and (during AJAX requests) setting post__in to display only the matching posts.
Results Wrapper
The <div class=”wpfilters-results”> element wraps the entire post loop output. This wrapper is critical because the frontend JavaScript looks for this class to find where to inject filtered results. After a filter AJAX request completes, WPFilters replaces the content inside this wrapper with the new filtered posts.
For consistency, even the “no posts found” message is wrapped in an element with the wpfilters-results class. This ensures a stable target element exists whether posts are found or not.
Pagination Wrapper
The <nav class=”wpfilters-pagination”> element wraps the paginate_links() output. This wrapper allows the JavaScript to locate and update pagination links after filtering. Without this wrapper, pagination might not update correctly when filters change.
Pagination Variable Handling
Page templates use the page query variable for pagination, while archives use paged. The template code handles both by taking the maximum value of either variable, ensuring pagination works correctly regardless of which variable WordPress sets.
Important Considerations
Align Query with Filter Sources
Filter options are automatically generated based on the post types included in your WP_Query. WPFilters only displays filter options that are relevant to the post types you’re querying. If your WP_Query doesn’t include post types that have the taxonomy or custom field data your filters are built from, those filter options will not appear.
For example, if your filter element is configured to show categories but your WP_Query only includes the page post type, the category filter will appear empty because pages typically don’t have category assignments. Similarly, if you have a custom taxonomy filter for WooCommerce products but your query only includes regular posts, no filter options will display because posts don’t use product taxonomies.
Preserve URL Parameters in Pagination
WPFilters adds filter selections to the URL as query parameters. When users navigate between pages, these parameters must be preserved so filters remain active. You can extend the paginate_links() function with the ‘add_args’ parameter to keep filter parameters in pagination links.
Only pass safe, known parameter keys to avoid security issues. Do not blindly copy all values from $_GET without validation.
Block and Full Site Editing Themes
If you’re using a block theme or Full Site Editing (FSE) theme that doesn’t have traditional header.php and footer.php files, this template example will not work as written. For block themes, you’ll need to either create a child theme with classic template support or use the block theme’s equivalent HTML template parts and block patterns.
Installation and Setup
File Location
Save the template file in your active theme directory. For a parent theme, place it at: wp-content/themes/your-theme/wp-filters-query.php
For better maintainability, use a child theme: wp-content/themes/your-child-theme/wp-filters-query.php
Assign Template to a Page
- Go to Pages → Add New in your WordPress admin
- In the sidebar, find the Template option
- Select “WP Filters — custom query”
- Publish or update the page
Visit the page on the frontend and test your filters and pagination.
Summary
Using WPFilters with a custom WP_Query gives you full control over how content is displayed and filtered. By properly marking your query and structuring your template, you can build powerful, dynamic filtering experiences beyond standard WordPress archives.

