Adding "Sale" product category to products that are on sale in Woocommerce
Asked Answered
L

2

9

As part of a WooCommerce site I want to have a sale page that lists sale items (with pagination and filtering). I think the best way to do this is to have a 'Sale' category that is added automatically to any posts that are part of the sale (as category pages allow for filtering and pagination automatically.

I have this code so far to programatically add the sale category to products when you save them:

function update_test( $product) { 
wp_set_object_terms($product, 'sale', 'product_cat', true );
}

add_action( 'save_post', 'update_test', 1, 2);`

However, I only want this to happen if a product is on sale (i.e has sale price set) so that saving posts that are not on sale does not add the sale category. I have tried several different things, but have had no luck. I tried this, but it didnt work:

function update_test( $product ) { 
if($product->is_on_sale()){
wp_set_object_terms($product, 'sale', 'product_cat', true );
}
}

add_action( 'save_post', 'update_test', 1, 2);`

but this just made my site freeze on save.

Any ideas?

Andy

Laid answered 5/12, 2016 at 0:42 Comment(1)
There is a plugin that creates an On Sale page for all your sale products, which has pagination: wordpress.org/plugins/on-sale-page-for-woocommercePortuna
E
7

Updated 2 (October 2018)

save_post is a WordPress hook that works with $post_id argument and target all kind of posts. You need to target product custom WooCommerce post_type first in a condition (and publish post_status).

Also as it's not a post object you can't use is_on_sale() method with it. But you can use get_post_meta() function to check if the sale price is set in the product.

Here is the fully functional and tested code (for simple products only):

add_action( 'save_post_product', 'update_product_set_sale_cat' );
function update_product_set_sale_cat( $post_id ) {
    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
        return $post_id;
    }

    if ( ! current_user_can( 'edit_product', $post_id ) ) {
        return $post_id;
    }

    if( get_post_status( $post_id ) == 'publish' && isset($_POST['_sale_price']) ) {
        $sale_price = $_POST['_sale_price'];

        if( $sale_price >= 0 && ! has_term( 'Sale', 'product_cat', $post_id ) ){
            wp_set_object_terms($post_id, 'sale', 'product_cat', true );
        }
    }
}

Code goes in function.php file of your active child theme (or active theme). Tested and works.

Related: Auto remove Sale product category from not on sale products in Woocommerce

Embower answered 5/12, 2016 at 1:54 Comment(5)
Thanks for the quick response. I have tried this code in my function file and on save it gives me the following error message: "Call to undefined method WP_Post::is_on_sale()" I have tried a few things and got this error back, not sure how to solve it. AndyLaid
Thanks! This is working well for simple products. Will have to have a think about how to make it work for variable products now. Man, woocommerce don't like to make anything easy.Laid
Do you mean Woo Commerce is changing so that it works for variations? Or that you have maybe found a way to make it work for variable products? Either way, thanks so much for the help so far! I have been banging my head against a wall all of yesterday trying to sort this.Laid
@Laid this hook works only for simple products, as variations are updated via ajax (so the hook is not going to be fired and doesn't detect anything)… ALSO the product categories can be set for the variable product but NOT for a particular variation of this variable product… Sorry about that :( … I will try to find something for that (on my little free time) but it's going to be much more difficult…Embower
No problem! Thanks for the help up to here. I suspected that it would be impossibly hard for the variable products. Might have to keep with manually adding and removing the sale category for now. Will update this if I ever do find a solution for both though! Cheers!Laid
B
1

I think a more convenient way of doing this, that also works on variable products, would be adding the following in child theme's function.php (or via a plugin, etc):

add_action( 'woocommerce_update_product', 'update_product_set_sale_cat', 10, 2 );

function update_product_set_sale_cat( $product_id, $product ) {
    if ( $product->is_on_sale() ) {
        wp_add_object_terms($product_id, "sale", 'product_cat');
    } else { // this will also remove the sale category when the product in no longer on sale
        wp_remove_object_terms($product_id, "sale", 'product_cat');
    }
}

It uses the woocommerce_update_product hook which runs whenever a product is updated/created in the database.

Bournemouth answered 7/2, 2022 at 17:12 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.