Here’s an interesting question we got from Mike:

I sell grass fed beef skewers, and there are a certain number of skewers per pound. Customers should be able to select the number of skewers, but I want to show them the cost per pound so they can compare them. Is this possible?


There are a couple moving parts to this question, but the optimal solution here would be to change the WooCommerce price display. As prices are based on skewer quantity, we want the “product” to represent one skewer, and the price to be the skewer price. That way, customers can order 3 skewers and be charged the right amount.

However, you can definitely change the pricing display so it’s easier for customers to compare unit price across products. If several products will have different unit prices, you’d need a more advanced way to do this, but here are a couple methods to get you started with adjusting the WooCommerce price display.

For either method, there are a couple important filters we’ll need to use:

  • woocommerce_get_price_html: changes the way price is shown on the product and shop pages
  • woocommerce_cart_item_price: changes the way product prices are shown in the cart table (not at checkout since only quantity / total price are shown here, not the unit price).

Filter WooCommerce Price Display for All Products

Let’s say you want to add a label to the end of all of your product prices, such as “per package” (helpful if your products are bundles of something or come in pre-packaged sets). You can change the pricing display to append this label to the price with the product and cart price filters:

The woocommerce_get_price_html filter will change this on your shop pages:

WooCommerce Price Display: shop labels changed

and on your single product pages:

WooCommerce price display: product label changed

The woocommerce_cart_item_price filter will adjust this display within the cart as well:

WooCommerce Price Display: Cart label Changed

Filter WooCommerce Price Display for a Single Product

What if you want to specifically change the price display for a particular product? This can be done with the same filters, as they’ll also pass additional arguments for you to conditionally change the price. For example, let’s return to our skewer example from the question. While skewers are sold individually at $2 per skewer, we want to show “$15 per kg” as the price instead so customers can compare different products.

WooCommerce original price display

This time we’ll separate out these filters and use two functions to modify the product and cart prices. We’ll first check for the product ID, then change the pricing display for that product alone.

The first function will change my product page:

WooCommerce price display: product price changed

Along with the shop display:

WooCommerce price display: shop price changed

While the second function will adjust my cart display with my new pricing:

WooCommerce price display: cart price changed

However, if you have multiple products with unit prices, this method will be very cumbersome, and we probably don’t want to have a switch / if statements for every product ID. Instead, I’d recommend using a product custom field to adjust the price display. We can use the ID to get this field, then save ourselves a lot of hard-coding since we’ll pull the field in programmatically.

Filter WooCommerce Price Display Based on Product Fields

If you have to change the pricing display for some products but not all of them, or each product would have a different unit price, using a custom field will give us a far simpler code snippet to implement, as we can add the field for each product, then just retrieve this field with our snippet.

You can add a unit_price custom field to each product that requires it, then add the unit price value here.

WooCommerce price display: unit price field

Add custom field

Once you’ve added this, you can then retrieve the unit price, and if one is set for the product, adjust the pricing display to use that unit price and your custom label instead:

(wc_price() is a handy little function to format numbers with the shop pricing display settings, use it!)

In this case, pricing display on the product / shop page will only be changed if a unit price is set. If not, they price will remain the same:

WooCommerce price display: shop using custom fields for price

The same will happen with items in the cart — the WooCommerce price display will be conditionally adjusted depending on whether the item has a unit_price set or not in the custom field:

WooCommerce price display: cart using custom fields for price

Just because you price items in one way doesn’t mean you need to display that price to customers. Sometimes changing the price display can give customers more information about how the product is packaged, or it can allow customers to more easily compare products.

Hope this helps Mike!

Published by Beka Rice

Beka leads product direction for SkyVerge, focusing on new features for our plugins and Jilt. She spends a lot of time on research and interviews, but likes to write so she has an excuse to spend more time jamming out to anything from The Clash to Lady Gaga.

38 Comments

  1. […] a tutorial on changing the WooCommerce price display from […]

    • This is great! Just what I needed.
      Quick question though.. if I disable viewing of the product pages individually, and Want to insert a custom field from the page that displays the category.. would this still work? If so, how.

      My scenario is this:
      A category is displayed across multiple pages, but I need to pass the page name (or a custom field) through when the product is added to cart. Without affecting global product names.

  2. Great article, very helpful and well detailed. Is it possible to apply this (or exclude) to specific categories?

  3. hi

    would something like this work if i wanted to show prices /qty?

    i’ve got a product that’s set up with variations which are basically quantites eg 100, 200, 300, and each of those has a price, eg 80, 70, 60 so on the catalogue page it shows £60-80 as the price but ideally id like it to show 26p-60p

  4. Hi,

    Would it be possible to also add the ‘per kg’ as a custom field so this can be changed on each product page too please?

    • Sure, no reason you couldn’t use another custom field and get it the same way as the unit price, they’re all save the same way as postmeta 🙂

  5. Thanks Beka – Can you tell me how to modify this code so that instead of saying “Free” next to a free product in the card it says “No charge”?

    • Yet another follow up – I modified your code above to the following to return a blank after the per unit price in the shopping cart. It works if there is a price specified, but not if price = $0. Then “Free” still shows. I cannot figure out what is driving the “free” label in the shopping cart, can you help?
      function sv_change_product_price_cart( $price, $cart_item, $cart_item_key ) {
      if ( 550 === $cart_item[‘product_id’] ) {
      $price = ”;
      }
      return $price;
      }
      add_filter( ‘woocommerce_cart_item_price’, ‘sv_change_product_price_cart’, 10, 3 );

  6. Follow up to my post a few minutes ago – I DID successfully add this code to my child theme to get rid of this free language at checkout a while back… I only recently noticed it is still in the cart as the unit price and I need to correct that asap -TIA!
    /*get rid of the free shipping language at checkout */

    add_filter( ‘woocommerce_cart_shipping_method_full_label’, ‘remove_free_from_shipping_label’, 10, 2 );
    function remove_free_from_shipping_label($full_label, $method){
    return str_replace(‘ (‘ . __( ‘Free’, ‘woocommerce’ ) . ‘)’, “”, $full_label);
    }

  7. Thanks Beka!
    Weirdly, that code does not work either. I cannot figure out for the life of me where that silly little “free’ is being pulled from. Have also contacted the theme developers but they have not been too helpful. There are a few theme templates overriding Woocommerce but I have dug through them all and I can’t find any references to the word “free” in there either. Any clue where this little bugger might be hidden? Thanks in advance, Katie

  8. I have some variable products that we sell, and people sometimes think the price is for everything instead of individual items. I want to add “each” beside the price for these products. Would one of these ways solve my problem? Also where would I put the code if I need some? Thanks!

  9. Hello,
    Thanks for this great piece of code. I have got an issue.
    I tried your custom field method and it works fine. But I have used it in those products where I kept the price field bank(catalog mode) and now I am having issues in sorting by price.
    I have some products which say “Starting from rs 10000”. While sorting low to high those products always come upfront where as i have products which have lower price than those products. Is there a workaround about this??? Thanks in advance.

  10. Great info. I am looking for something similar, so i am asking you here.

    I need to hide the sale price if the product has a custom field. So, if custom field = 1, then hide sale price and only show the regular price (category page and single-page).

    Can it be done? I tried so many things and as a newbie, damn… it is so hard! Thanks a lot

  11. Thanks, I was trying to find out how to add text next to the price and this worked.

  12. Great article!
    I have 2 items types: LB and Pack. Anyway to do this by category?

    Example: I’m selling meat, most items are by lb but 5-10 items are by pack (ie hotdogs). All these items are in the same category. So All products say ‘lb’ while the deli category says ‘packs’.

    thanks!

  13. Very helpful article. I want to show two differnet prices in my shop, one web price that will be the price when a priduct is added to the cart and one store price that is the one the customer will get if he visits our physical store. Is there any way to do that?

    • Hey Konstantinos, you could use something similar to our ‘custom field’ approach to add an additional “in-store” price, you’d tack this onto the regular price display instead of modifying it, though leveraging the product’s short description to show an in-store price might be an easier route to get started. (since that typically displays right under the price)

  14. It is wrong working with the grouped product.

  15. Is there a way to only add “per dozen” to certain categories in woocommerce, or a way to exclude others? I have a fly fishing site where items are sold in dozens, but not all items are flies, some are rings and accessories, etc.

    http://gtconcepts.co/hf/shop/

    Thanks,
    Andy

  16. Thanks Beka, Very useful post indeed.

    I would like to know, if my products may have 2 different unit such as Kg and Package for example, “10$ per kg” and 15$ per Package”. How to modified it from your post, this section “Filter WooCommerce Price Display Based on Product Fields”. If you can explain me, that will be great. Thanks you Beka.

  17. Great article!
    I would like to add multiple id’s to this function.
    Could you tell me how it can be done?

    function sv_change_product_html( $price_html, $product ) {
    if ( 337 === $product->id ) {
    $price_html = ‘$15.00 per kg’;
    }

    return $price_html;

    }
    add_filter( ‘woocommerce_get_price_html’, ‘sv_change_product_html’, 10, 2 );

    function sv_change_product_price_cart( $price, $cart_item, $cart_item_key ) {
    if ( 337 === $cart_item[‘product_id’] ) {
    $price = ‘$15.00 per kg(7-8 skewers per kg)’;
    }
    return $price;
    }
    add_filter( ‘woocommerce_cart_item_price’, ‘sv_change_product_price_cart’, 10, 3 );

    Thanks in advance.

  18. Thank you so much!

    I tried adding a different parameter (one product will be listed ‘/lb’ and one will be listed ‘per unit’) when using Custom Fields.

    When I added a new function designating the new label, I received this error:

    Fatal error: Cannot redeclare sv_change_product_html() (previously declared in /home/Baptex1009/public_html/wp-content/themes/flatsome-child/functions.php:14) in /home/Bapex1009/public_html/wp-content/themes/flatsome-child/functions.php on line 47

    I am new to programming so I apologize if this is a confusing question! Would it be possible to use the function you provided but have it only grab text from the Custom Field instead of having two functions.

    Thanks in advance!

  19. Thanks, works great for us!

    One odd thing though: it doesn’t affect the price we see when logged in as admins. It only affects the price of visitors. At least for us!

    If you ever check back here, and you have any suggestions for how to also change the price for admins, please post!

    Maybe we’re just experiencing something odd.

  20. Simply the best tutorial i found about this issue, solved all of my problems. Thanks a lot!

    • does this require an additional plugin? where did you find “add” custom field?

  21. Wasn’t able to get this working with variable products. Trying to change the original price in the cart didn’t work. Product ID is 141 Product variation id 142

    function sv_change_product_price_cart( $price, $cart_item, $cart_item_key ) {
    if ( 142 === $cart_item[‘product_id’] ) {
    $price = ‘$15.00 per kg(7-8 skewers per kg)’;
    }
    return $price;
    }
    add_filter( ‘woocommerce_cart_item_price’, ‘sv_change_product_price_cart’, 10, 3 );

    Any advice would be appreciated Cheers!

    • Figured it out…..
      ///add ‘per month’ Curbside Service products in the shop
      function themeprefix_custom_price_message( $price ) {

      global $post;
      
      $product_id = $post->ID;
      $my_product_array = array( 2494,2518,2483,2521,2520,2505,2491,2512,2511,2510,2509,2451,2446,2460,2455,2424,2437,2500,2504,2501,2472,2461,2440,2442,2445,2516,2448,2421,2412,2423,2433,2431,2429,2427,2436,2486,2482,2479,2478,2475,2474,2470,2444,2438 );//add in product IDs
      if ( in_array( $product_id, $my_product_array )) {
          $textafter = '/Month* <br> <span class="billed-quarterly">* billed quarterly</span> <div id="curbside-shop-desc">The total cost for setting up residential curbside service at your address. </div>'; //add your text
          return $price . '<span class="price-description">' . $textafter . '</span>';
      }
      
      else { 
          return $price; 
      } 
      
      }
      add_filter( 'woocommerce_get_price_html', 'themeprefix_custom_price_message' );
  22. How to add text before the price?

  23. Beka, I have to say you are becoming a hero to me!

    This worked beautifully to customize the Grouped Product price and show the discounted total instead of the single item cost (which is terribly confusing to customers). In hand with the Dynamic Cart Pricing plugin, this allows me to show the savings before the customer places the item in the cart – plus I snuck in the discounted percentage right next to the price.

    Simply awesome, worked first time – thank you so much! You’re making me want to learn php you know 😛

  24. How can this be done on the order email sent to admin?

  25. does this require an additional plugin? if not, where do you add “custom field”? I can’t find it :/

  26. I found out a simple plugin which does exactly this.
    Have been using it for some time now & it works perfectly.
    Here is the link if anyone need https://wordpress.org/plugins/woocommerce-extra-price-fields/

  27. Your code for “per package” is perfect for my needs. However, could you help to create filter that only adds “per package” after price for certain product categories?

  28. Hallo,
    how can I solve the font size of the price the product globally? the font size is too small for me!

    Daniela

  29. Hello Beka,
    Ive search all threads in stackoverflow, but could not find the exact solution..do you happen to know how to display total product price in cart page? im using WC()->cart->get_product_price but when the qty change and press the update button, the displayed price remain same as single. It does not reflect against the qty..thanks

  30. Hello Beka, can you help me with an update to the latest version of woocommerce?

    Thank you.

Hmm, looks like this article is quite old! Its content may be outdated, so comments are now closed.