The Dynamic Pricing extension for WooCommerce is a great plugin that allows you to change prices on the fly under a number of different circumstances. One way in which we see this plugin being used quite often is per-product pricing for registered customers with a specific role – wholesalers, for example. However, when this approach is used the adjusted price is not displayed in the catalog – only in the cart. We’re going to fix that.
The Scenario
You’re using the Dynamic Pricing extension on your WooCommerce shop to give a special subset of your customers different pricing for specific products. For example, your best flavour of granola (peach) has a regular price of $8, but for Wholesalers you’ve defined a dynamic price of $6. When Wholesale customers shop, they still see the regular price, until their special price is displayed in the cart.
The Fix
We’re going to hook into the woocommerce_get_price
action which is applied when the price of every product is calculated. Our hook function will receive two arguments: the retail price and the product as an object. We’ll first abort the price change in the admin dashboard (line 5) and the cart (line 7). Then, we’ll check if the current product has pricing rules defined (line 11). If it does, we’ll get the current user’s details (line 14) and then check each rule to see if it’s role-based (line 17). If it is (line 19), and the current user has the same role (line 22), we’ll add the rule price to an array (line 23). We’ll then use the lowest price from this array instead of the retail price.
add_action( 'woocommerce_get_price', 'gowp_display_role_price', 10, 2 ); function gowp_display_role_price( $price, $product ) { // we don't want to modify prices in the admin dashboard if ( is_admin() ) return $price; // we'll let Dynamic Pricing do its own thing on the cart if ( is_cart() ) return $price; // does the product have any pricing rules defined? if ( $pricing_rules = get_post_meta( $product->id, '_pricing_rules', TRUE ) ) { // get the current user's details $current_user = wp_get_current_user(); // find all role-based rules that apply to our user and build an array of discounted prices foreach ( $pricing_rules as $pricing_rule ) { $conditions = $pricing_rule['conditions']; foreach ( $conditions as $key => $condition ) { $roles = $condition['args']['roles']; foreach ( $roles as $role ) { if ( in_array( $role, $current_user->roles ) ) { $role_rules[] = $key; } } } foreach ( $role_rules as $role_rule ) { $role_prices[] = $pricing_rule['rules'][$role_rule]['amount']; } } // use the lowest of available discounted prices if ( $role_prices ) { asort($role_prices); $price = array_shift( $role_prices ); } } return $price; }
This is exactly what I am looking for. What file does this go in? Is it in the main Woocommerce plugin or the Dynamic Pricing?
Hi Jeremy. I would put this either into your active theme’s functions.php or into a stand-alone plugin file (recommended).
Thanks, this works great!
Jeremy, sorry for the late reply. I believe the issue you’re experiencing may be related to the error in the code that @disqus_x8aeYByfW4:disqus pointed out today (line #23).
Lucas, I updated my site with the updated code and I am still having the same issue. I have 3 different levels of customers. My standard group has the highest price and then I used the fixed price for the Gold and Platinum. If the user is Standard or Platinum everything works as it should. However, when I make the user Gold, middle group, then they see the Platinum price on the shop page and when an item is added to the cart they see the Gold price but with the Platinum subtotal in the minicart. When that user goes to view the full cart they are shown the Platinum price crossed out with the correct Gold price next to it. I have added a screenshot of the issue. It happens with Variable and Simple products.
So, Standard is $10, Gold is $8 and Platinum is $5 and your screenshot is a Gold customer, seeing the Platinum price on the product and the sub-total – just making sure I’m following correctly. What happens for Gold customers without this code added?
You are correct with the situation. If I remove your code, the Gold customer sees the Standard price of $10 on the item page. Once they add the Pens to their cart then they see the correct $8 with the correct subtotal of $8.00.
Lucas. This is exactly what we need. But I am having the same issue Jeremy is. It is displaying the lowest price out of our multiple user roles. I have added David’s edit on line 23 but am still having the issue. Do you have an updated version of the code? I would be very appreciative of any help.
quick note… you need to get the current user if you want to only apply the role. replace the role check with this…
if ( in_array( $role, (array)$current_user->roles ) ) {
$role_rules[] = $key;
}
David, thank you for pointing this out. It seems that when I re-organized the code while writing the post I got this section wrong – the post has now been updated.
Lucas, thank you so much for sharing your coding experiences. Very valuable…
I am working on extending this a tad, with variable product type pricing. this is a simple one liner that is using the built-in WC prices.
if ( $product->is_type( ‘variable’ ) ) return ““.wc_price($product->min_variation_price).” “.wc_price($product->max_variation_price).”
“;
I think you can start parsing out the variation rules using something like this…
$variation_rules = $pricing_rule[‘variation_rules’];
(based upon your $conditions = $pricing_rule[‘conditions’];)
have you had to parse out the variation product type and try to match up the prices?
David, I edited your comment to format the code. Disqus supports
pre
andcode
tags, but apparently you need to HTML-encode the HTML tags to prevent them from being parsed.I’ve not had to mix this with variation pricing in the past, but if you provide some sample data I can try to replicate it locally.
Lucas, I just made a variable product with an attribute (tickets) 2 variations (7 day and Weekend Only), then assigned dynamic pricing to a specific role.
Works fine in the cart, but of course dynamic pricing just displays the “retail” not role based pricing on the product page. Only when in the cart you can see the role price.
I also added in another condition during the loop of
.
. It is checking to make sure a role is assigned and not the ‘EVERYONE’ setting which is not treated as a role. It was throwing errors in the WP log without it.
Hi David, I’m attempting to display rule values of the [applies_to] => everyone. My thinking is that I can apply the same logic?
it’s been a while since i have battled this…. but i do recall a role like that.. i think 🙂
the main thing to keep in mind with all of this is that showing the price is a very, very complex process because of all the potential variations. and, that is the reason it isn’t done.
it is very easy to see how you could potentially render a view, expose a price that shouldn’t be shown and then get the reseller in a drama with a consumer. the price can be shown in a lot of different locations and in different layouts.
you take on a LOT of ownership when you make the step into price rendering. be 110% everyone you are dealing with understands the risks 🙂
Thanks for the advice David. I’m luckily not dealing with the price but using the similar logic to print pricing tables. I used a different method to above but it’s working now 🙂
Thanks again
Dear Lucas, I apologize in advance as I am new to this, the codes you posted above, where exactly am I adding this to using the file manager? Please advise. Thank you so much for your assistance.
Hi Paula!
I would recommend editing files via FTP rather than the built-in editor as any syntax errors while editing can potentially bring the site down.
You can add this code to either the functions.php file of your active theme or as a stand-alone plugin; the latter is recommended, but requires a few extra steps.
Dear Lucas,
Thank you so much for your reply, I figured it out and it looks beautiful. I’m kinda new to this WordPress code business so it’s taking a minute and lots of Google search! 🙂
Thank you again for your assistance and I apologize for the bother.
Best regards,
Paula Vianna
No trouble at all – that’s what we’re here for!
David. This is exactly what we need. But I am having the same issue Jeremy is below. I tried contact Lucas, but this issue is somewhat time sensitive and I have not heard back yet. It is displaying the lowest price out of our multiple user roles for the product. We have tiered pricing for dealers ranging from $97.97 to $69.98. For our OEM users it goes down to $59.98. When I insert the code and log in as a dealer it is displaying $59.98. I think there are 2 things I need to change in the code. First, only getting the price for the current logged in user role. Second, displaying the HIGHEST price for that role instead of the lowest. I would be very appreciative of any help.
Jeremy… I have done quite a bit of work on this and have a working solution which I think handles these issues. The main issue is inspecting the role of the user that is logged in to the iteration loop of the offers – and it gets a bit complex especially when dealing with variable product types as the array is yet again nested. I am not at a location to share any code but you can reach me at dbaker@dkburnap.com if you want more info…
Hi – I’m keen to find a solution for outputting the price / discount structure on the product page for variable products. I am using the Dynamic Pricing extension.
In my scenario, I have user tiers – wholesale1 and wholesale2. Both users get quantity based discounts – though one is better than the other; e.g. wholesale1 gets 1 – 4 items 10% off, 5 – 10 items 20%… and wholesale2 will get 5% and 10% etc…
I tried your code – it doesn’t work for me. I also came across this function that did work well: http://blueskysessions.com/2014/03/31/woocommerce-dynamic-pricing-plugin-how-to-show-the-quantity-pricing-rules-for-all-product-variations-on-the-product-page/
However, it does not query the user role type before outputting the pricing table. So can anyone assist me in getting that to query the user role first and then display according to role?
I looked at alternate code canyon wholesale/pricing apps – but could not find one that a) supported multiple tiered users (wholesale1, 2 3 etc) and b) worked with product-csv-import which we use for bulk management.
Here’s my code that’s not quite there http://pastebin.com/AXih7ZrH
Any advise or assistance appreciated.
One of the best extension and this makes it more powerful.
I’ve looked everywhere for a solution to this.
Sadly im getting the discount amount instead of the price after discount.
Let’s say I have a product costing $200 with 50% discount. The price im seeing in the front-end is $50 instead of $100.
Anyone seeing this too?
I’m seeing the same thing with the code that was provided. Still trying to find a solution and would rather display it dynamically instead of relying on creating 900 messages, 1 for each product, using Conditional Content
If you use , instead of . you need to use str replace. I was seeing the same..
I’ve got the exact same thing… any chance you worked out a solution?
I’ve got a client who wants to use dynamic pricing and wondering if this could be the best solution? They will have a product with multiple variables one of which being size. The next variable will be material. The material price will need to differ though based on the size selected. Could this work for that scenario? Any advice would be much appreciated.
You wouldn’t need the dynamic pricing plugin for this if I’m understanding correctly. You can use the built-in variations functionality for this. https://docs.woothemes.com/document/variable-product/
Thank you but I can’t see how I would go about changing a variation price based on another variation selection
You have two attributes, Material and Size. Let’s say each has two choices. Material can be soft or hard and Size can be small or large. Once you’ve created your two attritubes, each with two options, you then generate Variations. In this case you’ll have four variations: soft/small, soft/large, hard/small, hard/large. Each variation can have its own price, SKU, weight, dimensions, etc.
THANK YOU!! You’ve saved me scratching my head and banging it very hard against a brick wall
That’s what we’re here for!
Sorry one more question if you don’t mind? The client now has 7 attributes each with up to 8 variations. How would I go around the pricing for that many combinations? Any tips gratefully received! Tearing my hair out here
After you’ve created the variations you can set the price for all of them using the bulk variation options (https://gowp.com/blog/apply-the-price-of-a-woocommerce-product-variation-to-all-variations-of-the-same-product/) and/or update the price of each variation individually.
Hi Lucas,
Thanks for sharing this code, I’ve learnt that little bit more about looping through data because of it.
I’ve spent some time now attempting to output the prices in a table via user role using the same method you’ve shared here. Whilst my table is outputting fine I’m still unable to only output the values that relate a particular role.
I’m sure I understand each stage and yet I’m not getting anywhere. If you have a moment to review my code I’d really appreciate it, even if it’s just to say “no, totally wrong” that would help.
StackOverflow Question
Thanks again
Is there a way to show a product’s bulk discount tables from within the shop/archive view?
Brilliant article Lucas! Saved me a lot of time.
I ended up using the Dynamic Pricing plugin from WooCommerce to fix everything up in the end but didn’t fancy the crazy high price for it.
How do I get this working with fixed_price set at dynamic pricing?
@karpstrucking:disqus is it possible to get it work for fixed price? Now it shows 0 at fixed price, I dont use variations
Need to use str replace.. dynamicpricing uses . and my price is set with ,.. 🙂
add_action( ‘woocommerce_get_price’, ‘gowp_display_role_price’, 10, 2 );
function gowp_display_role_price( $price, $product ) {
// we don’t want to modify prices in the admin dashboard
if ( is_admin() ) return $price;
// we’ll let Dynamic Pricing do its own thing on the cart
if ( is_cart() ) return $price;
// does the product have any pricing rules defined?
if ( $pricing_rules = get_post_meta( $product->id, ‘_pricing_rules’, TRUE ) ) {
// get the current user’s details
$current_user = wp_get_current_user();
// find all role-based rules that apply to our user and build an array of discounted prices
foreach ( $pricing_rules as $pricing_rule ) {
$conditions = $pricing_rule[‘conditions’];
foreach ( $conditions as $key => $condition ) {
$roles = $condition[‘args’][‘roles’];
foreach ( $roles as $role ) {
if ( in_array( $role, (array)$current_user->roles ) ) {
$role_rules[] = $key;
}
}
}
foreach ( $role_rules as $role_rule ) {
$role_prices[] = $pricing_rule[‘rules’][$role_rules[0]][‘amount’];
}
}
// use the lowest of available discounted prices
if ( $role_prices ) {
asort($role_prices);
$price = array_shift(str_replace(‘,’, ‘.’, $role_prices));
//print_r($price);
}
}
return $price;
}
This is SO close! A little late to the game but anyone able to help?
I can see the price change on the product page when I view as a wholesale role, but I get an “Invalid argument supplied for foreach()” error on this line: foreach ( $role_rules as $role_rule ) whenever I view the product as an admin or not logged in. It seems like there isn’t an array (which would make sense, only wholesale has discounts) so how can I “turn off” this part of the code when not viewing as a wholesale role?