Overview

FacetWP Sort facet dropdown exampleThe Sort facet type adds a sort box for changing the listing order.

It might seem a bit counter-intuitive that Sort is a facet type, but just like any other facet type, a Sort facet can be added by making a new facet in the FacetWP admin interface.

Usage

Go to the Facets tab, click “add new”, choose “Sort” as Facet type, set its options, and place it on your page with a shortcode.

Available options

Name Description
Default label The dropdown label that the user sees by default (i.e. when no sort has been selected). Default: “Sort by”. Note: this label is translatable with the facetwp_i18n hook.
Sort options The UI for customizing the choices that appear in the sort dropdown. Each row corresponds with a sort choice, allowing you to set:

  • the label. Note: these labels are translatable with the facetwp_i18n hook.
  • the name (i.e. what gets added to the URL). Note: each sorting rule’s name needs to be unique.
  • the sort criteria. Each sort criteria row includes the field name and sort direction. Each sort option can contain multiple sort criteria. Be careful to choose a field that is unique and set for each post. If this is not the case, it can lead to duplicate posts. Adding a second, fallback sorting method can also prevent this.

Setting sort options

The following example shows the setup for a sort box containing the default label of “Sort results” and four sort options: Title (a-z), Title (z-a), Price (low to high), and Price (high to low).

Sort by distance
Example settings with four sort options.

You can change the order of the options by clicking the black “up” arrow on the right side of each sort option.

Using multiple sort criteria

Sort facet option with multiple sorting criteria
Sort by post date first, then by post title

Each sort option can have multiple sort criteria. Click the black “plus” icon next to a sort criteria row to add an extra row.

This can be useful to add a fallback sorting method, for example as a fix for duplicate posts in the listing.

The example on the right sorts by post date first, then by post title. If there are multiple posts in the results that share the same post date, they will be sorted next by their title.

Sort by distance

When a Proximity facet is in use as a filter (with a location entered), the post IDs are automatically re-sorted in the post__in argument of the query, from nearest to furthest. This makes it possible to sort results by distance.

To enable sort by distance, create a new sort option and set its data source to post__in with ASC or DESC order. If you make both a ASC and aDESC sort option, make sure each sort option has a unique technical name set.

Be aware that sorting by distance only works when a location has been entered in the Proximity facet.

If you want to sort the results by distance without a Sort facet setting it explicitly, use this custom code.

Custom field formatting

For numerical sorts like “Price”, the custom field should contain a raw integer or decimal value (with a dot). Fields containing dollar signs, commas, or other symbols won’t work.

For date sorts, the field should contain values in YYYY-MM-DD, YYYYMMDD or YYYY-MM-DD HH:MM:SS format. The default “Post Date” and “Post Modified” fields use this format already. But if you’re using a custom field in some other format, it likely won’t work.

Sorting WooCommerce product variations

If you are using FacetWP with WooCommerce product variations, be aware that sorting by product variation prices is currently not (yet) supported with the Sort facet. The logic of the Sort facet is based on WP_Query and therefore supports only basic custom fields-based sorting. Product variation prices are unfortunately more complex than that.

If you need sorting by product variation price, you could use WooCommerce’s built-in sort box, which works on the “normal” WooCommerce product archive. FacetWP fully supports WooCommerce product archive pages.

How to change the initial sort order

Before any interaction with the Sort facet, the order of the post listing is determined by the orderby and order parameters that are implicitly or explicitly set for the listing’s query. How you can change this sort order depends on the type of listing template you are using on your page.

Sorting a WP Archive

If you are using a WP Archive, you can modify any WP_Query parameter, including orderby and order, with the pre_get_posts filter.

See our tuturial on customizing WP archive queries for an example of how to do that.

Sorting a custom WP_Query

If you are using a custom WP query, you can modify any WP_Query parameter, including orderby and order, in the argument of the new WP_Query($args) function you are using to generate the query. See the WP_Query documentation for examples.

Sorting Elementor or Beaver Builder queries

If you are using Elementor with for example a Posts widget, you can set the orderby and order parameters in the “Query” tab of the widget’s settings.

Similarly, if you are using Beaver Builder with a Posts module, the query settings are available in its “Content” tab.

Sorting Listing Builder queries

Adding sort order criteria in the Listing Builder Query tab
Adding one or more sort order criteria in the Listing Builder’s “Query” tab.

If you are using FacetWP’s built-in Listing Builder, you can add sort criteria in the “Query” tab.

Simply click the “Add query sort” button and select the orderby and order sort criteria from the dropdowns.

You can even add multiple sort criteria by clicking the button again and adding an extra sort row. This can be useful to add a fallback sorting method. For example if you want to sort by post date and some posts share the same date. In this case you could sort by post date first, and by post title second.

Sorting Listing Builder queries in Dev mode

Adding orderby and order parameter in the Listing Builder Query tab in Dev mode
Adding orderby and order parameters in the Listing Builder’s “Query” tab in Dev mode.

If you are using the Listing Builder in “Dev mode”, you can adapt the orderby and order parameters manually with PHP, in the “Query” tab.

The easiest way is to start with “Dev mode” disabled, create your query, sorting and filter criteria with the settings, and then click the “Convert to query args” button. This converts your query settings to PHP and will switch the “Query” tab to “Dev mode”.

In the “Query Arguments” field you can then manually adapt the generated orderby and order parameters, and change or add any other query parameter available in WP_Query.

Display sort options as radio buttons

The Sort facet currently does not have a setting to display its options as radio buttons. With the following code this is possible.

For this solution to work, you first need to create a Sort facet and add it to your page.

Then we use the facetwp_facet_html hook to add radio elements looking similar to the Radio facet to the Sort facet’s HTML, and populate them with the sort values from the Sort facet’s dropdown. Add the following two pieces of code to your (child) theme’s functions.php:

// Replace 'my_sort_facet' with the name of your sort facet

add_filter( 'facetwp_facet_html', function( $output, $params ) {

  if ( 'my_sort_facet' == $params['facet']['name'] ) {
    $output .= '<div class="facetwp-sort-radio">';
    $output .= '<div class="facetwp-radio sort-radio" data-value="" data-type="sort">Any</div>'; // Optional "Any" option
    foreach ( $params['facet']['sort_options'] as $key => $atts ) {
      $output .= '<div class="facetwp-radio sort-radio" data-value="' . $atts['name'] . '" data-type="sort"> ' . $atts['label'] . '</div>';
    }
    $output .= '</div>';
  }

  return $output;
}, 10, 2 );

Note that the line creating the “Any” radio button is optional.

Next, when clicking one of the radio buttons we trigger the corresponding Sort facet option, and set the clicked radio button to be “checked”. Last but not least, we hide the original sort select element with a bit of CSS (which you can also place in your theme’s CSS file).

// Replace 'my_sort_facet' with the name of your sort facet

add_action( 'wp_footer', function() {
  ?>
    <script>
      (function($) {

        var sortfacet = 'my_sort_facet';

        $(document).on('click', '.sort-radio', function() {
          var val = $(this).attr('data-value');
          FWP.facets[sortfacet] = [val];
          FWP.toggleOverlay('on'); 
          FWP.fetchData();
          FWP.setHash();
        });

        $(document).on('facetwp-loaded', function() {
          if ('undefined' !== typeof FWP.facets[sortfacet]) {
            $('.sort-radio').filter('[data-value="' + FWP.facets[sortfacet] + '"]').addClass("checked");
          }
        });

      })(jQuery);
    </script>

    <style>
        /* Replace 'my_sort_facet' with the name of your sort facet */
        .facetwp-facet-my_sort_facet select {
            display: none;
        }
    </style>
  <?php
}, 100 );

Display a Sort facet as an fSelect dropdown

Display a Sort facet as fSelect dropdown
Display a Sort facet as fSelect dropdown

The Sort facet displays as a default HTML <select> dropdown element, which can be difficult to style.

With the following code, it is possible to force the Sort dropdown to display as an fSelect type dropdown. This will replace the <select> with better stylable nested divs.

The code sets the showSearch option to false preventing the fSelect from showing its default search box (which does not make much sense in a Sort dropdown).

Add the code to your (child) theme’s functions.php:

add_action( 'wp_footer', function() {
  ?>
    <link href="/wp-content/plugins/facetwp/assets/vendor/fSelect/fSelect.css" rel="stylesheet" type="text/css">
    <script src="/wp-content/plugins/facetwp/assets/vendor/fSelect/fSelect.js"></script>
    <script>
      document.addEventListener('facetwp-loaded', function() {
        fUtil('.facetwp-type-sort select').fSelect({showSearch: false});
      });
    </script>
  <?php
}, 100 );

Note: If you already have an actual fSelect facet on the page, you don’t need to include the links to the fSelect CSS and JavaScript files.

Fix duplicate results when using a Sort facet

If you are seeing duplicate posts in your listing while using a Sort facet (or only while selecting specific sorting methods), the cause is almost always the chosen field to order by.

If results are ordered by a value that is the same (or empty) for multiple posts, or by a random value, MySQL does not have a fallback and will often sort erratically. For example, ordering by menu_order can be problematic, because it defaults to 0 if it is not explicitly set for each post.

This issue can be easily fixed by adding a secondary, fallback sort order. Preferably use a field that is unique, like ID. But title, or date (if that is not the problematic field) can work too.

In this tutorial you can read more about which scenarios can cause this to happen, and how to fix it quickly in all possible situations.

See also