When you place facets on an existing WordPress archive, search, blog/home or WooCommerce shop page, FacetWP will automatically detect the right query and post loop, and your facets will just work.

However, there are circumstances in which FacetWP’s automatic query/post-loop detection fails, resulting in the facets and listing not being updated:

Solving issues with FacetWP’s automatic post loop detection

How it works

On WordPress archive pages, including search result pages, blog pages, and the WooCommerce shop page and product category pages, FacetWP will automatically detect the main archive query to use for filtering.

Using WP’s loop_start hook, Facetwp identifies the post loop that uses this query, and a <!--fwp-loop--> HTML comment is placed above the post loop in the template.

Next, FacetWP’s front-end JavaScript looks for that HTML comment and automatically adds a facetwp-template class on its direct parent HTML element, unless there is already another facetwp-template class present on the page. FacetWP needs this class to dynamically replace all HTML within this container with the AJAX refresh that happens when facets are used.

When the facetwp-template class ends up missing because one of these steps go wrong, the solution is add it manually.

Note that this is also the fix for issues with some caching and optimization plugins (like Cloudflare) that minify HTML. HTML minification removes HTML comments, including the <!--fwp-loop--> comment needed by FacetWP.

Fix the loop detection

When the above described automatic query/post-loop detection fails (which can happen for a myriad of reasons), the facetwp-template class will not be not placed on the post-loop’s parent element. Without it, FacetWP does not know which content to dynamically replace, the facets will not work and the listing will not get updated when filtering.

The solution is easy: manually place the facetwp-template class on an element that (directly) surrounds the post loop, in the WP archive’s template file.

Find the correct WP archive file

First, you need to determine which template file is used for the archive page you are on. The exact file depends on your theme’s setup. See WordPress’ built-in Template Hierarchy for more information about how these filenames work.

As a general rule, these will be some of the file names:

Template File name
Default template: archive.php
Category archive: category.php
Taxonomy archive: taxonomy.php
Date archive: date.php
Author archive: author.php
Custom Post Type archive: archive-[posttype].php
Custom Taxonomy archive: taxonomy-[posttype].php
WooCommerce shop: archive-product.php
Search page: search.php
Blog home: home.php

Manually add the facetwp-template class

In the archive’s template file, you will find a post loop that starts with if ( have_posts() ) and an else statement for when there are no posts found, similar to this:

<div class="facetwp-template">

<?php
if ( have_posts() ) :
  while ( have_posts() ) :
    the_post();
    ?>
      <h1><?php the_title() ?></h1>
      <div><?php the_content() ?></div>
  <?php
  endwhile;
else :
  _e( 'Sorry, no posts matched your criteria.' );
endif;
?>
    
</div>

As can be seen in the above code, the facetwp-template class needs to be placed on a container element (usually a <div>) that surrounds the loop code, preferably on the direct parent element. If there is no container element, you can add one yourself.

Customizing WP archive queries

What is the right approach if you want to use a WP archive query but customize how it works, for example, sort it in a different way or modify the number of posts per page?

We often see developers doing this by using a custom WP_Query in a WP archive template. The downside of this approach is that the database is getting queried twice, adding unnecessary overhead. It also breaks plugins that rely on WP’s default archive query.

If your desired query is very complicated, it may indeed be best to build it with a custom WP_Query. But make sure to place it on a single page or post template, not on a WP archive. If you don’t want or cannot move the custom WP_Query from the WP archive, read the instructions below on how to make this work with FacetWP.

However, instead of using a separate custom WP_Query, it is often much easier to modify the already existing WP archive query with a pre_get_posts filter. Especially for basic query arguments like the post types to be fetched, the number of posts per page, or the sorting method.

Using a custom WP_Query on a WP archive

If you have a custom WP_Query on a WP archive page, and don’t want or cannot change the way things are set up, you have to tell FacetWP explicitly which query (not) to use.

FacetWP has built-in query detection that determines which query on the page is the main query to use for filtering. On WP archive pages, FacetWP by default will always prioritize the archive query ahead of any other query on the page, including the custom WP_Query you placed on that page. This is the reason why a custom query on a WP archive will lead to unexpected results: FacetWP is using another query than the one defined in the custom query.

Using the facetwp_is_main_query hook, it is possible to force FacetWP to ignore the archive query, and use the custom query instead. Add the following code to your (child) theme’s functions.php to do this:

add_filter( 'facetwp_is_main_query', function( $is_main_query, $query ) {
    if ( $query->is_archive() && $query->is_main_query() ) {
        $is_main_query = false;
    }
    return $is_main_query;
}, 10, 2 );

Using a Listing Builder shortcode on a WP archive

You may be tempted to place a Listing Builder shortcode on a WP archive, in order to customize the query, or to make use of the Listing Builder’s display features.

Generally, on WP archive pages, it would be better to not use shortcode templates but to use the WP archive template query itself (and if necessary, customize the archive query). Shortcode templates can best be placed on single pages or posts.

But if you want to keep using a template shortcode on a WP archive page, you have to tell FacetWP explicitly which query (not) to use. There are a few approaches to this, depending on what type of archive you are using.

How to determine if you are on a WP archive page

WP archive templates are a crucial part of how WordPress works, and a lot of plugins rely on these templates working correctly. But how do you know for sure if you are on a WP archive template (or any other type of default WordPress template)?

What is a WP archive page?

An “archive page” in WordPress refers to a collection of posts grouped by post type, category, tag, term, author, or date. The blog page (the post type archive for posts) and the search results page are also considered archive pages. The WooCommerce shop page is also an archive: it is a custom post-type archive of the post type “product”. The same is true for product category pages: they are custom taxonomy term archive pages.

WordPress automatically creates the queries on its archive templates. It has a built-in Template Hierarchy that defines which default archives are available and how you can add your own. When you create new custom post types or custom taxonomies (for example with plugins like Pods or Custom Post Type UI), these also will automatically have their own post-type and term archives.

Check for WP archive body classes

A quick way to determine if you are on a WP archive page is to look at the body classes of the page. WordPress automatically adds one or more classes depending on the archive type.

Most archives have the archive class. Additionally, there will be multiple classes specific to the type of archive. For example, categories will have category, terms term, and post type archives post-type-archive. The WooCommerce main shop page will have the body class post-type-archive-product.

The blog/home page will have the class blog and the search page the class search.

You are not on an archive when you are on a single page or post. Pages have the class page, and posts have the class single and, depending on the post type: single-[post-type].

Use WP’s conditional tags

Another way to determine on what type of template you are, is to temporarily echo or var_dump() one of WP’s conditional tags in your template file and see what its output is:

<?php
// Is an archive/search/blog if true
is_archive(); // Returns true on category, tag, author, date, custom post type, and custom taxonomy-based archives
is_search(); // Returns true on the WP search results page
is_home(); // Returns true on the blog page (the post type archive for posts - which is not necessarily the home page)

// Is not an archive if true
is_page(); // Returns true on single pages
is_singular(); // Returns true on single posts of any post type (post, attachment, page, custom post types).

// Use like this
var_dump( is_archive() ); // Returns bool(true) if it is on a WP archive page

// Or like this
if ( is_archive() ) { 
    echo "This is an archive template";
}
?>

See also