I am trying to change product price in cart using the following function:
add_action( 'woocommerce_before_shipping_calculator', 'add_custom_price'
);
function add_custom_price( $cart_object ) {
foreach ( $cart_object->cart_contents as $key => $value ) {
$value['data']->price = 400;
}
}
It was working correctly in WooCommerce version 2.6.x but not working anymore in version 3.0+
How can I make it work in WooCommerce Version 3.0+?
Thanks.
Update 2021 (Handling mini cart custom item price)
With WooCommerce version 3.0+ you need:
To use woocommerce_before_calculate_totals hook instead.
To use WC_Cart get_cart() method instead
To use WC_product set_price() method instead
Here is the code:
// Set custom cart item price
add_action( 'woocommerce_before_calculate_totals', 'add_custom_price', 1000, 1);
function add_custom_price( $cart ) {
// This is necessary for WC 3.0+
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Avoiding hook repetition (when using price calculations for example | optional)
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item ) {
$cart_item['data']->set_price( 40 );
}
}
And for mini cart (update):
// Mini cart: Display custom price
add_filter( 'woocommerce_cart_item_price', 'filter_cart_item_price', 10, 3 );
function filter_cart_item_price( $price_html, $cart_item, $cart_item_key ) {
if( isset( $cart_item['custom_price'] ) ) {
$args = array( 'price' => 40 );
if ( WC()->cart->display_prices_including_tax() ) {
$product_price = wc_get_price_including_tax( $cart_item['data'], $args );
} else {
$product_price = wc_get_price_excluding_tax( $cart_item['data'], $args );
}
return wc_price( $product_price );
}
return $price_html;
}
Code goes in functions.php file of your active child theme (or active theme).
This code is tested and works (still works on WooCommerce 5.1.x).
Note: you can increase the hook priority from 20 to 1000 (or even 2000) when using some few specific plugins or others customizations.
Related:
Set cart item price from a hidden input field custom price in Woocommerce 3
Change cart item prices based on custom cart item data in Woocommerce
Set a specific product price conditionally on Woocommerce single product page & cart
Add a select field that will change price in Woocommerce simple products
With WooCommerce version 3.2.6, #LoicTheAztec's answer works for me if I increase the priority to 1000.
add_action( 'woocommerce_before_calculate_totals', 'add_custom_price', 1000, 1);
I tried priority values of 10,99 and 999 but the price and total in my cart did not change (even though I was able to confirm with get_price() that set_price() had actually set the price of the item.
I have a custom hook that adds a fee to my cart and I'm using a 3rd party plugin that adds product attributes. I suspect that these WooCommerce "add-ons" introduce delays that require me to delay my custom action.
Related
I'm trying to append text to WooCommerce product title in the order meta - if products has a specific tag. I'm working from
"Append text to product title if product has product-tag on cart in WooCommerce"
"Display custom payment field in Woocommerce Admin, Orders and emails"
This is what I have so fare:
add_filter( 'woocommerce_get_order_item_totals', 'add_udstilling_below_cart_item_name', 10, 3 );
function add_udstilling_below_cart_item_name( $total_rows, $order, $tax_display ) {;
$new_total_rows = [];
foreach($total_rows as $key => $total ){
$new_total_rows[$key] = $total;
}
}
return $new_total_rows;
}
Based on your previous question and this new question, I assume that you would like to see the product title adjusted 'everywhere'.
IMPORTANT!! You should definitely read the following post to
understand that this is a general adjustment, so that you ultimately
no longer need the code from your previous post / question
Changing WooCommerce cart item names
In other words, you can start using the code below to see the adjustment in the following places
Order-receive (Thank you) page,
email notifications
My Account Orders> Single order details
Cart & Checkout and Backend Order edit pages.
Now you have change the names everywhere except on Shop archives and product pages…
function add_udstilling_order_item_name( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item ) {
// Get an instance of the WC_Product object
$product = $cart_item['data'];
// Get product id
$product_id = $cart_item['product_id'];
if( method_exists( $product, 'set_name' ) && has_term( 'udstillingsmodel', 'product_tag', $product_id ) ) {
$product->set_name( $product->get_name() . '(test)' );
}
}
}
add_action( 'woocommerce_before_calculate_totals', 'add_udstilling_order_item_name', 10, 1 );
My WP site sells customized t-shirts. The customization plugin makes each customized shirt a line item in the woocommerce cart. If there are 2 shirts ordered of one design (quantity of 2 on that line item) I want to discount. But if there is just 1 item per line I dont want to discount.
I found this solution
Adding a discount by cart items conditionally based on the item quantity
But this seems to change the product price in the db, so after the discount kicks in for say 2 blue shirts because there were 2 ordered on 1 line, if I add a 3rd shirt on a separate line it also gets the discount, which I dont want.
Since woocommerce version 3+ the linked answer code doesn't work. It needs something different and can even be done in a better way.
The code will apply a cart item discount based on the cart item quantity. In this code example, it will apply a discount of 5% on the cart item, when the quatity is equal or more than 2 (two).
The cart item unit price displayed is always the real product price. The discount will be effective and displayed on the cart item subtotal.
Additionally the product name will be appended with a discount mention.
The code:
add_filter('woocommerce_add_cart_item_data', 'add_items_default_price_as_custom_data', 20, 3 );
function add_items_default_price_as_custom_data( $cart_item_data, $product_id, $variation_id ){
$product_id = $variation_id > 0 ? $variation_id : $product_id;
## ----- YOUR SETTING ----- ##
$discount_percentage = 5; // Discount (5%)
// The WC_Product Object
$product = wc_get_product($product_id);
// Only for non on sale products
if( ! $product->is_on_sale() ){
$price = (float) $product->get_price();
// Set the Product default base price as custom cart item data
$cart_item_data['base_price'] = $price;
// Set the Product discounted price as custom cart item data
$cart_item_data['new_price'] = $price * (100 - $discount_percentage) / 100;
// Set the percentage as custom cart item data
$cart_item_data['percentage'] = $discount_percentage;
}
return $cart_item_data;
}
// Display the product original price
add_filter('woocommerce_cart_item_price', 'display_cart_items_default_price', 20, 3 );
function display_cart_items_default_price( $product_price, $cart_item, $cart_item_key ){
if( isset($cart_item['base_price']) ) {
$product = $cart_item['data'];
$product_price = wc_price( wc_get_price_to_display( $product, array( 'price' => $cart_item['base_price'] ) ) );
}
return $product_price;
}
// Display the product name with the discount percentage
add_filter( 'woocommerce_cart_item_name', 'append_percetage_to_item_name', 20, 3 );
function append_percetage_to_item_name( $product_name, $cart_item, $cart_item_key ){
if( isset($cart_item['percentage']) && isset($cart_item['base_price']) ) {
if( $cart_item['data']->get_price() != $cart_item['base_price'] )
$product_name .= ' <em>(' . $cart_item['percentage'] . '% discounted)</em>';
}
return $product_name;
}
add_action( 'woocommerce_before_calculate_totals', 'custom_discounted_cart_item_price', 20, 1 );
function custom_discounted_cart_item_price( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
## ----- YOUR SETTING ----- ##
$targeted_qty = 2; // Targeted quantity
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item ) {
// For item quantity of 2 or more
if( $cart_item['quantity'] >= $targeted_qty && isset($cart_item['new_price']) ){
// Set cart item discounted price
$cart_item['data']->set_price($cart_item['new_price']);
}
}
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
To display the discounted product price instead of the original product price, just remove woocommerce_cart_item_price() function (and hook)…
Newest similar: Cart item quantity progressive percentage discount in Woocommerce 3
I have a function on my Woocommerce website that enables customers to set a custom amount to pay for a specific product, based on a value I'm passing through the URL.
I'm using the woocommerce_before_calculate_totals hook, and up until I upgraded to WC 3.3.5, it was working fine. Now, when I run the code, the checkout initially shows the custom amount.
However, once the loader has finished updating, it resets the price to '0' (i.e. displaying £0.00 the checkout page's total fields).
Here's that code:
add_action( 'woocommerce_before_calculate_totals', 'pay_custom_amount', 99);
function pay_custom_amount() {
$payment_value = $_GET['amount'];
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
if($cart_item['data']->id == 21 ){
$cart_item['data']->set_price($payment_value);
}
}
}
Well, colour me baffled. I've trawled Stack Overflow for solutions but can't see any similar problems. I see the hook runs multiple times but gather this is normal.
If anyone know what might be happening here, it would be great if you could share.
You can't get a price from an URL and set it in woocommerce_before_calculate_totals action hook. This needs to be done differently.
In the below code:
the first hooked function will get that "amount" from the URl and will set it (register it) in cart item object as custom data.
the 2nd hooked function will read that amount from custom cart item data and will set it as the new price.
Now your the target product ID in your code need to be the same ID that the added to cart product.
The code:
// Get the custom "amount" from URL and save it as custom data to the cart item
add_filter( 'woocommerce_add_cart_item_data', 'add_pack_data_to_cart_item_data', 20, 2 );
function add_pack_data_to_cart_item_data( $cart_item_data, $product_id ){
if( ! isset($_GET['amount']) )
return $cart_item_data;
$amount = esc_attr( $_GET['amount'] );
if( empty($amount) )
return $cart_item_data;
// Set the custom amount in cart object
$cart_item_data['custom_price'] = (float) $amount;
$cart_item_data['unique_key'] = md5( microtime() . rand() ); // Make each item unique
return $cart_item_data;
}
// Alter conditionally cart item price based on product ID and custom registered "amount"
add_action( 'woocommerce_before_calculate_totals', 'change_conditionally_cart_item_price', 30, 1 );
function change_conditionally_cart_item_price( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
// HERE set your targeted product ID
$targeted_product_id = 21;
foreach ( $cart->get_cart() as $cart_item ) {
// Checking for the targeted product ID and the registered "amount" cart item custom data to set the new price
if($cart_item['data']->get_id() == $targeted_product_id && isset($cart_item['custom_price']) )
$cart_item['data']->set_price($cart_item['custom_price']);
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
I need to double the price for every product in Woocommerce frontend. For this I used the following code:
add_filter( 'woocommerce_product_get_price', 'double_price', 10, 2 );
function double_price( $price, $product ){
return $price*2;
}
But there is an error using this code. checkout page price is not correct.
for example the product orginal price is 10. We double the price by this code . so the product price is 20 now. When i added this product to the cart then cart and checkout page price is 40. That means this multiplication is take place in two times.
Please help to solve this.
Updated To double the price:
1) First you will restrict your code to single product and archives pages only:
add_filter( 'woocommerce_product_get_price', 'double_price', 10, 2 );
function double_price( $price, $product ){
if( is_shop() || is_product_category() || is_product_tag() || is_product() )
return $price*2;
return $price;
}
2) Then for cart and checkout pages, you will change the cart item price this way:
add_filter( 'woocommerce_add_cart_item', 'set_custom_cart_item_prices', 20, 2 );
function set_custom_cart_item_prices( $cart_data, $cart_item_key ) {
// Price calculation
$new_price = $cart_data['data']->get_price() * 2;
// Set and register the new calculated price
$cart_data['data']->set_price( $new_price );
$cart_data['new_price'] = $new_price;
return $cart_data;
}
add_filter( 'woocommerce_get_cart_item_from_session', 'set_custom_cart_item_prices_from_session', 20, 3 );
function set_custom_cart_item_prices_from_session( $session_data, $values, $key ) {
if ( ! isset( $session_data['new_price'] ) || empty ( $session_data['new_price'] ) )
return $session_data;
// Get the new calculated price and update cart session item price
$session_data['data']->set_price( $session_data['new_price'] );
return $session_data;
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Tested and working. It will change all prices as you expect in cart, checkout and order pages…
I am trying to change product price in cart using the following function:
add_action( 'woocommerce_before_shipping_calculator', 'add_custom_price'
);
function add_custom_price( $cart_object ) {
foreach ( $cart_object->cart_contents as $key => $value ) {
$value['data']->price = 400;
}
}
It was working correctly in WooCommerce version 2.6.x but not working anymore in version 3.0+
How can I make it work in WooCommerce Version 3.0+?
Thanks.
Update 2021 (Handling mini cart custom item price)
With WooCommerce version 3.0+ you need:
To use woocommerce_before_calculate_totals hook instead.
To use WC_Cart get_cart() method instead
To use WC_product set_price() method instead
Here is the code:
// Set custom cart item price
add_action( 'woocommerce_before_calculate_totals', 'add_custom_price', 1000, 1);
function add_custom_price( $cart ) {
// This is necessary for WC 3.0+
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Avoiding hook repetition (when using price calculations for example | optional)
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item ) {
$cart_item['data']->set_price( 40 );
}
}
And for mini cart (update):
// Mini cart: Display custom price
add_filter( 'woocommerce_cart_item_price', 'filter_cart_item_price', 10, 3 );
function filter_cart_item_price( $price_html, $cart_item, $cart_item_key ) {
if( isset( $cart_item['custom_price'] ) ) {
$args = array( 'price' => 40 );
if ( WC()->cart->display_prices_including_tax() ) {
$product_price = wc_get_price_including_tax( $cart_item['data'], $args );
} else {
$product_price = wc_get_price_excluding_tax( $cart_item['data'], $args );
}
return wc_price( $product_price );
}
return $price_html;
}
Code goes in functions.php file of your active child theme (or active theme).
This code is tested and works (still works on WooCommerce 5.1.x).
Note: you can increase the hook priority from 20 to 1000 (or even 2000) when using some few specific plugins or others customizations.
Related:
Set cart item price from a hidden input field custom price in Woocommerce 3
Change cart item prices based on custom cart item data in Woocommerce
Set a specific product price conditionally on Woocommerce single product page & cart
Add a select field that will change price in Woocommerce simple products
With WooCommerce version 3.2.6, #LoicTheAztec's answer works for me if I increase the priority to 1000.
add_action( 'woocommerce_before_calculate_totals', 'add_custom_price', 1000, 1);
I tried priority values of 10,99 and 999 but the price and total in my cart did not change (even though I was able to confirm with get_price() that set_price() had actually set the price of the item.
I have a custom hook that adds a fee to my cart and I'm using a 3rd party plugin that adds product attributes. I suspect that these WooCommerce "add-ons" introduce delays that require me to delay my custom action.