Skip to content

Instantly share code, notes, and snippets.

@damiencarbery
Last active November 29, 2021 18:40
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save damiencarbery/4c6a8ef3cd06fa9f003d329e93fe00cd to your computer and use it in GitHub Desktop.
Save damiencarbery/4c6a8ef3cd06fa9f003d329e93fe00cd to your computer and use it in GitHub Desktop.
WooCommerce: Promote Free Shipping by listing how much to add to cart to avail of it.
<?php
/*
Plugin Name: Promote Free Shipping (WooCommerce)
Plugin URI: http://www.damiencarbery.com
Description: Encourage customer to add more items to the cart to avail of free shipping.
Author: Damien Carbery
Version: 0.3
*/
class PromoteFreeShipping {
private $free_shipping_min_amount;
private $debug_mode;
public function __construct() {
$this->free_shipping_min_amount = false;
// Allow debug mode to be enabled when WordPress debug mode is enabled.
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
$this->debug_mode = true;
}
// Or set it manually.
$this->debug_mode = false;
}
public function init() {
add_action( 'woocommerce_load_shipping_methods', array( $this, 'get_free_shipping_amount' ) );
add_action( 'woocommerce_cart_totals_before_order_total', array( $this, 'promote_free_shipping_notice' ) );
add_action( 'woocommerce_review_order_after_shipping', array( $this, 'promote_free_shipping_notice' ) );
add_action( 'woocommerce_before_cart', array( $this, 'promote_free_shipping_notice_before_cart' ) );
}
// Determine the minimum amount for free shipping.
function get_free_shipping_amount( $package ) {
if ( $this->debug_mode ) {
error_log( 'PromoteFreeShipping: Entering get_free_shipping_amount().' );
//error_log( 'PromoteFreeShipping: $package:' . var_export( $package, true ) );
}
// Retrieve Rest of World (default) zone.
$row_zone = new WC_Shipping_Zone(0);
$all_zones[$row_zone->get_id()] = $row_zone->get_data();
$all_zones[$row_zone->get_id()]['formatted_zone_location'] = $row_zone->get_formatted_location();
$all_zones[$row_zone->get_id()]['shipping_methods'] = $row_zone->get_shipping_methods();
// Add user configured zones
$all_zones = array_merge( $all_zones, WC_Shipping_Zones::get_zones() );
if ( $this->debug_mode ) {
error_log( 'PromoteFreeShipping - $all_zones: ' . var_export( $all_zones, true ) );
}
// Note: This sometimes triggers a PHP warning - it appears that the $package array is not always
// populated. I don't know the circumstances when this happens or the cause.
$shipping_zone = WC_Shipping_Zones::get_zone_matching_package( $package );
if ( $this->debug_mode ) {
error_log( 'PromoteFreeShipping: Matched zone: ' . var_export( $shipping_zone, true ) );
}
$min_amounts = array();
// Verify that the shipping zone is in $all_zones (zone id 0 isn't!)
if ( array_key_exists( $shipping_zone->get_id(), $all_zones ) ) {
// Get all the methods for this zone and look for free_shipping methods.
$methods = $all_zones[ $shipping_zone->get_id() ][ 'shipping_methods' ];
foreach ( $methods as $method_id => $method_obj ) {
// Verify that the free_shipping method requires a minimum cart amount (some require a coupon)
if ( ( 'free_shipping' == $method_obj->id ) && ( 'min_amount' == $method_obj->requires || 'either' == $method_obj->requires ) ) {
$min_amounts[] = $method_obj->min_amount;
}
}
}
// Set to false if no free shipping.
$this->free_shipping_min_amount = ( empty( $min_amounts ) ) ? false : min( $min_amounts );
if ( $this->debug_mode ) {
error_log( 'PromoteFreeShipping: Free Shipping Min Amounts: ' . var_export( $min_amounts, true ) );
error_log( 'PromoteFreeShipping: Free Shipping Min Amount set to: ' . $this->free_shipping_min_amount );
}
}
// Add a notice to encourage the customer to add more items to the cart to avail of free shipping.
public function promote_free_shipping_notice( $location ) {
// Simply return if free shipping not available for the current zone.
if ( ! $this->free_shipping_min_amount ) {
return;
}
if (WC()->cart->cart_contents_total) {
$total = WC()->cart->get_displayed_subtotal();
// If cart is under free shipping threshold AND shipping to a country that has free shipping option,
// then tell them how much to add to the cart to get free shipping.
if ($total < $this->free_shipping_min_amount) {
$notice = 'To avail of free shipping add <em>'.wc_price($this->free_shipping_min_amount - $total).'</em> to your cart.';
if ( 'before_cart' == $location ) {
wc_print_notice( $notice, 'notice' );
}
else {
echo '<tr class="promote_free_shipping"><td colspan="2">'. $notice . '</td></tr>';
}
}
}
}
// Add the notice before the cart.
public function promote_free_shipping_notice_before_cart() {
$this->promote_free_shipping_notice( 'before_cart' );
}
}
$Promote_Free_Shipping = new PromoteFreeShipping();
$Promote_Free_Shipping->init();
<?php
// Encourage customers to add items to cart to avail of free shipping.
add_action('woocommerce_cart_totals_before_order_total', 'rac_promote_free_shipping');
add_action('woocommerce_review_order_after_shipping', 'rac_promote_free_shipping');
function rac_promote_free_shipping() {
if (WC()->cart->cart_contents_total) {
$total = WC()->cart->get_displayed_subtotal();
// If cart is under free shipping threshold AND shipping to a country that has free shipping option,
// then tell them how much to add to the cart to get free shipping.
$free_shipping_threshold = 25;
if ($total < $free_shipping_threshold) {
$country = WC()->checkout->get_value('billing_country');
$free_shipping_countries = array('IE', 'GB', 'IM', 'JE'); // Free shipping to Ireland, UK, Isle of Man and Jersey
if (in_array($country, $free_shipping_countries)) {
echo '<tr class="promote_free_shipping"><td colspan="2">To avail of free shipping add <em>'.wc_price($free_shipping_threshold-$total).'</em> to your cart.</td></tr>';
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment