WooCommerce: Display % Discount @ Shop Page

Default WooCommerce shows a “Sale” badge if the item is on sale – but what about showing the exact sale percentage instead?

I implemented this for one of my freelance clients so here you go with the easy-peasy solution. Enjoy!

Show discount percentage instead of the default “SALE!” on the WooCommerce product loop

PHP Snippet: Display Discount Percentage @ WooCommerce Shop / Category / Product Archive Pages

/**
 * @snippet       Display Discount Percentage @ Loop Pages - WooCommerce
 * @how-to        Get CustomizeWoo.com FREE
 * @author        Rodolfo Melogli
 * @compatible    WooCommerce 6
 * @community     https://businessbloomer.com/club/
 */ 

add_action( 'woocommerce_before_shop_loop_item_title', 'bbloomer_show_sale_percentage_loop', 25 );

function bbloomer_show_sale_percentage_loop() {
	global $product;
	if ( ! $product->is_on_sale() ) return;
	if ( $product->is_type( 'simple' ) ) {
		$max_percentage = ( ( $product->get_regular_price() - $product->get_sale_price() ) / $product->get_regular_price() ) * 100;
	} elseif ( $product->is_type( 'variable' ) ) {
		$max_percentage = 0;
		foreach ( $product->get_children() as $child_id ) {
			$variation = wc_get_product( $child_id );
			$price = $variation->get_regular_price();
			$sale = $variation->get_sale_price();
			if ( $price != 0 && ! empty( $sale ) ) $percentage = ( $price - $sale ) / $price * 100;
			if ( $percentage > $max_percentage ) {
				$max_percentage = $percentage;
			}
		}
	}
	if ( $max_percentage > 0 ) echo "<div class='sale-perc'>-" . round( $max_percentage ) . "%</div>";
}

[/php]

And a bit of CSS:

.sale-perc {
   background-color: #D9534F;
   display: inline;
   padding: .2em .6em .3em;
   font-size: 75%;
   font-weight: bold;
   color: #fff;
   text-align: center;
   border-radius: .25em;
}

“I don’t code – is there a reliable plugin for that?”

As many readers would love to code but don’t feel 100% confident with it, I decided to look for a reliable plugin that achieves the same (or even better) result.

In this case, I recommend the YITH WooCommerce Badge Management plugin. On top of displaying custom text badges (free version), you can also create CSS, image and advanced badges, assign product badges to specific products and/or categories, pick the badge position and much more.

But in case you wish to code, keep reading ๐Ÿ™‚

Where to add custom code?

You should place custom PHP in functions.php and custom CSS in style.css of your child theme: where to place WooCommerce customization?

This code still works, unless you report otherwise. To exclude conflicts, temporarily switch to the Storefront theme, disable all plugins except WooCommerce, and test the snippet again: WooCommerce troubleshooting 101

Related content

  • WooCommerce: Disable Variable Product Price Range $$$-$$$
    You may want to disable the WooCommerce variable product price range which usually looks like $100-$999 when variations have different prices (min $100 and max $999 in this case). With this snippet you will be able to hide the highest price, and add a “From: ” prefix in front of the minimum price. At the […]
  • WooCommerce: Hide Price & Add to Cart for Logged Out Users
    You may want to force users to login in order to see prices and add products to cart. That means you must hide add to cart buttons and prices on the Shop and Single Product pages when a user is logged out. All you need is pasting the following code in your functions.php (please note: […]
  • WooCommerce: Hide Prices on the Shop & Category Pages
    Interesting WooCommerce customization here. A client of mine asked me to hide/remove prices from the shop page and category pages as she wanted to drive more customers to the single product pages (i.e. increasing the click-through rate). As usual, a simple PHP snippet does the trick. I never recommend to use CSS to “hide” prices, […]
  • WooCommerce: How to Remove the “Default Sorting” Dropdown
    If the WooCommerce product sorting functionality (“Default Sorting” dropdown) is a waste of space or you don’t need that select box at all, you may want to remove it. No matter if you prefer custom code or a simple plugin – hiding the product sorting dropdown is a piece of cake. Enjoy!
  • WooCommerce: Add Prefix / Suffix to Product Prices
    Sometimes you may want to add a prefix or a suffix to your prices. It could be something like “From…”, “Only…”, “…tax free” and so on. The first good news is this is very easy to do with a WooCommerce filter (remember, filters change the value of an existing variable, while actions add content). The […]

Rodolfo Melogli

Business Bloomer Founder

Author, WooCommerce expert and WordCamp speaker, Rodolfo has worked as an independent WooCommerce freelancer since 2011. His goal is to help entrepreneurs and developers overcome their WooCommerce nightmares. Rodolfo loves travelling, chasing tennis & soccer balls and, of course, wood fired oven pizza. Follow @rmelogli

65 thoughts on “WooCommerce: Display % Discount @ Shop Page

  1. How i can show Display Discount price not in percentage please help

    1. Don’t divide the difference and don’t multiply the result by 100 – in this way you will get the amount

  2. Hello, how could I put the total value of the discount instead of the percentage, thanks.

    1. Just change the formula to “regular – sale”

  3. Thank you so much for this. I am using Advanced Dynamic Pricing for WooCommerce to apply discount on multiple products together rather than reducing the price individually. Is it possible to show the badge on the products discounted via Advanced Dynamic Pricing for WooCommerce plugin?

    1. Hi Junaid, thanks so much for your comment! Yes, this is definitely possible, but I’m afraid it’s custom work. If you’d like to get a quote, feel free to contact me here. Thanks a lot for your understanding!

  4. Another Solution from you guys God bless you!

    1. Thanks for the “guys” but it’s only me lol

  5. Sir, Where i have to put this code , ?
    which you have provided code in this post “

    1. Please read the whole post

  6. You are Awesome brother this is help me a lot ..
    thank you for sharing knowledge with us ..
    not this post your all post help me a lot for woocommerce customisation.

    1. Cheers brother

  7. Hi! First of all: I love all your snippets.
    That being said, with the gutenberg blocks we have now the chance to put woocommerce “Featured Product Block”, any chance anyone knows where to hook this action to make it work also on them?

    1. Hi Dan, thanks so much for your comment! Yes, this is definitely possible, but I’m afraid it’s custom work. If you’d like to get a quote, feel free to contact me here. Thanks a lot for your understanding!

  8. Hi,
    Is there any way I can display the discounts percentage off in same line as the price.

    1. Sure, you need CSS for that

  9. I did everything that I could, but I can’t get the results. I am using woo 4.1, where is the problem. Is it in snippet or compatibility with my WooCommerce version of some I don’t know how to copy and past?

    1. Could be anything… what theme are you on? Also, disable all plugins but WooCommerce

  10. If you have a large website with lots of product variants, this code seriously slows down performance of the website and consumes a lot of RAM. This is because the code is loading every child variant into RAM when it only needs access to the sale price and regular price.

    There is another function you can call on the parent product called get_variation_prices which grabs all the prices into an array – far quicker to parse through.

    To get this speed boost, change the foreach loop to this:

          $prices = $product->get_variation_prices( true ); // this is the fastest way to get the prices for all variants - returns multidimensional array from object cache
          foreach($prices['regular_price'] as $pid => $regular_price) {
            if ($regular_price == 0) continue; // if regular price is 0, skip this product
            if ($regular_price == $prices['sale_price'][$pid]) continue; // if sale price = regular price, skip this product
            $percentage = ( $regular_price - $prices['sale_price'][$pid] ) / $regular_price * 100;
            if ( $percentage > $max_percentage ) {
                $max_percentage = $percentage;
            }
          }
    

    I’ve outlined how I figured this out and the improvement here: https://www.wpintense.com/2020/04/29/figuring-out-slow-php-performance-caused-by-loops-using-xdebug/

    I improved speed from 15 seconds page-generation to 1 second. Your mileage will vary depending on how many product variations you have.

    1. Well done!

  11. hello Rodolfo, first of all thank you very much for your all snippets, It is very kind that you are sharing all this useful things! I use divi theme and it works perfect with the shop page.

    In a product when i use one module that shows related products the percentage works also works correct but it is not get centered and it is align on the left and this is kind of ugly…How can i solve this?

    In the shop page works 100% percent correct but in the product page i have this issue.

    Thanks i advance…greetings from Greece!

    1. Hi Stelios! You just need custom CSS

  12. Here is my contribution modifying your code..

    If you want to automatically display a product label on the archive page for products that are marked as “featured”, here is the code.

    add_action( 'woocommerce_before_shop_loop_item_title', 'mostrar_etiqueta_producto_destacado_novedad' );
    	function mostrar_etiqueta_producto_destacado_novedad(){
           global $product;
                  if ( ! $product->is_featured() ) return;
                     echo "<span class='destacado-novedad'>ยกNovedad!</span>"; 
        }

    1) You must replace “woocommerce_before_shop_loop_item_title” with the hook where you want it to be displayed in your case.
    2) You must replace “destacado-novedad” with the css class you want to give the label, and then give it styles with a little css.
    3) You must replace the text “ยกNovedad!” for the text you want displayed on the label.
    4) Give css styles to the span class to make the label look pretty. In my case, they are the following styles:

    span.destacado-novedad {
        color: #fff;
        padding: 1px 10px;
        background-color:#dd6868;
    }
    
  13. How can i show on single product page too?

    1. Mohammad, thanks so much for your comment! Yes, this is definitely possible, but I’m afraid it’s custom work. If you’d like to get a quote, feel free to contact me here. Thanks a lot for your understanding!

  14. Thanks for the code snippet! It works in my shop but the CSS is not working. Plus can you tell me how to show the discount below the price with some text? Just like this https://prnt.sc/r2ehol

    1. Hi Purkait, thanks so much for your comment! Yes, this is definitely possible, but I’m afraid it’s custom work. If you’d like to get a quote, feel free to contact me here. Thanks a lot for your understanding!

      1. Purkait, To do what you indicate in the photo, you just have to change the hook “woocommerce_before_shop_loop_item_title” by the hook indicated for the position you want, usually it is usually “woocommerce_after_shop_loop_item”.

        As for adding text before the discount percentage, you must replace the line:

        if ( $max_percentage > 0 ) echo "<div class='sale-perc'>-" . round($max_percentage) . "%</div>"; 

        por esta otra:

        if ( $max_percentage > 0 ) echo "<div class='sale-perc'>You save -" . round($max_percentage) . "%</div>"; 
  15. Hello
    If you are using a plugin to make discounts and the snippet doesnt work just replace get_sale_price() with get_price();
    $sale = $variation->get_price();
    get_sale_price() will get you the price from sale price field from each variation (in my case it was empty because i use some discount plugin for that)
    get_price will get you the active price of the product

    1. Nice!

    2. Worked perfectly, thank you so much!

  16. I was looking for this solution to show a percentage discount. They work great. Thanks man!

    1. Great!

  17. Amazing and just what i was looking for, thankyou

    Just one quick question, how do i add the words “off” after the discount amount so it would read 10% off for example

    1. Hi Ashley, thanks so much for your comment! Yes, this is definitely possible, but I’m afraid it’s custom work. If you’d like to get a quote, feel free to contact me here. Thanks a lot for your understanding!

      1. Hi Ashley,
        As for adding text after the discount percentage, you must replace the line:

        if ( $max_percentage > 0 ) echo "<div class='sale-perc'>-" . round($max_percentage) . "%</div>";

        for this:

        if ( $max_percentage > 0 ) echo "<div class='sale-perc'>You save -" . round($max_percentage) . "%</div>";
        1. I’m sorry.
          The code above is for adding text before the percentage.
          To add text after the percentage, is this code:

          if ( $max_percentage > 0 ) echo "<div class='sale-perc'> -" . round($max_percentage) . "% Off</div>";
          1. Thank you!

  18. https://www.dropbox.com/s/tz5c6bvjtzq3jva/Screenshot%202019-06-07%2011.30.59.png?dl=0

    https://www.dropbox.com/s/m3umnzd2dpiwks5/Screenshot%202019-06-07%2011.31.15.png?dl=0

    Should this work for variations or is our plugin stopping it? Has the correct base percentage but other options only have 10% off.

    1. This only works on the Shop page – does that help?

  19. Rodolfo thanks for the code, I don’t know why but it gave me error Optimum Nutrition my log:

    “PHP Warning: Division by zero in …”

    So I went to my functions.php file and the only code that had a math division on it was this one.

    Do you think I am doing something wrong?

    1. Snippet fixed, let me know ๐Ÿ™‚

  20. It worked on WordPress 5.0.3 / WooCommerce 3.5.4 / Jupiter 6 Theme with a little adjustment. Removed display:inline and changed padding to 10px.

    Would like to use it on Product page in top right corner. Any ideas?

    1. Nice, thanks Ryan! Unfortunately this is custom work and I cannot provide a complementary solution here via the blog comments. Thanks a lot for your understanding! ~R

  21. Thank you very much. It works for me on WC 3.3

  22. This worked like a charm. Thanks
    This saved my time

    1. Thank you Faisal! ๐Ÿ™‚

  23. After add this code in my DIVI theme function.php, i can’t upload images from my admin panel and i also can’t see any images in media library

    1. Hey Ankit, thanks for your comment! You should add this to your child theme functions.php

  24. Thank you again for another great snippet!

  25. Thank you! This is very helpful!

  26. Hi Rodolfo,

    For some reason, today I now get the following errors with this code:

    Notice: Undefined variable: highest_percentage

    Notice: WC_Product::get_child is deprecated since version 3.0! Use wc_get_product instead. in /wp-includes/functions.php on line 3831

    Is there a fix for WC 3+?

    1. John, thank you so much! I’ve updated the post with Woo 3.0 compatibility and also removed a couple of bugs ๐Ÿ™‚ Let me know!

  27. Hi Rodolfo,

    Excellent post! Please help me how can i make the percentage on the product of sale price.
    I want this; https://prntscr.com/f3jzzz

    Could you help?

    1. Toggy, thanks so much for your comment! Yes, this is possible – but unfortunately this is custom work and I cannot provide a complementary solution here on the blog. Thanks a lot for your understanding! ~R

  28. Awesome , It works.

    How can I have the same on product detail page ?

    1. Excellent Yash, thanks for your feedback! I suggest to check the single product page hooks (https://businessbloomer.com/woocommerce-visual-hook-guide-single-product-page/), so that you can find the exact position where you can show such discount ๐Ÿ™‚ Let me know!

      1. Thanks I can get on product page.

        I have one more question, how do I show on related products section where upsells are shown , and also show on featured product section in the project?

        Plz guide

      2. Is there any way to show the % discount on Feature product, related products section?

        1. Hello Yash, thanks for your comment! I’m afraid I can’t help this time – this is custom work and unfortunately I can’t provide premium support to free subscribers. Hope this is ok ๐Ÿ™‚

          For your interest, I just launched https://businessbloomer.com/club/, and you might find a suitable plan to cover your requests. Thanks a lot for your understanding!

  29. amazing!
    thank you a lot.
    why can’t i move it with margin inside css?
    it’s stuck in the center no matter what i do.
    could you help?

    1. Awesome Menelaos, thanks for your comment! Just remove the display: inline from the CSS ๐Ÿ™‚

Questions? Feedback? Customization? Leave your comment now!
_____

If you are writing code, please wrap it like so: [php]code_here[/php]. Failure to complying with this, as well as going off topic or not using the English language will result in comment disapproval. You should expect a reply in about 2 weeks - this is a popular blog but I need to get paid work done first. Please consider joining the Business Bloomer Club to get quick WooCommerce support. Thank you!

Your email address will not be published. Required fields are marked *