I am using this official woocommerce hook and snippet to Hide other shipping methods when “Free Shipping” is triggered by a coupon. Which works fine.
Currnently, it just displays FREE SHIPPING. I am trying to add in a text line where it displays FREE SHIPPING to say "-£3.95" in order to let the user know that they have saved money off their shipping.
I have tried adding a dummy "fee" inline to the IF statement, but it wont display.
$cart->add_fee( 'You saved -£3.95');
Code is as follows:
function my_hide_shipping_when_free_is_available( $rates ) {
$free = array();
foreach ( $rates as $rate_id => $rate ) {
if ( 'free_shipping' === $rate->method_id ) {
$free[ $rate_id ] = $rate;
break;
}
}
return ! empty( $free ) ? $free : $rates;
}
add_filter( 'woocommerce_package_rates', 'my_hide_shipping_when_free_is_available', 100 );
e.g. like the following example:
There is 2 ways:
1) In your existing code (best way) - It will append your formatted saved price on free shipping:
add_filter( 'woocommerce_package_rates', 'hide_other_shipping_when_free_is_available', 100, 1 );
function hide_other_shipping_when_free_is_available( $rates ) {
// Here set your saved amount
$labeleld_price = -3.95;
$free = array();
foreach ( $rates as $rate_id => $rate ) {
if ( 'free_shipping' === $rate->method_id ) {
$free[ $rate_id ] = $rate;
// Here we append the labbelled saved price formated display
$free[ $rate_id ]->label .= ' (' . strip_tags( wc_price( $labeleld_price ) ) . ')';
break; // stop the loop
}
}
return ! empty( $free ) ? $free : $rates;
}
Code goes in function.php file of your active child theme (or active theme). tested and works.
2) Using settings - Renaming the "Free shipping" label method:
Related
I am trying to hide a shipping method on the checkout page of WooCommerce when shipping country selected is United States - 'US' and cart_total is more than 100. But the script is still hiding both the Normal Shipping and Express shipping, when it should only hide the normal shipping(flat_rate:4). Any help will be greatly appreciated!
function nd_hide_shipping_when_free_is_available( $rates ) {
$shipping_counrtry = WC()->customer->get_shipping_country();
$total = WC()->cart->get_displayed_subtotal();
if ($shipping_country == "US" && $total >= 100){
unset($rates['flat_rate:4']);
return $rates;
}else{
$free = array();
foreach ( $rates as $rate_id => $rate ) {
if ( 'free_shipping' === $rate->method_id ) {
$free[ $rate_id ] = $rate;
break;
}
}
return ! empty( $free ) ? $free : $rates;
}
}
add_filter( 'woocommerce_package_rates', 'nd_hide_shipping_when_free_is_available', 100 );
You can try the following, that will hide 'flat_rate:4' shipping method rate id for US and when cart subtotal reaches 100 or more, otherwise when free shipping is available, it will hide other shipping methods:
add_filter( 'woocommerce_package_rates', 'shipping_based_on_country_subtotal_and_free_available', 100, 2 );
function shipping_based_on_country_subtotal_and_free_available( $rates, $package ) {
$country = WC()->customer->get_shipping_country();
$subtotal = WC()->cart->subtotal; // subtotal incl taxes
$condition = $country == "US" && $subtotal >= 100; // <== HERE Set your condition (country and minimal subtotal amount)
$free = array(); // Initializing
// Loop through shipping rates for current shipping package
foreach ( $rates as $rate_key => $rate ) {
if ( $condition ){
$targeted_rate_id = 'flat_rate:4';
if( $targeted_rate_id === $rate_key ) {
unset($rates[$targeted_rate_id]);
}
}
elseif ( 'free_shipping' === $rate->method_id ) {
$free[$rate_key] = $rate;
}
}
return ! empty( $free ) && ! $condition ? $free : $rates;
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.
Important: Once code is saved, empty the cart to refresh shipping rates...
I'm looking for a way to give free shipping on all orders based on weekday of the order. So if someone places an order (let's say on Monday) it will give him free shipping no matter what type of order quantity/amount/etc.
I've tried to hook up something from different other tutorials but I can't seem to get the part where I change the free_shipping limit + not sure it works since it's incomplete.
function free_shipping_day( $rates, $package ) {
// valid days
$valid_days = array('Mon');
// current day
$today = date ( 'D' );
// check if it's valid day
if( in_array($today, $valid_day) ){
// clear other shipping methods allow only free
foreach ( $rates as $rate_id => $rate ) {
if ( 'free_shipping' === $rate->method_id ) {
$free[ $rate_id ] = $rate;
}
}
// set free_shipping limit to 0
// show notice
wc_add_notice( __( "Shipping is free today!" ), 'notice');
}
}
add_action('woocommerce_package_rates', 'free_shipping_day');
Any help is very appreciated since I'm kind of stuck with this.
To make free shipping available on specific days of the week, it requires a different hook to bypass the free shipping limitations (if they exist).
We use date() function with "w" parameter that gives an integer from 0 (Sunday) to 6 (Saturday):
// Enable free shipping on specific days of the week
add_filter( 'woocommerce_shipping_free_shipping_is_available', 'enable_free_shipping_for_specific_week_days', 10, 3 );
function enable_free_shipping_for_specific_week_days( $is_available, $package, $shipping_method ) {
// Free shipping is available on mondays and wednesdays for example
if( in_array( date('w'), [ 1, 3 ] ) ) {
return true;
}
return $is_available;
}
To hide other shipping methods when free shipping is available, you can use additionally the following:
// Hide other shipping methods when free shipping is available
add_filter( 'woocommerce_package_rates', 'hide_other_shipping_methods_when_free_shipping_is_available', 100, 2 );
function hide_other_shipping_methods_when_free_shipping_is_available( $rates, $package ) {
$free = array();
foreach ( $rates as $rate_id => $rate ) {
if ( 'free_shipping' === $rate->method_id ) {
$free[ $rate_id ] = $rate;
break;
}
}
return ! empty( $free ) ? $free : $rates;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
Add the follows code snippet in your active theme's functions.php -
function enable_free_shipping_for_days( $rates ) {
$free = array();
// valid days
$valid_days = array('Mon');
if( !in_array( date('D'), $valid_days ) ) return $rates;
foreach ( $rates as $rate_id => $rate ) {
if ( 'free_shipping' !== $rate->method_id ) continue;
$free[ $rate_id ] = $rate;
}
if( $free ) wc_add_notice( __( "Shipping is free today!" ), 'notice');
return ( $free ) ? $free : $rates;
}
add_filter( 'woocommerce_package_rates', 'enable_free_shipping_for_days', 99 );
I'm trying to add code like the one below into functions.php file. The overall function is to check products in cart and their custom fields (post_meta) called auto_delivery_default.
If its certain text in the custom field then display free shipping only, if all other text then show all other shipping methods.
Here's what I've gotten so far but I'm overlooking something making it not function right;
function show_free_ship_to_autodelivery ( $autodelivery_rate ) {
$autodelivery_free = array();
foreach( WC()->cart->get_cart() as $cart_item ){
$product = $cart_item['data'];
$product_id = $product->get_id(); // get the product ID
$autodelivery = get_post_meta( $product->get_id(), 'auto_delivery_default', true );
if( $autodelivery == "90 Days" ) {
$autodeliveryfree = array();
foreach ( $rates as $rate_id => $rate ) {
if ( 'free_shipping' === $rate->method_id ) {
$autodelivery_free[ $rate_id ] = $rate;
break;
}
}
return ! empty( $autodelivery_free ) ? $autodelivery_free : $autodelivery_rate;
}
}
}
add_filter( 'woocommerce_package_rates', 'show_free_ship_to_autodelivery', 10);
There is some errors and mistakes in your code… Instead, try the following that will hide other shipping methods when free shipping is available and when a cart item with a custom field auto_delivery_default has a value of 90 Days:
add_filter( 'woocommerce_package_rates', 'show_only_free_shipping_for_autodelivery', 100, 2 );
function show_only_free_shipping_for_autodelivery ( $rates, $package ) {
// Loop through cart items
foreach( $package['contents'] as $cart_item ){
if( $cart_item['data']->get_meta('auto_delivery_default') == '90 Days' ) {
$found = true;
break; // Stop the loop
}
}
if( ! ( isset($found) && $found ) )
return $rates; // Exit
$free = array();
foreach ( $rates as $rate_id => $rate ) {
if ( 'free_shipping' === $rate->method_id ) {
$free[ $rate_id ] = $rate;
break;
}
}
return ! empty( $free ) ? $free : $rates;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
I need a way to achieve the following: If Free Shipping is available, AND the order is being shipped to a specific zone, hide all other shipping methods.
I found this snippet:
function hide_shipping_when_free_is_available( $rates ) {
$free = array();
foreach ( $rates as $rate_id => $rate ) {
if ( 'free_shipping' === $rate->method_id ) {
$free[ $rate_id ] = $rate;
break;
}
}
return ! empty( $free ) ? $free : $rates;
}
add_filter( 'woocommerce_package_rates', 'hide_shipping_when_free_is_available', 100 );
How would I add a conditional into it to only apply it to orders going to one zone?
The following code will hide all other shipping methods when free shipping is available for a specific Zone (you will define in the function the targeted zone ID or Zone name):
add_filter( 'woocommerce_package_rates', 'free_shipping_hide_others_by_zone', 100, 2 );
function free_shipping_hide_others_by_zone( $rates, $package ) {
// HERE define your shipping zone ID OR the shipping zone name
$defined_zone_id = '';
$defined_zone_name = 'Europe';
// Get The current WC_Shipping_Zone Object
$zone = WC_Shipping_Zones::get_zone_matching_package( $package );
$zone_id = $zone->get_id(); // The zone ID
$zone_name = $zone->get_zone_name(); // The zone name
$free = array(); // Initializing
// Loop through shipping rates
foreach ( $rates as $rate_id => $rate ) {
if ( 'free_shipping' === $rate->method_id && ( $zone_id == $defined_zone_id || $zone_name == $defined_zone_name ) ) {
$free[ $rate_id ] = $rate;
break;
}
}
return ! empty( $free ) ? $free : $rates;
}
Code goes in function.php file of the active child theme (or active theme). Tested and work.
/**
* Hide shipping rates when free shipping is available.
* Updated to support WooCommerce 2.6 Shipping Zones.
*
* #param array $rates Array of rates found for the package.
* #return array
*/
function my_hide_shipping_when_free_is_available( $rates ) {
$free = array();
foreach ( $rates as $rate_id => $rate ) {
if ( 'free_shipping' === $rate->method_id ) {
$free[ $rate_id ] = $rate;
break;
}
}
return ! empty( $free ) ? $free : $rates;
}
add_filter( 'woocommerce_package_rates', 'my_hide_shipping_when_free_is_available', 100 );
Based on this answer (code below), I successfully can hide flat rate from particular product category and local delivery option is available. This is working perfect.
The problem: local pickup option is NOT available for that particular category.
How can I make the local pickup option available to this special category?
This is the code that I use:
function custom_shipping_methods( $rates ){
// Define/replace here your correct category slug (!)
$cat_slug = 'your_category_slug';
$prod_cat = false;
// Going through each item in cart to see if there is anyone of your category
foreach ( WC()->cart->get_cart() as $values ) {
$item = $values['data'];
if ( has_term( $cat_slug, 'product_cat', $item->id ) )
$prod_cat = true;
}
$rates_arr = array();
if ( $prod_cat ) {
foreach($rates as $key => $rate) {
if ('free_shipping' === $rate->method_id || 'local_pickup' === $rate->method_id || 'local_delivery' === $rate->method_id) {
$rates_arr[ $rate_id ] = $rate;
break;
}
}
}
return !empty( $rates_arr ) ? $rates_arr : $rates;
}
add_filter( 'woocommerce_package_rates', 'custom_shipping_methods', 100);
One more thing: Is it possible to show local delivery and local pickup for that special category depending on location?
Currently in my store local Pickup or Delivery is setup only for one location.
Advice: ONLY for WooCommerce version 2.6.x (added compatibility for WC 3+)
After many tests… You will need to change 2 little things in your code:
add_filter( 'woocommerce_package_rates', 'custom_shipping_methods', 100, 2 );
function custom_shipping_methods( $rates, $package ){
// Define/replace here your correct category slug (!)
$cat_slug = 'posters';
$prod_cat = false;
// Going through each item in cart to see if there is anyone of your category
foreach ( WC()->cart->get_cart() as $values ) {
$product = $values['data'];
// compatibility with WC +3
$product_id = method_exists( $product, 'get_id' ) ? $product->get_id() : $product->id;
if ( has_term( $cat_slug, 'product_cat', $product_id ) )
$prod_cat = true;
}
$rates_arr = array();
if ( $prod_cat ) {
foreach($rates as $rate_id => $rate) { // <== There was a mistake here
if ('free_shipping' === $rate->method_id || 'local_pickup' === $rate->method_id || 'local_delivery' === $rate->method_id) {
$rates_arr[ $rate_id ] = $rate;
// break; // <========= Removed this to avoid stoping the loop
}
}
}
return !empty( $rates_arr ) ? $rates_arr : $rates;
}
There was 2 mistakes:
One in the foreach loop with a bad variable name that I have replace it.
Removed break; avoiding stoping the foreach loop when one condition match.
This code goes on function.php file of your active child theme or theme.
This code is tested and fully functional (it will work if you have correctly set your shipping zones).
You will need to refresh shipping cached data: disable, save and enable, save related shipping methods for the current shipping zone, in woocommerce shipping settings.
References:
Hide other shipping methods when FREE SHIPPING is available
WooCommerce - Hide other shipping methods when FREE SHIPPING is available