WooCommerce 2.6 – Hide shipping methods when FREE SHIPPING is available

WooCommerce 2.6 brings major changes in the shipping module including the introduction of Shipping Zone.
These changes break the number of existing snippets including the snippet to Hide shipping methods when FREE SHIPPING is available.

This is because of minor changes in the way $rates array is formed for the shipping method “Free Shipping”. Prior to WooCommerce 2.6, the details of shipping method “Free Shipping” is stored under array element $rates['free_shipping']. Now it is stored as $rates['free_shipping:shipping_zone_instance_id'] where shipping_zone_instance_id is the shipping zone instance id of the shipping method.
Means, if the instance id of shipping zone is 1, the rates array key will be free_shipping:1 and if instance id of shipping zone is 2, then the rates array key will be free_shipping:2 and so on.

Please refer this article for more details on shipping zones and to get an idea of instance id.

Code Snippet to Hide shipping methods when FREE SHIPPING is available.

Below snippet is an effort to make the existing snippet work for WooCommerce 2.6. Let me know in comments if this can be improved. Alternatively, you can use ELEX WooCommerce Hide Shipping Method Plugin to conditionally hide WooCommerce shipping methods.

 

 

Comments (36)

  • integratutions
    integratutions

    Hello Vj,

    I need your help with this scenario.

    I have these shipping options:
    1. Free Shipping Above $50 Spent.
    2. Normal Shipping Below $50 Spent @ $5.
    3. Express Shipping @ $10.

    I would like Express Shipping option to be shown at all times. Free shipping to be shown only when the customer has more than $50 in the cart. It’s hidden and normal shipping is shown in its place when the cart has less than $50.

    Please help and advice :(((

    Thank you in advance!

    September 15, 2017 at 5:06 am
    • Lorenzo
      Lorenzo

      Hi @integratutions,

      You can use this code snippet to hide flat_rate 5$ when order cost is 50 or above. You’ll have to configure the flat rate ID and the free shipping ID.

      Let me know if you face any issues.

      September 15, 2017 at 3:01 pm
    • integratutions
      integratutions

      Hello Lorenzo,

      Thank you for your quick reply. 🙂

      How do I check what’s my Free Shipping ID? I’m using Woocommerce 3.1.2. And the Free shipping settings pops up when clicked, not directed to a page where I can see the ID as it’s used to be done before. URL ends with &zone_id=1.

      Screenshots:
      https://cl.ly/0d0h3Z3b253b
      https://cl.ly/3E0J193x0G0q
      https://cl.ly/1e2k2B3d3m3b

      Another question is where do I set the Flat Rate ID? I can only see via the comment to set the Free Shipping ID. Here’s the edited code:

      // Hide shipping method(s) based on cart total.

      add_filter(‘woocommerce_package_rates’, ‘wf_remove_shipping_options_basedon_cart_total’, 10, 2);
      function wf_remove_shipping_options_basedon_cart_total($rates, $package){
      global $woocommerce;
      $order_total_limit = 50; //Set here limit of cart total
      $method_to_hide_when_cross_limit = array(
      ‘wf_shipping_ups:03’
      );

      $method_to_show_when_cross_limit = array(
      ‘free_shipping:1’, //config here exact free shipping key of you cart
      );

      $cart_total = WC()->cart->cart_contents_total;
      if ( $cart_total >= $order_total_limit ) {
      foreach ($method_to_hide_when_cross_limit as $shipping_method) {
      unset( $rates[$shipping_method] );
      }
      }else{
      foreach ($method_to_show_when_cross_limit as $shipping_method) {
      unset( $rates[$shipping_method] );
      }
      }
      return $rates;
      }

      Thank you so much. 🙂

      September 18, 2017 at 5:45 am
    • Lorenzo
      Lorenzo

      Hi @integratutions,

      To get the free shipping ID and Flat rate ID you need to go to the cart page and when the free shipping and flat rate shows up right click on the free shipping or flat rate and click on inspect, and the shipping method and ID will show in the details as the screenshot shown here https://snag.gy/sdZlDG.jpg

      September 18, 2017 at 11:31 pm
    • integratutions
      integratutions

      Hello Lorenzo,

      Alrighty, I have gotten my flat rate ID(flat_rate:3) and free shipping ID(free_shipping:1), but something is still not correct and my flat rate 3 is still showing when the order amount is more than $50. My site is contactlens.sg, would you be able to have a look at my ID and code below to see what’s the mistake? Sorry for the trouble and really appreciate your patience and kind assistance. 🙂

      add_filter(‘woocommerce_package_rates’, ‘wf_remove_shipping_options_basedon_cart_total’, 10, 2);
      function wf_remove_shipping_options_basedon_cart_total($rates, $package){
      global $woocommerce;
      $order_total_limit = 50; //Set here limit of cart total
      $method_to_hide_when_cross_limit = array(
      ‘flat_rate:3’
      );

      $method_to_show_when_cross_limit = array(
      ‘free_shipping:1’, //config here excat freeshipping key of you cart
      );

      $cart_total = WC()->cart->cart_contents_total;
      if ( $cart_total >= $order_total_limit ) {
      foreach ($method_to_hide_when_cross_limit as $shipping_method) {
      unset( $rates[$shipping_method] );
      }
      }else{
      foreach ($method_to_show_when_cross_limit as $shipping_method) {
      unset( $rates[$shipping_method] );
      }
      }
      return $rates;
      }

      September 22, 2017 at 4:17 am
    • integratutions
      integratutions

      Oh yes, please select Singapore for shipping country as I have different rates for other countries groups.
      https://cl.ly/1W2v1e271q2N

      September 22, 2017 at 4:19 am
    • Lorenzo
      Lorenzo

      Hi @integratutions,

      Can you try using the flat rate ID as flat_rate without the post-fix :03, if you still face issues please raise a ticket in xadapter support and provide admin credentials to your site so that i can check.

      September 22, 2017 at 11:39 am
  • alex-13-05
    alex-13-05

    Good day! Is there a way hide specific shipping method when ALL products in cart with shipping classes? Thanks

    March 21, 2017 at 1:50 am
  • Dave B

    I have successfully applied this code to a site and it works. But what if im using real time UPS shipping rates and have GROUND UPS and 3 Day UPS as the shipping options and I want to show FREE SHIPPING but only remove the GROUND UPS option and still display the 3 day UPS option?

    SO if free shipping is available it would look like this:

    – FREE SHIPPING
    – 3day UPS $x.xx

    October 8, 2016 at 2:33 am
    • elvin
      Elvin

      Hi Dave,
      You can achieve this by replacing ‘flate_rate’ with the id corresponding to 3 Day UPS.

      October 8, 2016 at 9:54 pm
  • carl

    I need help with hiding free shipping when the product is Flat rate only, I have no idea about coding and would really need a step by step to set this up. You can email me at Carl.cunningham@everymantactical.us

    September 30, 2016 at 11:05 pm
    • elvin
      Elvin

      Hi Carl,
      You can achieve this by replacing ‘local_pickup’ and ‘free_shipping’ by ‘flat_rate’ in the above code and paste it in current themes functions.php

      October 1, 2016 at 10:32 pm
  • Jack

    Hi,

    Thank you for the code snippet! But I have a question on my logic.

    If order is less than 100 than flat rate and local pick up
    If order more than 100 free shipping and local pick up

    Can this logic work?

    September 3, 2016 at 4:28 pm
    • elvin
      Elvin

      Hi Jack,
      The code snippet will give only free shipping or local pickup if any one or both are available and will discard all other shipping options.

      September 3, 2016 at 9:48 pm
  • Donny van der Kloot

    Hi,

    Thank you for the code snippet! But I have a question.

    I use version 2.6 and when I add this code I get the following problem:

    Only local pickup is visible (not the paid shipping method) . Only orders > € 200,- will be delivered free.

    August 25, 2016 at 10:31 am
    • elvin
      Elvin

      Hi Donny van der Kloot,
      Replace the following with
      if (‘free_shipping’ === $rate->method_id || ‘local_pickup’ === $rate->method_id) {
      this line
      if (‘free_shipping’ === $rate->method_id) {
      wil help you fix your issue. This will remove all shipping options if free shipping is available.

      August 25, 2016 at 4:17 pm
  • Rajesh Rajput

    I updated my woocommerce from 2.2 to 2.6 and copy & past the code in function.php file in theme folder. but it does not do anything. it shows both free shipping & other delivery option on the cart page. The function is not called.

    August 4, 2016 at 7:38 am
    • elvin
      Elvin

      Make sure that you have copied the code to the current active theme’s functions.php file.

      August 4, 2016 at 9:40 am
  • Fabian Rueda

    Thanks!! it works”… flat rate when it should be, after a certain “amount” changes to free shipping, abd if the person insert the “adequate” postal code, the option changes to “local pickup”… but.. i think the most of us needs to show “at the same time” local pickup (if the postal code is in the region)..”and” the other option “flat rate and free shipping depending of the configuration each person wants..

    I use the code on 28/07 on 12:48 German time…

    July 28, 2016 at 10:48 am
  • Kramer

    Hi Elvin

    I tried it, and at first I thought it was working (it hides flat rate and keeps local pickup).

    But it seems to be hiding flat rate even when free shipping is not available? it only shows local pickup.

    July 1, 2016 at 10:43 am
    • elvin
      Elvin

      Replace this code,
      if (‘free_shipping’ === $rate->method_id || ‘local_pickup’ === $rate->method_id) {
      $new_rates[$key] = $rates[$key];
      }
      with
      if (‘free_shipping’ === $rate->method_id) {
      $new_rates[$key] = $rates[$key];
      if( ‘local_pickup’ === $rate->method_id) {
      $new_rates[$key] = $rates[$key];
      }
      }

      July 1, 2016 at 5:47 pm
  • Russell

    Hi,

    I’ve looked at this snippet of code and others which aim to solve a similar problem. When I put this code and the suggested changes in my child theme’s functions.php file I’m not seeing the flat rate option disappear when the order value is greater than the limit set in the free rate.

    My aim is to hide the flat rate (paid delivery) option when the value of the order is > the value set in the free shipping option. This means that the site should always show 2 options.

    1. Local pick up
    2. Either “Free delivery” if order value >= threshold set in free delivery shipping option OR “Flat rate” if <the threshold.

    I've tried replacing the code line as indicated in one of the other replies. I've tried replacing it in both instances together and separately but the behavior of the system doesn't seem to change. It always shows all 3 optiions

    Thanks in anticipation

    June 29, 2016 at 5:38 pm
    • Vj
      Vj

      Hi Russell, Updated code committed.

      July 2, 2016 at 5:56 am
    • Russell

      Hi VJ,

      When you say “Updated code committed” what does this mean?

      I’ve tried using these two versions of code…

      add_filter(‘woocommerce_package_rates’, ‘xa_hide_shipping_rates_when_free_is_available’, 10, 2);
      function xa_hide_shipping_rates_when_free_is_available($rates, $package)
      {
      global $woocommerce;
      $version = “2.6”;
      if (version_compare($woocommerce->version, $version, “>=”)) {
      $new_rates = array();
      foreach($rates as $key => $rate) {
      if (‘free_shipping’ === $rate->method_id || ‘local_pickup’ === $rate->method_id) {
      $new_rates[$key] = $rates[$key];
      }
      }
      return $new_rates;
      }
      else {
      if (isset($rates[‘free_shipping’])) {
      // Below code is for unsetting single shipping method/option.
      $free_shipping = $rates[‘free_shipping’];
      if (isset($rates[‘local_pickup’])) {
      $local_pickup = $rates[‘local_pickup’];
      $rates = array(); // Unset all rates.
      $rates[‘local_pickup’] = $local_pickup; // Restore local pickup.
      $rates[‘free_shipping’] = $free_shipping; // Restore free shipping rate.
      }
      else {
      $rates = array(); // Unset all rates.
      $rates[‘free_shipping’] = $free_shipping; // Restore free shipping rate.
      }
      }
      }
      return $rates;
      }

      and this code

      add_filter(‘woocommerce_package_rates’, ‘xa_hide_shipping_rates_when_free_is_available’, 10, 2);
      function xa_hide_shipping_rates_when_free_is_available($rates, $package)
      {
      global $woocommerce;
      $version = “2.6”;
      if (version_compare($woocommerce->version, $version, “>=”)) {
      $new_rates = array();
      foreach($rates as $key => $rate) {
      if (‘free_shipping’ === $rate->method_id) {
      $new_rates[$key] = $rates[$key];
      if( ‘local_pickup’ === $rate->method_id) {
      $new_rates[$key] = $rates[$key];
      }
      }
      }
      return $new_rates;
      }
      else {
      if (isset($rates[‘free_shipping’])) {
      // Below code is for unsetting single shipping method/option.
      $free_shipping = $rates[‘free_shipping’];
      if (isset($rates[‘local_pickup’])) {
      $local_pickup = $rates[‘local_pickup’];
      $rates = array(); // Unset all rates.
      $rates[‘local_pickup’] = $local_pickup; // Restore local pickup.
      $rates[‘free_shipping’] = $free_shipping; // Restore free shipping rate.
      }
      else {
      $rates = array(); // Unset all rates.
      $rates[‘free_shipping’] = $free_shipping; // Restore free shipping rate.
      }
      }
      }
      return $rates;
      }

      In both cases I loose all shipping methods and instead get a message that shipping rates will be calculated once an address has been entered…

      For clarity and in simple terms what I think is required is something that does this.

      1. If Local pickup is set as an option then ALWAYS display local pickup AND
      2. If free shipping is available AND if the order value is >= the threshold amount set for free shipping then display free shipping ELSE
      3. Display Paid delivery

      = display 1 and either 2 or 3

      Thanks again in anticipation of a working solution (I wish I knew a bit more about how all this works :-))

      Russell

      July 3, 2016 at 8:06 pm
    • elvin
      Elvin

      Hi Russell,
      The code snippet is updated.
      It will show only free shipping and local pickup if both are available.
      If free shipping alone is available only free shipping will be shown.
      If local pickup alone is available only local pickup will be shown.
      If both free shipping and local pickup are not available then all the returned shipping options will be shown.

      July 4, 2016 at 6:51 am
    • Russell

      Hi Elvin,

      Many thanks for your support with this but it’s still not doing what I expect and what I’m sure a lot of people would love to see…

      The behaviour that I’m seeing is:

      If free shipping is available show both free shipping and local pickup
      If free shipping is not available only show local pickup

      I think this is in line with your described behaviour above

      However, this is different than I have been asking for and I’m wondering if I’m guilty of hijacking a different question?

      There are three shipping options in woocommerce 2.6:1. Local pickup, 2. Flat rate and 3. Free delivery.

      Free delivery is configurable. I have 2 shipping zones WA14* and M33* WA14* is set to be free if>= 15 M33* is free if >= 20.

      If I create an order of <15 in my basket then in checkout I see only local pickup for both zones
      If I create an order of 17.5 then WA14* shows free delivery and local pickup. If I change the shipping address to M33* then I only see local pickup again.

      I am not seeing flat rate at all with this code.

      With an order value of 17.5 if I change from my billing address (which is WA14 5NH) to a different shipping address (such as M33 7PE) then I would expect the free delivery option to change to show the associated flat rate charge.

      You can see the site behaviour at arnies.co.uk

      I tried the patch that you suggested for Kramer but I got the same result

      Hope you can help please

      Regards
      Russell

      July 5, 2016 at 7:27 am
    • elvin
      Elvin

      Hi Russell,
      The purpose of this code snippet is to hide the flat rate and other available shipping methods when free shipping is available. However it is been little modified to show local pickup too. If you want flat rate also comment the code snippet.

      July 8, 2016 at 11:41 am
  • Kramer

    Hi, the snippet works great, but how do we hide only the flat rate, but keep local pickup? Please help! Thanks

    June 24, 2016 at 7:06 pm
    • Vj
      Vj

      In this case, do not $rates = array(); Instead unset($rates['flat_rate']);

      June 25, 2016 at 4:50 am
    • Kramer

      You mean on line 25, replace $rates = array(); with unset($rates[‘flat_rate’]); ???

      Because I tried that and it doesn’t work?

      June 25, 2016 at 7:42 am
    • Vj
      Vj

      Putting debug logs by getting help from developer should help you to identify the issue.

      June 27, 2016 at 6:59 am
    • Kramer

      Hi Vj.

      All we’re trying to do is hide other shipping methods (normal flat rate) when free is available, BUT keep local pickup.

      If you could post a working snippet that can do this, that would be great!

      Thanks

      June 27, 2016 at 7:13 am
    • elvin
      Elvin

      I have updated the code to give local pickup option along with free shipping option. Please use it.

      July 1, 2016 at 6:22 am
  • Futuro

    Its working correctly but i want to know one more thing that one more option is visible custom option below flat rate how to hide that actually i only want flat rate and free shipping

    June 15, 2016 at 6:17 pm
    • Vj
      Vj

      Is there a way you can provide screenshot of shipping options shown cart page by sharing a link or so? That will help me to understand your question better.

      June 15, 2016 at 6:59 pm

Leave a Reply