FB Pixel

Display product-specific role-based prices with the Dynamic Pricing extension

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;

}

43 thoughts on “Display product-specific role-based prices with the Dynamic Pricing extension”

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

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

  2. 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).”

        add to cart to see AAA 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 and code 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

            $pricing_rules

            .

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

            foreach ( $conditions as $key => $condition ) {
            
                // note you may have [applies_to] => everyone which means no [roles] in the array
                if ( array_key_exists('roles',$condition['args']) ) {
                    $roles = $condition['args']['roles'];
                     foreach ( $roles as $role ) {
                        if ( in_array( $role, (array)$current_user->roles ) ) {
                            $role_rules[] = $key;
                        }
                    }
                }
            
          • Hi David, I’m attempting to display rule values of the [applies_to] => everyone. My thinking is that I can apply the same logic?

            
            // Check if everyone
            $is_everyone = $condition['args']['applies_to'];
            
            // into the array
            if ( in_array( $is_everyone, 'everyone' ) ) {
                    $role_rules[] = $array_rule_sets[$rule_key]['rules'];
            }
          • 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

    • 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…

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

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

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

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

  7. Is there a way to show a product’s bulk discount tables from within the shop/archive view?

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

    • @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;

      }

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

Comments are closed.