WooCommerce: Sort By Featured Products @ Shop

The “Default sorting” dropdown sorts products by menu_order and then title on the WooCommerce Shop, Category and Tag pages.

But what if you want to place the featured products first in the list (I mean, why would anyone set products as featured if you can’t really “promote” them on the Shop page)?

In today’s case study, we will replace the “Default sorting” option with a workaround, create a new one with the same label (so that customers won’t notice it), set it as the default sorting option, and make sure it sorts by featured products first, and then by menu_order and title. Enjoy!

These two products are marked as “featured”. What I want is for these 2 to show on top of the WooCommerce Shop page.
And this is the result once the snippet below is active: the two featured products now show on top of the WooCommerce Shop page, before all the others!

PHP Snippet: Featured Products First on the WooCommerce Shop / Cat / Tag Pages

/**
 * @snippet       Move Featured Products To Top @ Woo Shop Page
 * @how-to        businessbloomer.com/woocommerce-customization
 * @author        Rodolfo Melogli, Business Bloomer
 * @compatible    WooCommerce 8
 * @community     https://businessbloomer.com/club/
 */

// Replace "default sorting" option with a custom one

add_filter( 'woocommerce_catalog_orderby', 'bbloomer_woocommerce_catalog_orderby_custom' );

function bbloomer_woocommerce_catalog_orderby_custom( $sortby ) {
    $sortby['featured'] = __( 'Default sorting', 'woocommerce' );
	unset( $sortby['menu_order'] );
    return $sortby;
}

// Make the custom one the default one

add_filter( 'woocommerce_default_catalog_orderby', 'bbloomer_woocommerce_catalog_orderby_custom_default' );

function bbloomer_woocommerce_catalog_orderby_custom_default() {
	return 'featured';
}

// Set sorting for new option

add_filter( 'woocommerce_get_catalog_ordering_args', 'bbloomer_woocommerce_catalog_orderby_custom_args' );

function bbloomer_woocommerce_catalog_orderby_custom_args( $args ) {
	$orderby_value = isset( $_GET['orderby'] ) ? wc_clean( $_GET['orderby'] ) : apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) );
	if ( 'featured' == $orderby_value ) {
		$args['orderby'] = 'menu_order title';
		$args['order'] = '';
		$args['meta_key'] = '';
	}
	return $args;
}

// Adjust order to allow for featured posts

add_filter( 'posts_orderby', 'bbloomer_woocommerce_catalog_orderby_custom_featured_first', 10, 2 );

function bbloomer_woocommerce_catalog_orderby_custom_featured_first( $order_by, $query ) {
	global $wpdb;
	if ( ! is_admin() ) {
		$orderby_value = ( isset( $_GET['orderby'] ) ? wc_clean( (string) $_GET['orderby'] ) : apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) ) );
		$orderby_value_array = explode( '-', $orderby_value );
		$orderby = esc_attr( $orderby_value_array[0] );
		$order = ( ! empty( $orderby_value_array[1] ) ? $orderby_value_array[1] : 'ASC' );
		$featured_product_ids = wc_get_featured_product_ids();
		if ( $orderby == "featured" && is_array( $featured_product_ids ) && ! empty( $featured_product_ids ) ) {
			if ( empty( $order_by ) ) {
				$order_by = "FIELD(" . $wpdb->posts . ".ID,'" . implode( "','", $featured_product_ids ) . "') DESC ";
			} else {
				$order_by = "FIELD(" . $wpdb->posts . ".ID,'" . implode( "','", $featured_product_ids ) . "') DESC, " . $order_by;
			}
		}  
	}
	return $order_by;
}

Where to add custom code?

You should place custom PHP in functions.php and custom CSS in style.css of your child theme: where to place WooCommerce customization?

This code still works, unless you report otherwise. To exclude conflicts, temporarily switch to the Storefront theme, disable all plugins except WooCommerce, and test the snippet again: WooCommerce troubleshooting 101

Related content

Rodolfo Melogli

Business Bloomer Founder

Author, WooCommerce expert and WordCamp speaker, Rodolfo has worked as an independent WooCommerce freelancer since 2011. His goal is to help entrepreneurs and developers overcome their WooCommerce nightmares. Rodolfo loves travelling, chasing tennis & soccer balls and, of course, wood fired oven pizza. Follow @rmelogli

4 thoughts on “WooCommerce: Sort By Featured Products @ Shop

  1. Hi,

    I was looking for exactly this and it works to put featured products first on a category page but it is adding the option of default ordering on the dropdown which is unfortunate because I have mine set to popularity. This means apart from those marked as featured you don’t see the most popular products after the featured, its just a random order.

    1. Hello Ian, thanks so much for your comment! Yes, this is definitely possible, but I’m afraid it’s custom work. If you’d like to get a quote, feel free to contact me here. Thanks a lot for your understanding!

      1. Rodolfo you are a star! Best and most comprehensive code solution I was able to find for putting featured products on top in the category listing pages. As a related question, possible to apply further sorting of products by custom ordering (Edit product > Product data > Advanced > Menu order, I assume this should change products’ order in the category listing pages)? Asking, because sometimes we have 10+ featured products and would be great if those could be further sorted.

        1. Tomas, thanks so much for your comment! Yes, this is definitely possible, but I’m afraid it’s custom work. If you’d like to get a quote, feel free to contact me here. Thanks a lot for your understanding!

Questions? Feedback? Customization? Leave your comment now!
_____

If you are writing code, please wrap it like so: [php]code_here[/php]. Failure to complying with this, as well as going off topic or not using the English language will result in comment disapproval. You should expect a reply in about 2 weeks - this is a popular blog but I need to get paid work done first. Please consider joining the Business Bloomer Club to get quick WooCommerce support. Thank you!

Your email address will not be published. Required fields are marked *