Overview

FacetWP Sort facet dropdown example.

The 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.

Sort by custom numerical or date fields

For some custom fields, the field formatting is important to get them to work:

Sort by custom numerical fields

For numerical sorting options like “Price”, the custom field should contain a raw integer or a decimal value (with a dot for decimals). Fields containing dollar signs, commas, or other symbols will not work.

Also make sure to choose “NUMERIC” as the field type, not “TEXT”:

Use NUMERIC as the field type for sorting by a custom numerical field.
Use NUMERIC as the field type for sorting by a custom numerical field.

Sort by custom date fields

For date sorting options, the custom field should contain values in YYYY-MM-DD, YYYYMMDD or YYYY-MM-DD HH:MM:SS format. If your custom field uses any other format, the sort will not work. Note that the built-in “Post Date” and “Post Modified” fields already use this format.

Also make sure to choose “TEXT” as the field type, not “NUMERIC”:

Use TEXT as the field type for sorting by a custom date field.
Use TEXT as the field type for sorting by a custom date field.

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:

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

// 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">' . facetwp_i18n('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">' . facetwp_i18n($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).

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

// 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:

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() { ?> <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.

Fix sorting issues with apostrophes, quotes or other special characters in post titles

Fix sorting issues with special characters in post titles by sorting by Post Name instead of by Post Title.
Fix sorting issues with special characters in post titles by sorting by “Post Name” instead of by Post Title.

If you have a sort option that sorts by “Post Title”, and your post titles contain or even start with (double) quotes, apostrophes, or other special characters, the posts will be sorted with those characters included. This means that posts starting with a quote will always appear on top when you sort by post title, which is not ideal.

To prevent this, set your Sort facet option to sort by “Post Name” instead. The post name is the post’s slug, which will have all special characters already removed because it’s part of the post’s permalink/URL.

This will work well as long as your post slugs are close to the post titles, which normally will be the case, unless you manually adapt the slugs.

Fix a non-working Sort facet on WooCommerce product pages

The only two WooCommerce's 'Default product sorting' options that work with Sort facets.
The only two WooCommerce’s “Default product sorting” options that work with Sort facets.

If you are using WooCommerce, and your Sort facet does not work on your products/shop page, you probably have set WooCommerce’s “Default product sorting” setting to a sort option that is incompatible with Sort facets.

There are only two “Default product sorting” options that work with Sort facets:

  1. Default sorting (custom ordering + name)
  2. Sort by most recent

The other sort options are incompatible because FacetWP cannot change them.

For more info and ways to still use one of the incompatible sort options, see this section on the WooCommerce page.

Pre-select a Sort facet option

Sort facet options: sorting by Post Title ASC and DESC.
Sort facet options: sorting by Post Title ASC and DESC.

If your post listing query has a specific order set with the “order” and “orderby” query arguments, you may want to let your Sort facet reflect that same order on page load.

For example, if your query has the orderby argument set to ["title" => "ASC"], and your Sort facet has that same order set in a sort option called title_a_z, like in the image on the right, you can pre-select that option on page load with the “facetwp_preload_url_vars” hook.

See also