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
 * @donate $9     https://businessbloomer.com/bloomer-armada/
 */

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 this snippet?

You can place PHP snippets at the bottom of your child theme functions.php file (delete "?>" if you have it there). CSS, on the other hand, goes in your child theme style.css file. Make sure you know what you are doing when editing such files - if you need more guidance, please take a look at my free video tutorial "Where to Place WooCommerce Customization?"

Does this snippet (still) work?

Please let me know in the comments if everything worked as expected. I would be happy to revise the snippet if you report otherwise (please provide screenshots). I have tested this code with Storefront theme, the WooCommerce version listed above and a WordPress-friendly hosting on PHP 7.3.

If you think this code saved you time & money, feel free to join 14,000+ WooCommerce Weekly subscribers for blog post updates or 250+ Business Bloomer supporters for 365 days of WooCommerce benefits. Thank you in advance :)

Need Help with WooCommerce?

Check out these free video tutorials. You can learn how to customize WooCommerce without unnecessary plugins, how to properly configure the WooCommerce plugin settings and even how to master WooCommerce troubleshooting in case of a bug!

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.

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

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

  2. 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 );
            }
          }
          
       }
      
      
  3. 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!

  4. 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!

  5. 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!

  6. 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!

  7. 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!

  8. 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
     * @donate $9     https://businessbloomer.com/bloomer-armada/
     * 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!

  9. 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!

  10. 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!

  11. 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)

  12. 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

  13. 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?

  14. 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.

  15. 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!

  16. 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!

  17. 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!

  18. 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!

  19. 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!

  20. 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?

  21. 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? Support? Leave your Comment Now!
_____

If you are writing code, please wrap it between shortcodes: [php]code_here[/php]. Failure to complying with this (as well as going off topic, not writing in English, etc.) will result in comment deletion. 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 BloomerArmada to get blog comment reply priority, ask me 1-to-1 WooCommerce questions and enjoy many more perks. Thank you :)

Your email address will not be published.