Online retailers use free shipping to encourage customers to buy more. I am sure many customers have added an item or two to the cart in order to reach the free shipping threshold. If your store has customers from multiple countries, and the threshold is different for different countries, then you cannot have a single promotional banner listing the threshold.
While the store should have a page listing delivery charges, including the free shipping threshold, a reminder in the cart may have a better conversion rate.
For a client I wrote a small bit of code to compare the current cart total to the threshold and displayed how much to add to the cart to avail of free shipping. As free shipping was only available to a small number of countries I hard coded the threshold and countries in the code. It was nice and simple, and worked.
Removing Hard Coded Values
It always bothered me that the code, although working well, had the threshold and countries hard coded. If the client changed anything in the Shipping Zones then my code would be out of sync.
Searching for the Right Hook
I searched the WooCommerce source code to see how the Shipping Zones (introduced in 2.6) determined the shipping methods to display. For each apply_filters() and do_action() call that I found I wrote code to see the data being manipulated at that stage. In one stage I could see all the shipping methods for the selected destination country and then the next stage the available methods were adjusted based on the current cart (e.g. free shipping method removed when below the threshold). I could see how to access the free shipping threshold amount. I was close to giving up.
I eventually found The Ultimate Guide to WooCommerce Shipping Zones blog post by Igor Benic where it demonstrated how to retrieve all the shipping zones and currently active zone. I also read Rodolfo Melogli’s WooCommerce: “You Only Need to Spend $$ to Get Free Shipping” @ Cart Page. While it didn’t work for me, I copied the idea storing the threshold values in an array and using min() to find the lowest.
Examining Shipping Zone Data
Now that I knew about the WC_Shipping_Zones::get_zones() and WC_Shipping_Zones::get_zone_matching_package() functions I was able to do some debugging to examine the data returned by each of those functions.
I am slowing starting to write PHP classes for my plugins so was able to determine the free shipping threshold and store it in a member variable. This value can be retrieved in the two member functions that display the free shipping message. Nice and tidy.
An obvious enhancement to the code is to allow other plugins adjust the displayed method i.e. update the echo line to add an apply_filters() call.
Update: A fellow developer contacted me to report that the code wasn’t working for her. I did a lot of investigation to retrieve the “Rest of World” zone information (some methods worked, some didn’t). I then added code to ensure that the free shipping method required a minimum cart amount (it can be set to require a coupon).