You can get lists of all simple products, variable products, or featured products easily with WooCommerce. It’s also easy to get things like “in-stock” products or “out of stock” products. However, getting a list of WooCommerce sale products can be a bit tougher because sale products use different meta keys to determine sale status depending on the product type.

Let’s take a look at a couple of ways you can get sale products.

Check sale status

First of all, this post will tell you how to get all sale products. If you’re only interested in checking for sale status with one product, there’s a very simple way to do that:

global $product;
if ( $product->is_on_sale() ) {
    do_something();
}

We’re talking about querying all sale products instead.

Display all sale products

First of all, many developers want to query sale products so they can display them in a custom template or archive page.

If you want to display all sale products in a “deals” page or something and you want to use the WooCommerce loop to display them, you can easily do so via the sale products shortcode. No complex queries or additional code necessary 🙂 :

[[sale_products columns="3" per_page="12"]]

This lets WooCommerce do the heavy lifting for you, so use this if you’re just looking to output an archive of sale products:

WooCommerce sale products

On Sale page

Querying WooCommerce sale products

You can use WP_Query to get your sale products, but how you do this matters. The default recommendation is typically to use the _sale_price meta to key to determine which products are on sale.

The issue with this is that variable products don’t use this key, so it would only return simple products. No problem, right? Let’s just add the meta key that variable products use as well: _min_variation_sale_price. We can then query both of these keys with an OR relationship to get products with either meta key.

$args = array(
    'post_type'      => 'product',
    'posts_per_page' => 8,
    'meta_query'     => array(
        'relation' => 'OR',
        array( // Simple products type
            'key'           => '_sale_price',
            'value'         => 0,
            'compare'       => '>',
            'type'          => 'numeric'
        ),
        array( // Variable products type
            'key'           => '_min_variation_sale_price',
            'value'         => 0,
            'compare'       => '>',
            'type'          => 'numeric'
        )
    )
);

$loop = new WP_Query( $args );

This totally works. You can now do whatever you’re trying to do with sale products that’s not simply outputting them onto the page. That doesn’t mean it’s the best way to get your sale products.

Let’s return to that shortcode we mentioned before to see how WooCommerce gets sale products.

Whoa, they’re doing something different. This uses the wc_get_product_ids_on_sale() function, which returns an array containing the IDs of the products that are on sale. This lets them use a simple query to get the sale products:

$query_args = array(
    'posts_per_page'    => 8,
    'no_found_rows'     => 1,
    'post_status'       => 'publish',
    'post_type'         => 'product',
    'meta_query'        => WC()->query->get_meta_query(),
    'post__in'          => array_merge( array( 0 ), wc_get_product_ids_on_sale() )
);
$products = new WP_Query( $query_args );

This is a more efficient way to query WooCommerce sale products.

So why is this better?

  • it’s easier for SQL to run the single post__in query compared to the more complicated query for meta keys
  • this method uses a separate query to get the product IDs on sale, and that can be parsed and optimized (related to next point)
  • querying for post__in when we already have the IDs is much, much faster because the wc_get_product_ids_on_sale function uses a transient, meaning this query is skipped if the transient exists

The moral of the story is that WooCommerce (and WordPress) optimize a lot for you, so before building your own query, take a look at how WooCommerce core handles this to see if there are similar use cases, or if there’s a function that can do part of the query for you.

Published by Max Rice

Max is one of our co-founders, CEO, resident webhook expert, and coffeescript lover. He's a top WooCommerce contributor, unit test aficionado, survivor of coding with timezones, and spends much of his time being the chief bottleneck at SkyVerge.

14 Comments

  1. Thank you very much for this article. it’s really help me to create my new woocommerce plugin.

  2. Hi,

    I am using the mystile theme and trying to have a category called “Sale Items” which automatically gets populated with all the items that are currently on sale.

    Is it possible to do this?

    Thanks

  3. Hi

    I used your Dynamic Pricing plugin to discount a whole category by 20%, the products show that they are on sale, but when I use the shortcode to display all my sale items, none of the products discounted through Dynamic Pricing show up.

    Is there a fix for this one at all? Cheers!

    • Hey Sean, I’m afraid we don’t have a Dynamic Pricing plugin, I’d recommend getting in touch with the author for support 🙂

  4. thanks a lot it’s a really working nice once.

  5. Thanks so much. Do you guys have say building a woocommerce theme from scratch course? I did the Treehouse one its good but not complete and not from scratch. Do you know where you can get a book or video training like this?

    Thanks

  6. Hello Max and Beka Rice: Thanks so much for the information you unselfishly shared in this article. I’m new to WC, learning it for the last 4 days. I’m interested in querying all products that have sales percentage > 70%. Could you give some pointers as how to go about doing that (what the $query_arg looks like, etc.) Thanks so much. Please keep up the great work:)

  7. How to create spesific promotion page for example weekend sale page, promo page with prizes etc

  8. Your article doesn’t really make clear that the function wc_get_product_ids_on_sale() does not return variation products on sale. So even though it might be a faster function, it’s also an incomplete one.

  9. Very useful, thanks!

  10. Very good article! I would like to ask how i can display all the on sale products of a SPECIFIC category on a sales page…

Comments are closed.

Error: Please enter a valid email address

Error: Invalid email

Error: Please enter your first name

Error: Please enter your last name

Error: Please enter a username

Error: Please enter a password

Error: Please confirm your password

Error: Password and password confirmation do not match