Search code examples
phpwordpresswoocommerceproductdiscount

Temporary global sale price discount for all products in WooCommerce


What I need:

We are planning to start a campaign. We want to give a temporary 10% discount on every product we sell on our site for the next 30 days. We want to display both the regular price and the discounted price on all shop's pages.

  • We have approximately 200,000 products.
  • Our products don't have variations.

Requirements:

  • All products should get 10% discount.
  • The discount should be visible and active for all visitors.
  • The discount should be applied automatically without any user actions.
  • Both the regular price and the discounted price should be visible to all visitors of the site.
  • It should be easy to remove the discount after 30 days.
  • The solution should not relay on any additional plugins, except WooCommerce. We are trying to keep our third-party plugin usage to minimum.
  • The modifications to the front-end should be minimal to none.

Environment:

  • Our shop is built on WooCommerce 8.1.
  • Using W3 Total Cache with Redis.
  • Hosted on dedicated server with Ubuntu Server 22.04. Running Apache 2.4 with PHP 8.1 and MySQL 8.

What have I tried and didn't work:

  • Using a plugin. All plugins I've tried have problems (or require too much manual clicking) handling 200,000 products.
  • Creating a coupon and applying it programmatically on Cart page. This actually did the discount part. However, it required some modifications to the theme to show the new discounted price to the users.

Question:

How to do this?


Solution

  • Updated (allowing products with zero price and resetting existing sale prices)

    Instead of overwriting products prices as you suggest in your comment, you could use the following to add a temporary global discount, that keeps the original product price with a general sale price with a 10% discount:

    // Below define the discount rate
    function discount_rate(){
        return 0.9; // 10% discount
    }
    
    add_filter('woocommerce_product_get_price', 'custom_price_discount', 20, 2);
    add_filter('woocommerce_product_variation_get_price', 'custom_price_discount', 20, 2);
    function custom_price_discount( $price, $product ) {
        if ( $price > 0 ) {
            return floatval($product->get_regular_price()) * discount_rate();
        }
        return $price;
    }
    
    add_filter('woocommerce_product_get_sale_price', 'custom_sale_price_discount', 20, 2);
    add_filter('woocommerce_product_variation_get_sale_price', 'custom_sale_price_discount', 20, 2); 
    function custom_sale_price_discount( $price, $product ) {
        return $product->get_price();
    }
      
    add_filter('woocommerce_product_is_on_sale', 'custom_product_is_on_sale', 20, 2);
    function custom_product_is_on_sale( $is_on_sale, $product ) {
        return $product->get_price() > 0 ? true : false;
    }
    
    function remove_zero_prices( $prices ) {
        foreach( $prices as $key => $price ) {
            if ( $price > 0 ) {
                continue;
            }
            unset($prices[$key]);
        }
        return $prices;
    }
    
    add_filter( 'woocommerce_get_price_html', 'custom_dynamic_sale_price_html', 20, 2 );
    function custom_dynamic_sale_price_html( $price_html, $product ) {
        if( $product->is_type('variable') ) {
            $prices     = $product->get_variation_prices( true );
            $reg_prices = remove_zero_prices( $prices['regular_price'] );
    
            if ( count($reg_prices) > 0 ) {
                return wc_format_sale_price( wc_price( end($reg_prices) ), wc_price( reset($reg_prices) * discount_rate() ) ) . $product->get_price_suffix();
            } 
        }
        return $price_html;
    }
    

    Code goes in functions.php file of your child theme (or in a plugin). Tested and works. It could work with your very large catalog.