In the previous post, I’ve shown you how to filter WordPress posts and custom post types by a meta field value using WP REST API. Some of you might think that this method can be used for the WooCommerce custom post types too (products, orders, etc.). Although they are the custom post types too, WooCommerce uses its own REST API endpoints. You can learn more about the WooCommerce REST API in the official documentation.
Earlier, we used the rest_{$this->post_type}_query filter hook to pass our custom arguments to a posts query based on the provided query parameters. This hook doesn’t work with the WooCommerce custom post types, but, luckily, we can still filter products or orders by a meta field using a similar filter hook.
How to filter WooCommerce products by a meta field?
We’ll start with the most important post type in WooCommerce. Let’s imagine that our products have a custom meta field — Brand. And we want to get all products belonging to a certain brand using WooCommerce REST API. How can we do this?
For example, I want to get all products with the Brand meta field equal to Nike. How can I achieve this using WooCommerce REST API?
As I said earlier, the rest_{$this->post_type}_query filter hook doesn’t get triggered when you use the WooCommerce REST API endpoints. Luckily, the WooCommerce developers have added a very similar filter hook —woocommerce_rest_{$this->post_type}_object_query.
As you might have guessed, all you need to do is to change {$this->post_type} to the post type’s slug you need. Since we want to filter WooCommerce products, we’ll need to use the woocommerce_rest_product_object_query filter hook. This hook passes two arguments to its handlers: $args and $request. We can modify the WP_Query arguments using the first argument, and we can access the request parameters using the last one.
I guess you got the idea. Especially, if you’ve already experimented with my previous tutorial. Let’s write some code:
add_filter( 'woocommerce_rest_product_object_query', 'filter_products_by_brand_field', 999, 2 );
function filter_products_by_brand_field( $args, $request ) {
if ( ! isset( $request['brand'] ) ) {
return $args;
}
$source_value = sanitize_text_field( $request['brand'] );
$source_meta_query = array(
'key' => 'brand',
'value' => $source_value
);
if ( isset( $args['meta_query'] ) ) {
$args['meta_query']['relation'] = 'AND';
$args['meta_query'][] = $source_meta_query;
} else {
$args['meta_query'] = array();
$args['meta_query'][] = $source_meta_query;
}
return $args;
}
Now, a GET request to the following URL: https://mywebshop.com/wp-json/wc/v3/products?brand=Nike, will return an array of products which brand meta field equals to “Nike”. If there are no products matching this requirement, WooCommerce REST API will return an empty array.
How to use this filter hook with other WooCommerce post types?
The best part of this hook is that you can use the same logic for all WooCommerce post types. As I said, all you need to do is to pass the slug of the post type you want to filter instead of the {$this->post_type}. For example:
- Use woocommerce_rest_shop_order_object_query hook to filter WooCommerce orders
- Use woocommerce_rest_shop_coupon_object_query hook to filter WooCommerce coupons
- Use woocommerce_rest_product_variation_object_query hook to filter WooCommerce variations
You can learn more about the WooCommerce custom post types in the WooCommerce documentation. In all cases, your hook handlers will receive two arguments: $args (an array of the WP_Query arguments defined before) and $request (a WP_REST_Request instance which allows you to access a request’s parameters).
Summary
As you see, this method almost completely repeats the one we used to filter regular WordPress post types. There is no surprise, though, given that WooCommerce belongs to Automattic — the company behind WordPress.
Anyways, I hope this post you found this post helpful for you and your project. If you have any other questions about WooCommerce REST API or want me to describe a topic you’re interested in — let me know about this in the comments section below.
Thank you for reading this post; see you in the next one!
Thank you so much for this great tutorial!
I can’t get it to work with variable products, even with the “woocommerce_rest_product_variation_object_query”
I’m using it to search for barcodes, which is attached to both simple products, and also to each variant of a product.
The code works for simple products but variants just returns an empty array?
Hope you can help 🙏
Hi Jonas! Probably, it’s because /wp-json/wc/v3/products endpoint does not return variations. To get and filter product variations, you need to use /wp-json/wc/v3/products/{product_id}/variations endpoint.
Hi Kayart
Thank you so much for the answer!
The problem is that I need to search a barcode number and return the product that contains the barcode on the main product or variant.
If I use your suggestion, then I have to pass a product ID 🥺
Any good suggestions?
Are products’ barcodes stored as meta fields?
Yes
Using this plugin: https://github.com/kreamweb/Product-GTIN-EAN-UPC-ISBN-for-WooCommerce
Meta field key “_wpm_gtin_code”
It also adds this parameter to the product – maybe that could be an easier way?
* New: Added ‘ean_code’ in WooCommerce Rest product data
I think that the easiest way for you is to create a special REST API endpoint that will filter both product and product_variation post type by their _wpm_gtin_code meta field value
Thank you very much for your suggestions 😊
You’re welcome! You can buy me a coffee if you want to thank me for my work 😅
Hi how can we filter using like compare?
You can use any comparison operators that the WP_Meta_Query class supports. Here’s a brief description of the available options:
https://andriy.space/wordpress-meta-query/#meta-query-comparison-operators
I’m currently trying this to filter the orders by billing_phone but it doesn’t return anything.
I’ve also tried the key as _billing_phone
Hi Anthony! I wrote an answer to a similar question on StackOverflow.
Besides, are you sure that you’re forming your API request correctly?