I applied a 5% discount to the Woocommerce cart, based on cart amount and shipping method, which seems to be working fine. But I cannot manage to change the shipping method title when the rule applies, i need to add a message "5% discount" to all local-pickup methods.
I found a workarround using conditional shipping, but that won´t work in this website, I need to use the same method, but adding a message to the title.
Any ideas?
This is my code:
function local_pickup_discount( $cart ) {
$chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
$carrito_total = WC()->cart->get_cart_contents_total();
$chosen_shipping_no_ajax = $chosen_methods[0];
if ( 0 === strpos( $chosen_shipping_no_ajax, 'local_pickup' ) && $carrito_total < 60000) {
$discount = $cart->subtotal * 0.05; // 5% discount applied here
$cart->add_fee( __( 'Descuento por retiro en sucursal', 'yourtext-domain' ) , -$discount ); // Fee descripton
}
}
add_action( 'woocommerce_cart_calculate_fees', 'local_pickup_discount');
Thanks in advance, i know this must be a very simple thing to do, but i am not used to work with php.
You have to use this hook to rename your label woocommerce_cart_shipping_method_full_label. Inside you can apply any conditional logic you want and output label with custom one.
Note: This label is used in both cart and checkout. So if you want it only on checkout add condition is_checkout() or is_cart() if you want to limit it.
function wc_change_local_pickup_label( $label, $method ) {
$carrito_total = WC()->cart->get_cart_contents_total();
if ( $carrito_total < 60000 && 'local_pickup' === $method->method_id) {
$label = "Local pickup 5% discount";
}
return $label;
}
add_filter( 'woocommerce_cart_shipping_method_full_label', 'wc_change_local_pickup_label', 10, 2 );
Related
Currently, our store offers "Free Shipping up to $350", after thought on how to incorporate this into eCom - I believe this will be the simplest method. Fetch Shipping Cost --> IF Shipping Costs > $350 --> Apply "350-shipping" coupon code.
We use 2 different plugins to calculate shipping:
1.) WooCommerce FedEx Shipping
2.) WooCommerce WWE LTL Quotes
Looking to incorporate this inside of functions.php. Note, I am also working on a solution, so will apply here if I get to it sooner
Notice here the correct code for the Shipping Page: https://i.imgur.com/TndLiHT.png
So far I have the following:
// $350 Shipping Coupon
add_filter( 'woocommerce_package_rates', 'custom_shipping_rate_label_based_on_cost', 100, 2 );
function custom_shipping_rate_label_based_on_cost( $rates, $package ){
// Loop through available shipping rates
foreach ( $rates as $rate_key => $rate ) {
$rate_cost = $rate->cost;
if ( $rate_cost > 350 ) {
echo "<script type='text/javascript'>alert('350 Detected');</script>";
}
}
return $rates;
}
What is missing here is I need to say:
IF ALL Items in Foreach are greater than $350. Right now, if I run this script, I get an endless loop of "350 detected"
add_action( 'woocommerce_after_calculate_totals', 'apply_coupon_depending_on_shipping_total', 999, 1 );
function apply_coupon_depending_on_shipping_total( $cart ) {
$coupon_code = 'coupon_code';
if ( $cart->has_discount( $coupon_code ) ) {
return;
}
$shipping_total = $cart->get_shipping_total();
if ( $shipping_total > 350 ) {
$cart->apply_coupon( $coupon_code );
}
}
In Woocommerce I have the following situation: there are shipping methods before 100$, and after 100$ only one (free shipping) is available. So when a client buys a product 102$ and then apply the (10%) promo code, the price will be 91,80$. Because I unset the shipping methods after 100$ and the free shipping appears after 100$ only, for the client shows: "There are no shipping methods available..."
add_filter( 'woocommerce_package_rates', 'woocommerce_hide_shipping', 10, 2 );
function woocommerce_hide_shipping( $rates, $package ) {
$threshold = 100;
if ( WC()->cart->subtotal >= $threshold ) {
unset( $rates['flat_rate:45'] );
unset( $rates['flat_rate:75'] );
}
if ( WC()->cart->subtotal >= $threshold && !empty(WC()->cart->applied_coupons) ) {
//code here
}
return $rates;
}
Its possible to show the free shipping if the price was >100$ before promo code and a coupon was applied? I set up the free shipping to show a minimum order amount (100$) but there is a way to show, initialize? Other approaches are also welcomed.
The problem is.... Free Shipping that you have applied is bounded by min order and that is referring to order total (NOT SUBTOTAL).....
Whereas subtotal gives you the value without discount.
So,
Remove condition (min order total) from your Admin settings - Free shipping.... Now it will work for every order...
Then modify your code ---
add_filter( 'woocommerce_package_rates', 'woocommerce_hide_shipping', 10, 2 );
function woocommerce_hide_shipping( $rates, $package ) {
$threshold = 100;
if ( WC()->cart->subtotal >= $threshold ) {
unset( $rates['flat_rate:45'] );
unset( $rates['flat_rate:75'] );
}
if ( WC()->cart->subtotal < $threshold ) {
//code here
unset( $rates['free_shipping:45'] );
unset( $rates['free_shipping:75'] );
}
return $rates;
}
I want to add custom % value at woocommerce checkout page, but I want to show it only for Swiss country and hide it for others. Now I have the right code working for that, but the problems is that Im not able to show it when user choose switzerland. Here is a code so please help me see what Im doing wrong here
//Add tax for CH country
add_action( 'woocommerce_cart_calculate_fees','woocommerce_custom_surcharge' );
function woocommerce_custom_surcharge() {
global $woocommerce;
if ( WC()->customer->get_shipping_country('CH') )
return;
$percentage = 0.08;
$taxes = array_sum($woocommerce->cart->taxes);
$surcharge = ( $woocommerce->cart->cart_contents_total + $woocommerce->cart->shipping_total ) * $percentage;
// Make sure that you return false here. We can't double tax people!
$woocommerce->cart->add_fee( 'TAX', $surcharge, false, '' );
}
Im sure Im doing wrong inside here:
if ( WC()->customer->get_shipping_country('CH') )
thanks for help
The WC_Customer get_shipping_country() doesn't accept any country code as you are getting a country code. So you need to set it differently in your code condition.
Also as your hooked function has already the WC_Cart object as argument, you don't need global $woocommerce and $woocommerce->cart…
So your revisited code should be:
// Add tax for Swiss country
add_action( 'woocommerce_cart_calculate_fees','custom_tax_surcharge_for_swiss', 10, 1 );
function custom_tax_surcharge_for_swiss( $cart ) {
if ( is_admin() && ! defined('DOING_AJAX') ) return;
// Only for Swiss country (if not we exit)
if ( 'CH' != WC()->customer->get_shipping_country() ) return;
$percent = 8;
# $taxes = array_sum( $cart->taxes ); // <=== This is not used in your function
// Calculation
$surcharge = ( $cart->cart_contents_total + $cart->shipping_total ) * $percent / 100;
// Add the fee (tax third argument disabled: false)
$cart->add_fee( __( 'TAX', 'woocommerce')." ($percent%)", $surcharge, false );
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Tested and works… you will get something like:
But for taxes, you should better use default WooCommerce tax feature in Settings > Tax (tab), where con can set the tax rates for each country…
I have created a product on WooCommerce, and added two options on product detail page using the hook woocommerce_before_add_to_cart_button. Now when customers add product to cart from product detail page they have two options their. They can choose one option from these two options.
Then I have stored the user selected value in cart meta using the woocommerce hook woocommerce_add_cart_item_data.
I am using the code from this answer: Save product custom field radio button value in cart and display it on Cart page
This is my code:
// single Product Page options
add_action("woocommerce_before_add_to_cart_button", "options_on_single_product");
function options_on_single_product(){
$dp_product_id = get_the_ID();
$product_url = get_permalink($dp_product_id);
?>
<input type="radio" name="custom_options" checked="checked" value="option1"> option1<br />
<input type="radio" name="custom_options" value="option2"> option2
<?php
}
//Store the custom field
add_filter( 'woocommerce_add_cart_item_data', 'save_custom_data_with_add_to_cart', 10, 2 );
function save_custom_data_with_add_to_cart( $cart_item_meta, $product_id ) {
global $woocommerce;
$cart_item_meta['custom_options'] = $_POST['custom_options'];
return $cart_item_meta;
}
And this is what I have tried:
add_action( 'woocommerce_before_calculate_totals', 'add_custom_price', 10, 1);
function add_custom_price( $cart_obj ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
foreach ( $cart_obj->get_cart() as $key => $value ) {
$product_id = $value['product_id'];
$custom_options = $value['custom_options'];
$coupon_code = $value['coupon_code'];
if($custom_options == 'option2')
{
if($coupon_code !='')
{
global $woocommerce;
if ( WC()->cart->has_discount( $coupon_code ) ) return;
(WC()->cart->add_discount( $coupon_code ))
//code for second discount
}
else{
$percentage = get_post_meta( $product_id , 'percentage', true );
//print_r($value);
$old_price = $value['data']->regular_price;
$new_price = ($percentage / 100) * $old_price;
$value['data']->set_price( $new_price );
}
}
}
}
Now what I am trying to get with that last snippet is:
If Option1 is selected by the customer then woocommerce regular process is run.
If Option2 is selected then firstly coupon code applied to cart (if code entered by the customer) and then the price is divide by some percentage (stored in product meta) is applied afterward.
But it’s not working as expected because the changed product price is maid before and coupon discount is applied after on this changed price.
What I would like is that the coupon discount will be applied first on the product regular price and then after change this price with my custom product discount.
Is this possible? How can I achieve that?
Thanks.
This is not really possible … Why? … Because (the logic):
You have the product price
Then the coupon discount is applied to that price (afterwards)
==> if you change the product price, the coupon is will be applied to that changed price
What you can do instead:
You don't change product price
if entered the coupon is applied and …
If "option2" product is added to cart:
Apply a custom discount (a negative fee) based on the product price added after using WC_cart add_fee() method…
For this last case you will have to fine tune your additional discount.
If the coupon has not been applied or it's removed there is no additional discount.
Your custom function will be hooked in woocommerce_cart_calculate_fees action hook instead:
add_action( 'woocommerce_cart_calculate_fees', 'option2_additional_discount', 10, 1 );
function option2_additional_discount( $cart_obj ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
$discount = 0;
$applied_coupons = $cart_obj->get_applied_coupons();
foreach ( $cart_obj->get_cart() as $item_values ) {
if( 'option2' == $item_values['custom_options'] && !empty($applied_coupons) ){
$product_id = $item_values['product_id'];
$percentage = get_post_meta( $product_id , 'percentage', true );
$quantity = $item_values['quantity'];
$product_reg_price = $item_values['data']->regular_price;
$line_total = $item_values['line_total'];
$line_subtotal = $item_values['line_subtotal'];
$percentage = 90;
## ----- CALCULATIONS (To Fine tune) ----- ##
$item_discounted_price = ($percentage / 100) * $product_reg_price * $item_values['quantity'];
// Or Besed on line item subtotal
$discounted_price = ($percentage / 100) * $line_subtotal;
$discount += $product_reg_price - $item_discounted_price;
}
}
if($discount != 0)
$cart_obj->add_fee( __( 'Option2 discount', 'woocommerce' ) , - $discount );
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested and works.
Adding a negative fee using the WC_Cart->add_fee() method wasn't working for me. When i check the WC Cart class, it even states you are not allowed to use a negative ammount.
See the docs.
I did the following:
create a placeholder coupon with a 'secure' code, e.g. custom_discount_fjgndfl28. Set a discount ammount of 0, so when somebody (somehow) uses this coupon outside your program the discount is still 0.
Use filter woocommerce_get_shop_coupon_data, and set all the coupon data you want for that coupon/session.
Hook into woocommerce_before_calculate_totals and set your custom coupon to the cart.
At this point the Cart should calculate everything correctly. And when it becomes an order, it also has the correct discount ammount.
Note: the coupon code is also used as a label in some templates. Use filter woocommerce_cart_totals_coupon_label to change it.
Example functions:
/**
* NOTE: All the hooks and filters below have to be called from your own
* does_it_need_custom_discount() function. I used the 'wp' hook for mine.
* Do not copy/paste this to your functions.php.
**/
add_filter('woocommerce_get_shop_coupon_data', 'addVirtualCoupon', 10, 2);
function addVirtualCoupon($unknown_param, $curr_coupon_code) {
if($curr_coupon_code == 'custom_discount_fjgndfl28') {
// possible types are: 'fixed_cart', 'percent', 'fixed_product' or 'percent_product.
$discount_type = 'fixed_cart';
// how you calculate the ammount and where you get the data from is totally up to you.
$amount = $get_or_calculate_the_coupon_ammount;
if(!$discount_type || !$amount) return false;
$coupon = array(
'id' => 9999999999 . rand(2,9),
'amount' => $amount,
'individual_use' => false,
'product_ids' => array(),
'exclude_product_ids' => array(),
'usage_limit' => '',
'usage_limit_per_user' => '',
'limit_usage_to_x_items' => '',
'usage_count' => '',
'expiry_date' => '',
'apply_before_tax' => 'yes',
'free_shipping' => false,
'product_categories' => array(),
'exclude_product_categories' => array(),
'exclude_sale_items' => false,
'minimum_amount' => '',
'maximum_amount' => '',
'customer_email' => '',
'discount_type' => $discount_type,
);
return $coupon;
}
}
add_action('woocommerce_before_calculate_totals', 'applyFakeCoupons');
function applyFakeCoupons() {
global $woocommerce;
// $woocommerce->cart->remove_coupons(); remove existing coupons if needed.
$woocommerce->cart->applied_coupons[] = $this->coupon_code;
}
add_filter( 'woocommerce_cart_totals_coupon_label', 'cart_totals_coupon_label', 100, 2 );
function cart_totals_coupon_label($label, $coupon) {
if($coupon) {
$code = $coupon->get_code();
if($code == 'custom_discount_fjgndfl28') {
return 'Your custom coupon label';
}
}
return $label;
}
Please Note: i copied these functions out of a class that handles much more, it's only to help you get going.
I am trying to make a simple discount code for WooCommerce that gives you a percent discount before buying. Lets say that if you add products worth $100 you get 2% discount and if you add products worth $250 you get 4%, etc.
The only thing I found was this:
// Hook before calculate fees
add_action('woocommerce_cart_calculate_fees' , 'add_custom_fees');
/**
* Add custom fee if more than three article
* #param WC_Cart $cart
*/
function add_custom_fees( WC_Cart $cart ){
if( $cart->cart_contents_count < 3 ){
return;
}
// Calculate the amount to reduce
$discount = $cart->subtotal * 0.1;
$cart->add_fee( 'You have more than 3 items in your cart, a 10% discount has been added.', -$discount);
}
But could not manage to make it work with the modifying the hooks with those for the price.
How can I achieve this?
Here is the way to do it using conditions based on cart subtotal excl tax amount to add this progressive percentage as a negative fee, so a discount:
add_action( 'woocommerce_cart_calculate_fees','cart_price_progressive_discount' );
function cart_price_progressive_discount() {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
$has_discount = false;
$stotal_ext = WC()->cart->subtotal_ex_tax;
// Discount percent based on cart amount conditions
if( $stotal_ext >= 100 && $stotal_ext < 250 ) {
$percent = -0.02;
$percent_text = ' 2%';
$has_discount =true;
} elseif( $stotal_ext >= 250 ) {
$percent = -0.04;
$percent_text = ' 4%';
$has_discount =true;
}
// Calculation
$discount = $stotal_ext * $percent;
// Displayed text
$discount_text = __('Discount', 'woocommerce') . $percent_text;
if( $has_discount ) {
WC()->cart->add_fee( $discount_text, $discount, false );
}
// Last argument in add fee method enable tax on calculation if "true"
}
This goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested and works.
Similar: WooCommerce - Conditional Progressive Discount based on number of items in cart
Reference: WooCommerce class - WC_Cart - add_fee() method