What are facets?

Facets are UI elements used to filter, or “drill down”, content listings. Facets are aware of the content, and only relevant choices are displayed.

FacetWP offers many different facet types, such as checkboxes, dropdowns, etc. Some facet types are built-in, others you have to install as add-on plugins.

Create a facet

Browse to Settings > FacetWP, then click on “Add New” beside the Facets header. FacetWP includes a sample facet (Categories) to help get you started.

Set facet options

Each facet has its own set of options (which vary depending on the facet type).

Here’s an example of a facet edit screen:

Build the index

Re-index buttonAfter you have saved your facets, click the Re-index button.

This may take a few minutes depending on how much content exists on your site, so please be patient. The progress bar below the button will refresh every few seconds with the percentage completed.

It is not necessary to keep the page open while the indexer is running. If the page is closed, indexing will still finish but it might take a bit longer.

Display a facet

Copy the shortcode

Copy shortcode buttonCopy shortcode in facet overviewAfter creating the facet and setting it’s options, click the red “Copy shortcode” button.

It’s also possible to copy shortcodes directly from the Facets listing screen. Click the cog/gear icon on the right side of the facet’s row and click “Copy shortcode” in the dropdown.

You can also create your shortcode manually, using the facet name (the name in the grey box). Each facet’s shortcode looks like this:

[facetwp facet="the_facet_name"]

Place the shortcode

Place FacetWP shortcode into a WP block editor Shortcode block
How to past a facet or listing shortcode into a WP Shortcode block.

Paste the shortcode into the body field of your page, or into Text widgets (Appearance > Widgets) of – for example – your sidebar.

If you’re using the WordPress block editor, you can also paste shortcodes into a Shortcode block.

Display a facet with PHP

Facets can also be placed directly in your WordPress archive templates, custom templates or includes, with PHP:

echo facetwp_display( 'facet', 'the_facet_name' );

How to duplicate facet

Duplicate, copy or clone a facet Since FacetWP v4.0 it is very easy to clone/duplicate a facet, including all its settings:

Go to Settings > FacetWP and click the Facets tab. On the right side of the row of the facet you want to clone, click the cog/gear icon and click “Duplicate” in the dropdown. This instantly creates a full copy of the facet and its settings, with the label and facet name having the word “copy” added.

You can then change the new facet’s label, name and settings and click “Save changes”. Don’t forget to hit the Re-index button afterwards.

Add a Listing Template

In order for facets to appear, they need to know which posts / query to filter upon.

Facets need what is called a Listing Template. There’s quite a few Listing Template options to choose from.

How to add labels / headings above each facet

FacetWP does not automatically output facet labels / headings, except in the Mobile Flyout menu.

However, it’s possible to add them using a bit of custom code in your (child) theme’s function.php (or use the Custom Hooks add-on). Or place the script part in your theme’s header.php or, better yet, into a custom javascript file.

The code below adds labels to each facet except Pager and Sort facets, as that would not make much sense:

function fwp_add_facet_labels() {
  ?>
    <script>
      (function($) {
        $(document).on('facetwp-loaded', function() {
          $('.facetwp-facet').each(function() {
            var facet = $(this);
            var facet_name = facet.attr('data-name');
            var facet_type = facet.attr('data-type');
            var facet_label = FWP.settings.labels[facet_name];
            if (facet_type !== 'pager' && facet_type !== 'sort') {
              if (facet.closest('.facet-wrap').length < 1 && facet.closest('.facetwp-flyout').length < 1) {
                facet.wrap('<div class="facet-wrap"></div>');
                facet.before('<h3 class="facet-label">' + facet_label + '</h3>');
              }
            }
          });
        });
      })(jQuery);
    </script>
  <?php
}

add_action( 'wp_footer', 'fwp_add_facet_labels', 100 );

Show labels only if facets have options

The code below also adds labels to each facet (except Pager and Sort facets). But it removes them when a facet has no options. The facets for which you want this to happen, need the “Show ghosts” option to be disabled.

function fwp_add_facet_labels() {
  ?>
    <script>
      (function($) {
        $(document).on('facetwp-loaded', function() {
          $('.facetwp-facet').each(function() {
            var facet = $(this);
            var facet_name = facet.attr('data-name');
            var facet_type = facet.attr('data-type');
            var facet_label = FWP.settings.labels[facet_name];
            if (facet_type !== 'pager' && facet_type !== 'sort') {
              if (('undefined' === typeof FWP.settings.num_choices[facet_name] ||
                ('undefined' !== typeof FWP.settings.num_choices[facet_name] && FWP.settings.num_choices[facet_name] > 0)) && $('.facet-label[data-for="' + facet_name + '"]').length < 1) {
                facet.before('<h3 class="facet-label" data-for="' + facet_name + '">' + facet_label + '</h3>');
              } else if ('undefined' !== typeof FWP.settings.num_choices[facet_name] && !FWP.settings.num_choices[facet_name] > 0) {
                $('.facet-label[data-for="' + facet_name + '"]').remove();
              }
            }
          });
        });
      })(jQuery);
    </script>
  <?php
}

add_action( 'wp_footer', 'fwp_add_facet_labels', 100 );

Customize facet heading HTML and contextual facet headings

If you need more flexibility in customizing the HTML output of the label / heading for styling, or if you need a different heading depending on the page, archive or template the facets are on, you can use the facetwp_render_output hook to inject custom headings.

The following code example displays an alternative heading if the facets are on the ‘products’ post type archive page, using a conditional tag. It also adds a class to the <h3> and it adds a wrapper div around the facet to make styling easier.

Note that this code also influences the HTML output of the facets in the Mobile Flyout menu, which already have an <h3> heading. If you are using the Mobile Flyout add-on, to prevent double headings, you can remove the default ones with the second part of the code:

function my_custom_facet_headings( $output, $params ) {

  // array of all facets in use, with their name as key and custom headings to be used in the array
  $customheadings = array(
    'my_facet_name_1' => array( 'Heading 1', 'Heading 1 alt' ),
    'my_facet_name_2' => array( 'Heading 2', 'Heading 2 alt' ),
  );

  foreach ( $customheadings as $name => $label ) {
    if ( isset( $output['facets'][ $name ] ) ) {
      if ( is_post_type_archive( 'products' ) ) { // or any WP conditional tag
        $heading = $label[0]; // use first heading in the array
      } else {
        $heading = $label[1]; // use second (alt) heading in the array
      }
      $output['facets'][ $name ] = '
                <h3 class="myheadingclass">' . $heading . '</h3>
                <div class="facet">' . $output['facets'][ $name ] . '</div>';
    }
  }

  return $output;
}

add_filter( 'facetwp_render_output', 'my_custom_facet_headings', 10, 2 );


// Optional: remove the default headings in the Mobile Flyout menu:

add_action( 'wp_footer', function() {
  ?>
    <script>
      (function($) {
        $(function() {
          if ('object' != typeof FWP) return;
          FWP.hooks.addFilter('facetwp/flyout/facet_html', function(facet_html) {
            return facet_html.replace('<h3>{label}</h3>', ''); // set the heading output to an empty string
          });
        });
      })(jQuery);
    </script>
  <?php
}, 100 );

How to hide empty facets

Using the code below, you can hide facets that contain no values. Add this code to your (child) theme’s function.php (or use the Custom Hooks add-on). Or place the <script> part in your theme’s header.php or, better yet, into a custom javascript file.

For this code to work, each facet you want to hide when it is empty needs to have a container div. This example assumes a container div with class facet-wrap. If you have facets in separate WP text widgets, you can use widget as the class. Modify the class as needed (see the comments in the code below for more details).

Show ghosts setting offAlso make sure the targeted facets do not have the “Show ghosts” setting enabled (if you are using Checkboxes, Radio or fSelect facets).

add_action( 'wp_footer', function() {
  ?>
    <script>
      (function($) {
        document.addEventListener('facetwp-loaded', function() {
          $.each(FWP.settings.num_choices, function(key, val) {

            // assuming each facet is wrapped within a "facet-wrap" container element
            // this may need to change depending on your setup, for example:
            // change ".facet-wrap" to ".widget" if using WP text widgets

            var $facet = $('.facetwp-facet-' + key);
            var $wrap = $facet.closest('.facet-wrap');
            var $flyout = $facet.closest('.flyout-row');
            if ($wrap.length || $flyout.length) {
              var $which = $wrap.length ? $wrap : $flyout;
              (0 === val) ? $which.hide() : $which.show();
            }
          });
        });
      })(jQuery);
    </script>
  <?php
}, 100 );

See also