WooCommerce: Bulk Dynamic Pricing Without a Plugin

You’re looking to assign different unit prices based on the quantity added to Cart, for example from 1-100 price is $5, from 101-1000 price is $4.90 and from 1001 units ordered price becomes $4.75.

There are many “Dynamic Pricing” plugins out there (and the number #2 on this article would suit complex pricing rules and dynamic discounts), but this time I want to teach you a simple code to DIY WooCommerce quantity-based pricing.

As usual, comments and shares are much appreciated. Enjoy!

Screenshot of a WooCommerce product with €34 price per unit below our bulk pricing thresholds (more screenshots below)

PHP Snippet: Change Product Price Based on Quantity Added to Cart (Bulk Pricing)

In our example, our product price is €34 and I want to apply a 5% discount above 100 units and a 10% discount above 1000 units. Screenshots for threshold 1 and threshold 2 are below the snippet.

/**
 * @snippet       Bulk (Dynamic) Pricing - WooCommerce
 * @how-to        Get CustomizeWoo.com FREE
 * @author        Rodolfo Melogli
 * @compatible    WooCommerce 3.8
 * @community     https://businessbloomer.com/club/
 */

add_action( 'woocommerce_before_calculate_totals', 'bbloomer_quantity_based_pricing', 9999 );

function bbloomer_quantity_based_pricing( $cart ) {

    if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;

    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return;

    // Define discount rules and thresholds
    $threshold1 = 101; // Change price if items > 100
    $discount1 = 0.05; // Reduce unit price by 5%
    $threshold2 = 1001; // Change price if items > 1000
    $discount2 = 0.1; // Reduce unit price by 10%

    foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
		if ( $cart_item['quantity'] >= $threshold1 && $cart_item['quantity'] < $threshold2 ) {
			$price = round( $cart_item['data']->get_price() * ( 1 - $discount1 ), 2 );
			$cart_item['data']->set_price( $price );
		} elseif ( $cart_item['quantity'] >= $threshold2 ) {
			$price = round( $cart_item['data']->get_price() * ( 1 - $discount2 ), 2 );
			$cart_item['data']->set_price( $price );
		} 	
    }
	
 }
Threshold 1 reached: 5% discount
Threshold 2 reached: 10% discount

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: How to Fix the “Cart is Empty” Issue
    For some reason, sometimes you add products to cart but the cart page stays empty (even if you can clearly see the cart widget has products in it for example). But don’t worry – it may just be a simple cache issue (and if you don’t know what cache is that’s no problem either) or […]
  • WooCommerce: “You Only Need $$$ to Get Free Shipping!” @ Cart
    This is a very cool snippet that many of you should use to increase your average order value. Ecommerce customers who are near the “free shipping” threshold will try to add more products to the cart in order to qualify for free shipping. It’s pure psychology. Here’s how we show a simple message on the […]
  • WooCommerce: Cart and Checkout on the Same Page
    This is your ultimate guide – complete with shortcodes, snippets and workarounds – to completely skip the Cart page and have both cart table and checkout form on the same (Checkout) page. But first… why’d you want to do this? Well, if you sell high ticket products (i.e. on average, you sell no more than […]

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

53 thoughts on “WooCommerce: Bulk Dynamic Pricing Without a Plugin

  1. Great tutorial,

    How can I display in the cart and checkout the initial price too before the discount?

    1. Hello Vasilis, 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!

  2. Useful post as usual. But how about bulk pricing in single product page? I mean I whould also change the price, based on selected quantity before add an item to the cart, from the product page, and then eventually change it on cart. Is there a hook for single product page?
    Thank you in advance, awesome job.

    1. Hello Giovanni, 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!

  3. Hi Rodolfo,

    Thanks for all you help and support with this info.

    In the case of being able to apply this code, how would it be so that the discount only applies when another product is added to the cart?

    Thank you very much

    1. Hi Francisco, 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. Hi, thanks for the great work as always! Is there a way to create a rule that applies a % discount based on categories? I’d like to try to do this with code because using plugins my facebook store never shows the discount price only full price. So I thought maybe there’s a way to solve this with code.

    1. Hi Nicholas, 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!

  5. Hi everybody,

    I have change the code to make it work with a fix price with more quantity but it does work for the other quantity. Any tips will be appreciated.

    add_action( 'woocommerce_before_calculate_totals', 'bbloomer_quantity_based_pricing', 9999 );
     
    function bbloomer_quantity_based_pricing( $cart ) {
     
        if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
     
        if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return;
     
        // Define discount rules and thresholds
        $threshold1 = 2; // Change price if items > 2
        $discount1 = 20; // Reduce unit price by 20$
        $threshold2 = 3; // Change price if items > 3
        $discount2 = 40; // Reduce unit price by 40$
    	$threshold3 = 4; // Change price if items > 4
        $discount3 = 60; // Reduce unit price by 60$
    	$threshold4 = 5; // Change price if items > 5
        $discount4 = 80; // Reduce unit price by 80$
     
        foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
          if ( $cart_item['quantity'] >= $threshold1 && $cart_item['quantity'] < $threshold2 ) {
             $price = round( $cart_item['data']->get_price() - ( $discount1 ), 2 );
             $cart_item['data']->set_price( $price );
          } elseif ( $cart_item['quantity'] >= $threshold2 ) {
             $price = round( $cart_item['data']->get_price() - ( $discount2 ), 2 );
             $cart_item['data']->set_price( $price );
          } 
    		elseif ( $cart_item['quantity'] >= $threshold3 ) {
             $price = round( $cart_item['data']->get_price() - ( $discount3 ), 2 );
             $cart_item['data']->set_price( $price );
          }
    		elseif ( $cart_item['quantity'] >= $threshold4 ) {
             $price = round( $cart_item['data']->get_price() - ( $discount4 ), 2 );
             $cart_item['data']->set_price( $price );
          }
        }
        
     }
    

    Thanks you a lot for your help.

    1. Sorry guys I just fixe my code…
      Here is the code with 5 + quantity discount.

      
      add_action( 'woocommerce_before_calculate_totals', 'bbloomer_quantity_based_pricing', 9999 );
       
      function bbloomer_quantity_based_pricing( $cart ) {
       
          if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
       
          if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return;
       
          // Define discount rules and thresholds
          $threshold1 = 2; // Change price if items > 2
          $discount1 = 20; // Reduce unit price by 20$
          $threshold2 = 3; // Change price if items > 3
          $discount2 = 40; // Reduce unit price by 40$
      	$threshold3 = 4; // Change price if items > 4
          $discount3 = 60; // Reduce unit price by 60$
      	$threshold4 = 5; // Change price if items > 5
          $discount4 = 80; // Reduce unit price by 80$
       
          foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
            if ( $cart_item['quantity'] >= $threshold1 && $cart_item['quantity'] < $threshold2 ) {
               $price = round( $cart_item['data']->get_price() - ( $discount1 ), 2 );
               $cart_item['data']->set_price( $price );
            } elseif ( $cart_item['quantity'] >= $threshold2 && $cart_item['quantity'] < $threshold3 ) {
               $price = round( $cart_item['data']->get_price() - ( $discount2 ), 2 );
               $cart_item['data']->set_price( $price );
            } 
      		elseif ( $cart_item['quantity'] >= $threshold3 && $cart_item['quantity'] < $threshold4 ) {
               $price = round( $cart_item['data']->get_price() - ( $discount3 ), 2 );
               $cart_item['data']->set_price( $price );
            }
      		elseif ( $cart_item['quantity'] >= $threshold4 ) {
               $price = round( $cart_item['data']->get_price() - ( $discount4 ), 2 );
               $cart_item['data']->set_price( $price );
            }
          }
          
       }
      
      
  6. Hi there, spectacular resource by the way…

    Our client would like each product to have its own bulk discount price ie. they are a promotional company.
    To this end we have created custom fields via ACF Pro in order for the thresholds to be applied per product.
    Unfortunately we can’t seem to define the variable via the ACF field eg.

     $threshold1 = get_field('quantity_1'); // Change price if items < ACF field - quantity 1 

    What are we missing here?
    Kindest, Andy

    1. Hey Andy 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!

  7. How can we show the total amount of discounts made to the customer?

    1. Hi Hakan, 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. Not working for me (latest woo-version), price do not change.

    1. Sorry Daniel, works here

      1. This wasn’t working for me either, but after removing the following line, it works perfectly:

        if ( is_admin() &amp;&amp; ! defined( 'DOING_AJAX' ) ) return;

        FYI- I am skipping the cart, and going straight to checkout using Daniel’s code

        1. Thanks for your feedback!

  9. Hi!

    I’m looking for a code to add custom discount (%) based on user role. I’ve added now 3 custom user role.
    Can You help me?

    Thanks in advance!

    1. Hi Istvan, 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!

  10. Hi Rodolfo Melogli,
    I would like to have nth product free.

    For example 5 products added, 6th added price should be 0.
    I works when all product quantities are 1, but if you have same product with quantity = 6, how to make it’s TOTAL price of product_price_of_quantity_1 * 5 ?

    1. Hi Marius, 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!

  11. Hi,
    Thanks for the code! It helps me a lot. With a little search in your tutorials and your other articles I changed the code.

    I need a discount for a specific product and a fixed price, not a percentage.
    With a little search in your tutorials and your other articles I changed the code.

    Best regards,
    Mieke

    /**
     * @snippet       Bulk (Dynamic) Pricing - WooCommerce
     * @how-to        Get CustomizeWoo.com FREE
     * @author        Rodolfo Melogli
     * @compatible    WooCommerce 3.8
     * @community     https://businessbloomer.com/club/
     * modified version with product ID en fixed price discount 
     */
     
    add_action( 'woocommerce_before_calculate_totals', 'bbloomer_quantity_based_pricing', 9999 );
     
    function bbloomer_quantity_based_pricing( $cart ) {
     	global $product;
        if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
        if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return;
     
        // Define discount rules and thresholds and product ID
        $threshold1 = 100; // Change price if items > 99
        $discount1 = 0.10; // Reduce unit price by 0.10 euro
        $threshold2 = 200; // Change price if items > 199
        $discount2 = 0.20; // Reduce unit price by 0.20 euro
        $product_id = 5869; //zwollenaartje
    
        foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
          $product_in_cart = $cart_item['product_id'];
            if ( $product_in_cart === $product_id && $cart_item['quantity'] >= $threshold1 && $cart_item['quantity'] < $threshold2 ) {
               $price = round( $cart_item['data']->get_price() - $discount1, 2 );
               $cart_item['data']->set_price( $price );
            } elseif ( $product_in_cart === $product_id && $cart_item['quantity'] >= $threshold2 ) {
               $price = round( $cart_item['data']->get_price() - $discount2, 2 );
               $cart_item['data']->set_price( $price );
            }    
          }
    }
    
    1. Nice!

  12. Hi!

    Could you give me a help for a specific product only?
    I would like to add a discount only

    product_id == 540

    Thx

    1. Hi there, 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!

  13. Hi , I am trying to understand what one line in this code does

     $product_id = $cart_item['product_id'];

    You appear to creating a variable $product_id but I cannot see this variable used anywhere else in the code.
    Can you explain please.

    thank you

    1. You’re right, it’s not needed!

  14. Hi Rodolfo,

    Very informative post for the price object. I was wondering why are you subtracting 1 from the $discount variables? Thanks in advance.

    1. Hi Edder, thank you! It was easier for me. To calculate discounted price, I do price*0.95 in case it’s 5% off (0.05 discount). So the formula actually becomes price*(1-0.05)

  15. Ho Rodolfo,
    I’ve got my shop set up using WooCommerce Product Table – would your code need changing to work? I’ve adjusted to the below to test and price doesn’t change once threshold reached…

    add_action( 'woocommerce_before_calculate_totals', 'bbloomer_quantity_based_pricing', 9999 );
     
    function bbloomer_quantity_based_pricing( $cart ) {
    
        if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
    
        if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return;
    
        // Define discount rules and thresholds
        $threshold1 = 5; // Change price if items > 4
        $discount1 = 0.05; // Reduce unit price by 5%
        $threshold2 = 10; // Change price if items > 9
        $discount2 = 0.1; // Reduce unit price by 10%
    
        foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
          $product_id = $cart_item['product_id'];
          if ( $cart_item['quantity'] >= $threshold1 && $cart_item['quantity'] get_price() * ( 1 - $discount1 ), 2 );
             $cart_item['data']->set_price( $price );
          } elseif ( $cart_item['quantity'] >= $threshold2 ) {
             $price = round( $cart_item['data']->get_price() * ( 1 - $discount2 ), 2 );
             $cart_item['data']->set_price( $price );
          }   
        }
    
     }
    
    1. Just need to clarify. It does work if I hit “Update Cart” on the cart page. Just wanting price to change on the fly on the shop page if someone reaches the threshold… Ajax I suppose?. Is this possible?

      1. It should work. I see PHP errors in your custom functions, maybe fixing those might help

  16. It did not work for me. Maybe should I try a different setting for my store or something like that? Thank you!

    1. Weird, it should work if you have set up everything correctly. Can you try with a different theme and no other plugins please?

  17. I am looking for a plugin where the customer selects from a drop down menu 1-100 and based on which amount they choose, the price changes. For example default is 1 in the dropdown list and price $100, but if you select 10 in the dropdown list, the price changes to $1000 – can your plugin or code help?

    1. Hi Jake, 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!

    2. You can do this without a plugin or integration my friend. Just switch from “Simple Product” to “Variable Product” on the product page and then create your attributes.

  18. Does it work in a multi-currency environment?

    Your code is perfect when running in the default currency. (REALLY APPRECIATE!!), but in multi-currency environment, sounds have some problem,

    To be exact, I found that the displayed price in Single Product Price has double multiplied the currency rate.

    For example: If the product is US$63.95, it should be HK$498 (fix exchange rate between HKD & USD set as 7.8). However, the display price become $63.95 x 7.8 x7.8 = HK$3,890.72…….

    Here’s a video capture for your reference: https://jmp.sh/AxbNJ43
    P.S. I’m Using Villatheme’s MultiCurrency Plugin. (https://villatheme.com/extensions/woo-multi-currency/)
    P.P.S The Above example is: offer 15% discount for order 3 unit or above.

    Great Thanks!

    1. Hello Joe, 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!

  19. Hi,
    Thanks for the code it is amazing! 🙂 Is it possibly to apply it for just specific products ?

    1. Hello Jozsef, 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!

  20. Amazing like always!!!

    Just a question, what do I need to write if I want to add another level (i.e: +5 = 5%, +10=10% and +20=20%) ?

    Thank you for all Rodolpho

    1. Hi Stan, 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!

  21. Hello! Your blog is really great!
    Is there a way to apply a percentage discount to all products older than 100 days from today’s date?
    Without a plugin…

    1. Hey Fabio, 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!

  22. Hi
    Great … Can the settings ( my price rule) show up on the single product page? So the customer can see if he/she added a few more the price would drop?

    I am only targeting 1-2 products that both have variants and quantity is low:
    1 = full price (100$)
    3 = 10% off / OR 89$ pr. item
    5 = 15% off / OR 85$ pr. item

    Best regards

    Peter

    1. Hello Peter, 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!

  23. I’m wondering if this could be amended to shipping costs

    – For example if a “flat” rate were set to say: $10 per order. Then if more than one item were placed in the cart, the ( $cart_item[‘quantity’] ) would check for more than one – and use the threshold function to apply it to the “flat rate” amount replacing it with: $14 instead.

    What do you think?

  24. Congratulations ! I think it’s a good post to do this action in an online Woocommerce store without using a plugin. Is it possible to apply different price and different quantity conditions for each product? Thank you

    1. Thanks so much! Yes, it is possible – I suggest you take a look at “conditional logic”: https://businessbloomer.com/conditional-logic-woocommerce-tutorial/ and https://businessbloomer.com/woocommerce-conditional-logic-ultimate-php-guide/. Let me know 🙂

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 *