Menu Close

WooCommerce: Sort By Featured Products @ Shop

default

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        Get CustomizeWoo.com FREE
 * @author        Rodolfo Melogli
 * @compatible    WooCommerce 8
 * @donate $9     https://businessbloomer.com/bloomer-armada/
 */

// 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;
}
View Source
Posted in WooCommerce Tips