Change Cart Item Prices Based on Custom Cart Item Data in Woocommerce

Change WooCommerce cart item price based on a custom field and quantity threshold

In your code $variation_data['variation_id'] is not defined as $variation_data doesn't exist for woocommerce_before_calculate_totals hook… Try the following instead:

add_action( 'woocommerce_before_calculate_totals', 'quantity_based_bulk_pricing', 9999, 1 );
function quantity_based_bulk_pricing( $cart ) {

if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;

if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;

// Define the quantity threshold
$qty_threshold = 6;

// Loop through cart items
foreach( $cart->get_cart() as $cart_item_key => $cart_item ) {
// Get the bulk price from product (variation) custom field
$bulk_price = (float) $cart_item['data']->get_meta('bulk_price');

// Check if item quantity has reached the defined threshold
if( $cart_item['quantity'] >= $qty_threshold && $bulk_price > 0 ) {
// Set the bulk price
$cart_item['data']->set_price( $bulk_price );
}
}
}

Code goes in functions.php file of your active child theme (or active theme). It should works.

Change cart item prices based on custom cart item data in Woocommerce

You need to use 2 different hooks:

  • The first one just as yours without trying to change the price in it.
  • The second one where you will change your cart item price

The code:

add_filter( 'woocommerce_add_cart_item', 'add_custom_cart_item_data', 10, 2 );
function add_custom_cart_item_data( $cart_item_data, $cart_item ) {

if( isset( $_POST['new-width'] ) )
$cart_item_data['new-width'] = $_POST['new-width'];
if(isset( $_POST['new-height'] ) )
$cart_item_data['new-height'] = $_POST['new-height'];

return $cart_item_data;
}

add_action( 'woocommerce_before_calculate_totals', 'set_custom_cart_item_price', 20, 1 );
function set_custom_cart_item_price( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;

if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;

// First loop to check if product 11 is in cart
foreach ( $cart->get_cart() as $cart_item ){
if( isset($cart_item['new-width']) && isset($cart_item['new-height'])
&& ! empty($cart_item['new-width']) && ! empty($cart_item['new-height']) )
$cart_item['data']->set_price( '30' );
}
}

Code goes in function.php file of your active child theme (or theme) or also in any plugin file.

Tested and works

Issue with changing WooCommerce cart item prices based on product meta

The woocommerce_cart_item_name hook is being misused in your code attempt. A filter hook should always return something compared to the use of echo.

You should use the woocommerce_before_calculate_totals hook instead

So you get:

function action_woocommerce_before_calculate_totals( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;

if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return;

// Change price if > 3000
$threshold = 3000;

// Loop through cart items
foreach ( $cart->get_cart() as $cart_item ) {
// Get regular price
$price = $cart_item['data']->get_regular_price();

// Subtotal = Get quantity * price
$subtotal = $cart_item['quantity'] * $price;

// Greater than
if ( $subtotal > $threshold ) {
// Get meta
$meta = $cart_item['data']->get_meta( '_opt_price_var', true );

// NOT empty
if ( ! empty ( $meta ) ) {
// Set new price
$cart_item['data']->set_price( $meta );
}
}
}
}
add_action( 'woocommerce_before_calculate_totals', 'action_woocommerce_before_calculate_totals', 10, 1 );

Increase cart item prices based on payment method in WooCommerce

There are some mistakes in your code

  • Use WC()->session->get( 'chosen_payment_method' ); outside the foreach loop
  • get_post_meta() is not needed to get the price, you can use get_price()
  • You will also need jQuery that is triggered when changing the payment method.

So you get:

function action_woocommerce_before_calculate_totals( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;

if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;

// Get payment method
$chosen_payment_method = WC()->session->get( 'chosen_payment_method' );

// Compare
if ( $chosen_payment_method == 'cod' ) {
$increaseby = 3;
} elseif ( $chosen_payment_method == 'paypal' ) {
$increaseby = 8;
} else {
$increaseby = 10;
}

// Loop through cart items
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
// Get price
$price = $cart_item['data']->get_price();

// Set price
$cart_item['data']->set_price( $price + ( $price * $increaseby ) / 100 );
}
}
add_action( 'woocommerce_before_calculate_totals', 'action_woocommerce_before_calculate_totals', 10, 1 );

function action_wp_footer() {
if ( is_checkout() && ! is_wc_endpoint_url() ) :
?>
<script type="text/javascript">
jQuery(function($){
$( 'form.checkout' ).on( 'change', 'input[name="payment_method"]', function() {
$(document.body).trigger( 'update_checkout' );
});
});
</script>
<?php
endif;
}
add_action( 'wp_footer', 'action_wp_footer' );

Change cart item prices in Woocommerce 3

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

How to set custom product price after add to cart in WooCommerce?

You used woocommerce_add_cart_item_data to add custom meta is right but you didn't set custom price to product price.

function wdm_add_item_data( $cart_item_data, $product_id ) {

$cart_item_data[ "_custom_options" ] = 678
return $cart_item_data;
}
add_filter( 'woocommerce_add_cart_item_data', 'wdm_add_item_data', 10, 2 );

Use the woocommerce_before_calculate_totals action hook to set
custom price to product in the cart.

function woocommerce_custom_price_to_cart_item( $cart_object ) {  
foreach ( $cart_object->cart_contents as $key => $value ) {
if( isset( $value["_custom_options"] ) ) {
$value['data']->set_price($value["_custom_options"]);
}
}
}
add_action( 'woocommerce_before_calculate_totals', 'woocommerce_custom_price_to_cart_item', 10 );

Customize cart item subtotal based on custom cart item data in Woocommerce

You are not doing that in the right way and you need to rethink it differently…

Here is a complete example that will allow you to keep the default item price (product price) and to get a calculated cart item subtotal based on your "length" custom cart item data:

// For testing (example): Add a dropdown to product page for lenght
add_action( 'woocommerce_before_add_to_cart_button', 'add_lenght_custom_field');
function add_lenght_custom_field() {
echo '<div class="class_dropdown_length">
<label for="rope_length">Select a length</label>
<select id ="rope_length" name="rope_length">
<option value="">1 m</option>
<option value="5">5 m</option>
<option value="10">10 m</option>
<option value="25">25 m</option>
</select>
</div>';
}

// Add custom cart item data (lenght) on add to cart and calculate the new price
add_filter( 'woocommerce_add_cart_item_data', 'filter_woocommerce_add_cart_item_data', 10, 3 );
function filter_woocommerce_add_cart_item_data( $cart_item_data, $product_id, $variation_id) {
if( isset($_POST['rope_length']) && ! empty($_POST['rope_length']) ) {
$the_id = $variation_id > 0 ? $variation_id : $product_id;

$product = wc_get_product( $the_id );

$length = (float) esc_attr($_POST['rope_length']); // The chosen lenght

// Add the dropdown value as custom cart item data
$cart_item_data['custom'] = array(
'length' => $length, // The lenght value from custom field (if needed)
'price' => $product->get_price(), // The default product price
'new_price' => $product->get_price() * $length, // Calculated price from lenght
'unique_key' => md5(microtime().rand()), // Make each item unique
);
}
return $cart_item_data;
}

// Display the selected lenght value below cart item name
add_filter( 'woocommerce_cart_item_name', 'display_select_length_after_cart_item_name', 10, 3 );
function display_select_length_after_cart_item_name( $name, $cart_item, $cart_item_key ) {
if( is_cart() && isset($cart_item['custom']['length']) ) {
$name .= '<p>'.__("Lenght:") . ' ' . esc_html($cart_item['custom']['length']) . '</p>';
}
return $name;
}

// Display the default product price (instead of the calculated one)
add_filter( 'woocommerce_cart_item_price', 'filter_woocommerce_cart_item_price', 10, 3 );
function filter_woocommerce_cart_item_price( $product_price, $cart_item, $cart_item_key ) {
if( isset($cart_item['custom']['price']) ) {
$product_price = wc_price( wc_get_price_to_display( $cart_item['data'], array('price' => $cart_item['custom']['price']) ) );
}
return $product_price;
}

// Customizing cart item price subtotal
add_action( 'woocommerce_before_calculate_totals', 'set_cart_item_calculated_price', 10, 1 );
function set_cart_item_calculated_price( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;

// Required since Woocommerce version 3.2 for cart items properties changes
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;

// Loop through cart items
foreach ( $cart->get_cart() as $cart_item ) {
// Set the new calculated price based on lenght
if( isset($cart_item['custom']['new_price']) ) {
$cart_item['data']->set_price( $cart_item['custom']['new_price'] );
}
}
}

This code goes in function.php file of your active child theme (or active theme). Tested and works.

You can see that the product price is different that the custom calculated subtotal (price x length):

Sample Image

Display and save added custom cart item data on Woocommerce Cart, Checkout and Orders

To display and save custom meta data added to cart in cart, checkout and orders when using:

WC()->cart->add_to_cart( $product_id ,1,  0,array(), array('add_size' => array('PR CODE'=>'1.0') );

You will use the following code:

// Display custom cart item meta data (in cart and checkout)
add_filter( 'woocommerce_get_item_data', 'display_cart_item_custom_meta_data', 10, 2 );
function display_cart_item_custom_meta_data( $item_data, $cart_item ) {
$meta_key = 'PR CODE';
if ( isset($cart_item['add_size']) && isset($cart_item['add_size'][$meta_key]) ) {
$item_data[] = array(
'key' => $meta_key,
'value' => $cart_item['add_size'][$meta_key],
);
}
return $item_data;
}

// Save cart item custom meta as order item meta data and display it everywhere on orders and email notifications.
add_action( 'woocommerce_checkout_create_order_line_item', 'save_cart_item_custom_meta_as_order_item_meta', 10, 4 );
function save_cart_item_custom_meta_as_order_item_meta( $item, $cart_item_key, $values, $order ) {
$meta_key = 'PR CODE';
if ( isset($values['add_size']) && isset($values['add_size'][$meta_key]) ) {
$item->update_meta_data( $meta_key, $values['add_size'][$meta_key] );
}
}

Code goes in function.php file of your active child theme (or active theme). Tested and works.

Example display on Cart (and Checkout) pages:

Sample Image

Example display on Orders (and email notifications):

Sample Image



Related Topics



Leave a reply



Submit