Menu Close

WooCommerce: Search By Custom Field (Frontend)

default

The default WooCommerce frontend product search returns results based on whether the search term is present in the product title, short and long description. Also, you can optionally search products by SKU.

But what if you also want to search for a custom field value e.g. you have a custom field called “_brand” and you want to get the products where “_brand” is equal to “apple“?

Now, I’m not sure I’ve explained this in plain English, so let’s take a look at a practical example. Enjoy!

With the snippet below, and if I had “puma” saved in the “_brand” custom field for some products, this search result would actually return those products!

PHP Snippet: Search Products By Custom Field Value @ WooCommerce Search

The only thing you need to change in the snippet below is ‘_brand‘. Change it to the key of your custom field, and you should get results based on that. Let me know in the comments if it works!

/**
 * @snippet       Search By Custom Field @ WooCommerce Search
 * @how-to        Get CustomizeWoo.com FREE
 * @author        Rodolfo Melogli
 * @compatible    WooCommerce 7
 * @donate $9     https://businessbloomer.com/bloomer-armada/
 */

add_filter( 'posts_search', 'bbloomer_product_search_by_custom_field' );

function bbloomer_product_search_by_custom_field( $where ) {
    global $wpdb, $wp;
    if ( is_admin() || ! is_search() || ! isset( $wp->query_vars['s'] ) || 'product' != $wp->query_vars['post_type'] ) {
        return $where;
    }
    $product_ids = array();
    $terms = explode( ',', $wp->query_vars['s'] );
    foreach ( $terms as $term ) {		
		$products = $wpdb->get_results( $wpdb->prepare( "SELECT ID, post_parent FROM {$wpdb->posts} LEFT JOIN {$wpdb->postmeta} ON {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id WHERE meta_key IN ( '_brand' ) AND meta_value LIKE %s;", '%' . $wpdb->esc_like( wc_clean( $term ) ) . '%' ) );       
		$products = array_merge( wp_list_pluck( $products, 'ID' ), wp_list_pluck( $products, 'post_parent' ) );
        if ( sizeof( $products ) > 0 ) {
            $product_ids = array_merge( $product_ids, $products );
        }
    }
    $product_ids = array_filter( array_unique( array_map( 'absint', $product_ids ) ) );
	if ( sizeof( $product_ids ) > 0 ) {
        $where = str_replace( 'AND (((', "AND ( ({$wpdb->posts}.ID IN (" . implode( ',', $product_ids ) . ")) OR ((", $where );
    }	
    return $where;	
}
View Source
Posted in WooCommerce Tips