Search code examples
phpwordpresswoocommerceproduct

Replace on sale product price with saving amount and percentages in Woocommerce


I use some code that shows the discounted price on Woocommerce archive pages for on sale products:

add_filter( 'woocommerce_get_price_html', 'display_savings_as_price_and_percentage', 10, 2 );
//add_filter( 'woocommerce_variable_price_html','display_savings_as_price_and_percentage', 10, 2 );
function display_savings_as_price_and_percentage( $price, $product ) {

    if( $product->is_on_sale() && ! is_admin() && ! $product->is_type('variable')){
        $product_price = (float) $product->get_regular_price();
        $sale_price = (float) $product->get_price();
        $save_price = wc_price( $product_price - $sale_price );
        $save_percentage = round( 100 - ( $sale_price / $product_price * 100 ), 1 ) . '%';
        $price .= sprintf( __('<p class="saved-on-sale">Save: %s (%s)</p>', 'woocommerce' ), $save_price, $save_percentage );
    }
    return $price;
}

Discount on archives pages:

discount on archive

But it doesn't work for variable products and I've tried with every hook I've found but I cannot figure out how to make it work variable products. (I commented out the hook for the variable in my code).

This is what I would like to have:
If the variable has a price span of 10-20 with a discount making it 10-15 I would like for that to be displayed like this with the default price striked through:

  • $40 - $50
  • $20 - $30
  • Save: $20 (40-50%)

How can I replace the on sale product price for variable products with saving amount and percentages?


Solution

  • The following code will handle both simple and variable on sale products:

    add_filter( 'woocommerce_get_price_html', 'display_savings_price_and_percentages', 20, 2 );
    function display_savings_price_and_percentages( $price_html, $product ) {
        // Only on frontend and for on sale products
        if( is_admin() || ! $product->is_on_sale() )
            return $price_html;
    
        // Only on archives pages
        if( ! ( is_shop() || is_product_category() || is_product_tag() ) )
            return $price_html;
    
        // Variable product type
        if( $product->is_type('variable')){
            $percentages = $savings = array(); // Initializing
    
            // Get all variation prices
            $prices = $product->get_variation_prices();
    
            // Loop through variation prices
            foreach( $prices['price'] as $key => $price ){
                // Only on sale variations
                if( $prices['regular_price'][$key] !== $price ){
                    // Calculate and set in the array the percentage for each variation on sale
                    $percentages[] = round(100 - ($prices['sale_price'][$key] / $prices['regular_price'][$key] * 100), 1 );
                    // Calculate and set in the array the savings for each variation on sale
                    $savings[]     = $prices['regular_price'][$key] - $prices['sale_price'][$key];
                }
            }
    
            $save_price      = wc_price( max($savings) );
    
            if( min($percentages) !== max($percentages) ){
                $save_percentage = min($percentages) . '-' . max($percentages) . '%';
                $save_text       = __( 'Save up to:', 'woocommerce' );
            } else {
                $save_percentage = max($percentages) . '%';
                $save_text       = __( 'Save:', 'woocommerce' );
            }
        }
        // All other product types
        else {
            $regular_price   = $product->get_regular_price();
            $sale_price      = $product->get_sale_price();
            $save_price      = wc_price( $regular_price - $sale_price );
            $save_percentage = round( 100 - ( $sale_price / $regular_price * 100 ), 1 ) . '%';
            $save_text       = __( 'Save:', 'woocommerce' );
        }
    
        return '<p class="saved-on-sale">' . sprintf( '%s %s (%s)', $save_text, $save_price, $save_percentage ) . '</p>';
    }
    

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

    enter image description here