Search code examples
phpwordpresswoocommerceproduct

Display product sale percentage in WooCommerce product archives pages


I want to display the sale percentage under the product title. This is my function in the functions.php page, however I am getting NAN% Off

    // Function to calculate and display sale percentage.
function display_sale_percentage() {
    global $product;

    if ( $product->is_on_sale() ) {
        // Get regular and sale prices
        $regular_price = $product->get_regular_price();
        $sale_price = $product->get_sale_price();

        // Calculate discount percentage
        $discount_percentage = round( ( ($regular_price - $sale_price) / $regular_price ) * 100 );

        // Display the percentage
        echo '<span class="sale-percentage">' . $discount_percentage . '% off</span>';
    }
}

// Hook the function to a suitable location in your product archive template.
// For example, you can hook it into the product loop.
add_action( 'woocommerce_before_shop_loop_item_title', 'display_sale_percentage', 25 );

Solution

  • Your code needs to handle variable products and its variations prices.

    For variable products, the following code will display

    • a discount percentage range, if there are at least 2 on sale variations with different discount percentages,
    • a unique discount percentage, if there is one on sale variation discount percentage

    For on sale simple products, the discount percentage will be displayed.

    // Utility function: Get an array of discount percentages from the variations
    function get_variations_discount_percentage( $product ) {
        $prices = $product->get_variation_prices( true );
        $percentages = array();
    
        foreach( $prices['regular_price']  as $key_id => $price ) {
            if( $price != $prices['price'][$key_id] ) {
                $reg_price  = floatval($price);
                $sale_price = floatval($prices['price'][$key_id]);
                $percentages[] = round( ($reg_price - $sale_price) / $reg_price * 100);
            }
        }
        return array_unique($percentages);
    }
    
    // Displays On Sale product discount percentage
    add_action( 'woocommerce_before_shop_loop_item_title', 'display_products_on_sale_percentage', 25 );
    function display_products_on_sale_percentage() {
        global $product;
    
        if ( ! $product->is_on_sale() ) return; // Only "On sale" products
    
        if ( $product->is_type('variable') ) {
            $percentages = get_variations_discount_percentage( $product );
    
            if ( count($percentages) > 1 ) {
                // Display the discount percentages range
                printf( '<span class="sale-percentage">From %d%% to %d%% off</span>', min($percentages), max($percentages) );
            } elseif ( count($percentages) === 1 ) {
                // Display the discount percentage
                printf( '<span class="sale-percentage">%d%% off</span>', current($percentages) );
            }
        } else {
            $reg_price  = (float) $product->get_regular_price();
            $sale_price = (float) $product->get_sale_price();
    
            // Display the discount percentage
            printf( '<span class="sale-percentage">%d%% off</span>',
                round( ($reg_price - $sale_price) / $reg_price * 100) );
        }
    }
    

    Code goes in functions.php file of your child theme (or in a plugin). Tested and works.