A client wanted to add a local delivery option to their existing online store, where the previously available shipping options were local pickup and UPS, depending on the type of product. That delivery option needed to meet the following requirements:
- Available only to customers within a 10 mile radius of the brick and mortar location, who
- Had a minimum order total of $25,
- Were purchasing items previously available for local pickup, and
- Introducing a $10 delivery fee to any order less than $100.
While there are many elements to the request that needed to be figured out, the solution ended up being significantly more challenging than expected.
Finding a plugin for WooCommerce that can calculate the distance between the store and a customer’s location is simple enough. The Shipping Zones by Drawing for WooCommerce does a fine job of this, and has the added bonus of being able to actually draw, on a map, the desired delivery area (which proved extremely valuable later on). The premium version of the plugin offers the ability to set a minimum purchase order, but setting a delivery fee based on order total wasn’t possible.
The solution to this problem should have been easy enough: create a coupon for $10 off cart totals of $100 or more, and automatically apply it to any order using the “distance radius” shipping method.
Problem #1
The two primary plugins in the WordPress repository that enhance the default coupon functionality within WooCommerce (WooCommerce Extended Coupon Features FREE and Smart Coupons for WooCommerce) claim the ability to restrict coupons to a particular shipping method. It became apparent (for whatever reason) those plugins were incapable of targeting the custom shipping method being used by the two “shipping radius” plugins being tried. This made little sense, but without digging into and modifying plugin code, a solution wasn’t readily apparent.
The next logical approach was purchasing the WooCommerce Distance Rate Shipping plugin. After going through the setup, and many frustrating hours of testing, a bug was discovered in which the “break” and “abort” conditional rules were not functioning properly (the plugin has since been updated to address this issue).
Having no idea on the timeline to fix the bug and release an updated version, an alternative solution had to be found. After much digging and testing, a custom function was created that would check the total cost of the cart and, if less than $100, check which shipping method was selected. If the local delivery shipping method was selected (in this case, the unique shipping id used by the Shipping Zones by Drawing for WooCommerce plugin), a $10 “Delivery Fee” would be automatically added to the cart.
// Add Delivery Fee if cart total less than $100 AND Distance Rate shipping selected add_action( 'woocommerce_cart_calculate_fees', 'fivetwelve_conditional_delivery_fee', 20, 1 ); function fivetwelve_conditional_delivery_fee( $cart ) { if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return; global $woocommerce; // Get the current cart total $cart_total = $woocommerce->cart->cart_contents_total; // Move forward if cart total is less than $100 if ( $cart_total < 100 ) { // Get the currently selected shipping method $chosen_shipping_methods = WC()->session->get( 'chosen_shipping_methods' ); // If shipping method is local delivery, add $10 delivery fee if( in_array( 'szbd-shipping-method:10', $chosen_shipping_methods ) ) $cart->add_fee( 'Delivery Fee', 10, false ); } }
Problem #2
The next part of the puzzle was limiting the local delivery option to orders of at least $25. There was an added complexity to this request because the local delivery option could only be available when products with a certain shipping class were in the cart. This meant only items previously available for local pickup were eligible for local delivery.
Another custom function was created that would first look at the products in the cart and confirm only items with the determined shipping class existed. If any “shipping only” products existed in the cart, OR the cart was less than $25, the local delivery shipping method would be unset and unavailable at checkout.
// Hide Local Delivery shipping method if cart less than $25 add_filter( 'woocommerce_package_rates', 'fivetwelve_hide_delivery_based_on_subtotal', 10, 2 ); function fivetwelve_hide_delivery_based_on_subtotal( $rates, $package ) { // Get the current cart total $cart_subtotal = $package['contents_cost']; // Set the shipping class for ineligible products $shipping_class_target = 45; // shipping class ID $in_cart = false; // Check the shipping class of each product in the cart foreach( WC()->cart->get_cart_contents() as $key => $values ) { if( $values[ 'data' ]->get_shipping_class_id() == $shipping_class_target ) { $in_cart = true; break; } } // If the cart total is less than $25, or // a product exists with the ineligible shipping class, // remove the local delivery shipping method if( $cart_subtotal < 25 || $in_cart ) unset( $rates[ 'szbd-shipping-method:10' ] ); return $rates; }
The End Result
While finding the solution took much longer than it should have (the WooCommerce Distance Rate Shipping plugin would have solved all of these problems, had it been working at the time), the end result works perfectly.
Using the Shipping Zones by Drawing for WooCommerce plugin made it incredibly easy to set the exact areas eligible for local delivery (which proved infinitely valuable when the client wanted to change their radius from 10 miles to the entire county, which required drawing the available delivery zone along the county lines). The plugin does the heavy lifting with determining whether the customer is eligible for local delivery, based on their location. If they are, the custom functions then confirm eligible products are in the cart, and that the order is greater than $25. If these conditions are met, and the customer selects the “Local Delivery” option, a $10 fee is added to orders less than $100.

Leave a Reply