type:
snippet
category:
shipping
name:
Free shipping using a coupon
versions:
0.6.0, 0.7.0, 0.7.1, 0.7.2, 1.0, 1.1
reference:
https://forum.foxycart.com/discussion/4487
tags:
snippets, shipping, advance
date:
2011-05-27

Setup 1: Free shipping using a 0% discount coupon

Using version 2.0? There is a new snippet available for our latest version, available from here.

Step 1: Add a coupon

First, set up a coupon - and depending on your store version, you will need to setup different coupons.

  • For FoxyCart 0.7.1 and older: Create a coupon of the type “Amount based on the quantity” with a discount string of 1-0.01
  • For FoxyCart 0.7.2 and newer: Create a coupon of the type “Percentage based on the quantity” with a discount string of 1-0. Note that a discount of 0 will mean that the coupon use won't be noted against order emails or the transaction report in the administration. If that is an issue, you'll want to use the previous $0.01 discount.

Give it a code and a name like (“Free Shipping!”). Note that this script relies on the coupon name having the string “free shipping” within the name. Case doesn't matter, so you can have it in all capitals, sentence case or however you like - as long as it appears within it's name somewhere. So for example “Free Shipping!”, “100% Free Shipping for all!” and “fReE sHiPpInG” are all valid for this code (although that last one isn't advised :). “Free quick shipping” however is not.

Step 2: Enable free shipping live rate

Then, enable free shipping on your account (in the Foxycart admin: STORE → shipping → CUSTOM OPTIONS → custom domestic services → free ground shipping). You can also rename that option to be whatever you want in the languages section of the administration.

Step 3: Add javascript

Then, in your checkout script, include the following javascript - pasting it right before the closing </head> tag of your checkout template:

<script type="text/javascript">
jQuery(document).ready(function(){
	jQuery(document).ajaxComplete(function(event, request, settings) {
		jQuery("label[for='shipping_service_60']").hide();
		if(fc_json.hasOwnProperty('coupons')) {
			jQuery.each(fc_json.coupons, function(i, coupon){
				if(coupon.name.search(/free shipping/i) > -1) {
					jQuery("label[for='shipping_service_60']").show();
					jQuery("label[for='shipping_service_60'].fc_shipping_service").text(coupon.name);
				}
			});
		}
		if (jQuery("label[for='shipping_service_60']").is(":hidden")) {
			jQuery("label[for='shipping_service_60']").remove();
		}
	});
});
</script>

Setup 2: Free shipping using session variables and fake coupons

While the previous setup uses the default FoxyCart coupon functionality as it currently stands, you are left with a $0.01 discount on the checkout which can be hard to stomach for some people. The following setup overwrites a default function in the cart to allow for a custom coupon to be set, but also allow normal coupons to be added as well. The downside of this method over the previous method is that the coupon code is essentially included in the source code of the page, but this script does obfuscate the string to hide it partly. The benefit of this approach though is that it look and feels just like a default coupon to the customer.

Step 1: Add javascript to the cart

Add this to your cart template, right before the closing </head> tag.

<script type="text/javascript">
FCcode = "fs";
FCtoken = "serrfuvc";
 
function fc_UpdateCart() {
  fc_PreventCheckout();
  if (FScheck(jQuery("#fc_coupon").val())) {
    window.location.href = "/cart?h:"+FCcode+"=true";
  } else {
    jQuery("#fc_cart_form").submit();
  }
}
 
jQuery(document).ready(function() {
  if (fc_json.custom_fields[FCcode] == "true") {
    var colspan = jQuery("#fc_cart_table tr.fc_cart_item:first td").length - 1;
    jQuery("#fc_cart_foot_discount_new").before('<tr class="fc_cart_foot_discount"><td colspan="' + colspan + '" class="fc_col1">Free Shipping:</td><td class="fc_col2"><span class="fc_discount">TBD</span><span class="fc_cart_coupon_remove"><a title="Remove this coupon" class="fc_cart_remove_link" href="https://'+window.location.hostname+'/cart.php?h:'+FCcode+'=false">[x]</a></span></td></tr>');
  }
});
 
function FScheck(FSval) {
  return (FCtoken.replace(/[a-zA-Z]/g, function(c){return String.fromCharCode((c<="Z"?90:122)>=(c=c.charCodeAt(0)+13)?c:c-26);}) == FSval);
}
</script>

At the start of the script is two variables you need to set.

FCcode is the name of the custom session attribute, which you'd be safe to leave this as it is unless you want to get specific.

FCtoken is the actual code that people need to type into the coupon input to apply the free shipping coupon. You may notice that this looks weird in the code above. That's because its obfuscated by the ROT13 method, which is a requirement for this script to work as it essentially crudely hides the code and adds an additional step for sneaky customers to work it out. To get your obfuscated string, work out what you want your coupon to be and visit this page to generate it. While it doesn't make your free shipping code completely secure, at least not having it in plain text in the source code makes it a little harder. In the code above, the FCtoken is actually “freeship”.

What does this script do?

Basically this script overwrites a default function that is called whenever someone hits enter on a text input such as the coupon or quantity inputs, or presses the 'update' buttons. It checks to see if the text in the coupon field matches the coupon code you've set. If it does, then it adds a hidden session attribute by reloading the cart. If it doesn't match, then it just submits the cart update as it normally would. Also, on page load, it checks if the session attribute has been set. If it has, it adds the table row for the free shipping, also with a button to remove it.

Step 2a: Add javascript to the checkout (live rates)

This approach is for checkouts that utilise live rates. This script relies on you having enabled 'Free Shipping' for your shipping settings in the FoxyCart admin (Under Shipping > CUSTOM OPTIONS > custom domestic services > free ground shipping), so make sure that is enabled.

Add this to your checkout template, right before the closing </head> tag.

<script type="text/javascript">
FCcode = "fs";
FConly = true;
 
jQuery(document).ready(function() {
  checkFreeShip();
 
  if (fc_json.custom_fields[FCcode] == "true") {
    var colspan = jQuery("#fc_cart_table tr.fc_cart_item:first td").length - 1;
    jQuery("#fc_cart_foot_shipping").before('<tr id="freeshipping" class="fc_cart_foot_discount"><td colspan="' + colspan + '" class="fc_col1">Free Shipping:</td><td class="fc_col2"><span class="fc_discount">APPLIED</span></td></tr>');
  }
 
  jQuery(document).ajaxComplete(function(event, request, settings) {
    if (settings.url.indexOf('GetShippingCost') != -1) {
      checkFreeShip();
    }
  });
});
 
function checkFreeShip() {
  if (fc_json.custom_fields[FCcode] == "true") {
    jQuery("label[for='shipping_service_60']").show();
    if (FConly) {
      $("#fc_shipping_methods_inner label").not("label[for='shipping_service_60']").hide();
    }
  } else {
    jQuery("label[for='shipping_service_60']").remove();
  }
}
</script>

There is two variables that need to be customised at the top of this script. FCcode needs to be set to the same as it was in the first step. FConly sets whether you only what the free shipping option returned to your customer or not. If this is set to true, no matter how many other shipping rate options are returned to the customer, only the free shipping option will be displayed. If false, all returned shipping rates will be visible, along with the free option.

What does this script do?

This script checks if the session attribute is set. If it is, it adds a line item to the cart for the free shipping coupon. Whenever the shipping rates are updated, if the session attribute is set, it shows the free shipping option and if it is set to be the only one, hides the other options. If the session attribute isn't set, then it removes the free shipping option from the checkout.

Step 2b: Add javascript to the checkout (flat rates)

This script relies on you having set your checkout to be shipped using flat rates, with a flat rate of 0 set in the administration.

Add this to your checkout template, right before the closing </head> tag.

<script type="text/javascript">
FCcode = "fs";
 
jQuery(document).ready(function() {
  if (fc_json.custom_fields[FCcode] == "true") {
    var colspan = jQuery("#fc_cart_table tr.fc_cart_item:first td").length - 1;
    jQuery("#fc_cart_foot_shipping").before('<tr id="freeshipping" class="fc_cart_foot_discount"><td colspan="' + colspan + '" class="fc_col1">Free Shipping:</td><td class="fc_col2"><span class="fc_discount">APPLIED</span></td></tr>');
  }
 
  FC.checkout.config.orderFlatRateShipping = myCustomShipping();
  FC.checkout.updateShipping(-1);
});
 
function myCustomShipping() {
  if (fc_json.custom_fields[FCcode] == "true") {
    return 0;
  } else {
    // ADD YOUR CUSTOM FLAT RATE CALCULATIONS, RETURNING THE CALCULATED FLAT RATE LIKE:
    // var myShipping = 5;
    // return myShipping;
  }
}
</script>

There is just the single variable needing to be updated in this script, FCcode which needs to match what you set in step 1. Also, if you'd like to provide some sort of other flat rate value if the customer hasn't added the coupon for free shipping to their cart, then add that inside the myCustomShipping where noted to.

What does this script do?

This script simply adds a line item to the cart in the top right to show that the free shipping coupon is part of this cart if it is set. It then updates the flat rate value to be the returned value of the function myCustomShipping(). This function checks if the session attribute has been set - if it has then it returns 0, if additional calculations are added to the else in that if statement, then that returned value would be set as the shipping.

Step 3: Add javascript to the receipt

Add the following right before the closing </head> in your receipt template:

<script type="text/javascript">
FCcode = "fs";
 
jQuery(document).ready(function() {
  if (fc_json.custom_fields[FCcode] == "true") {
    var colspan = jQuery("#fc_cart_table tr.fc_cart_item:first td").length - 1;
    jQuery("#fc_cart_foot_shipping").before('<tr id="freeshipping" class="fc_cart_foot_discount"><td colspan="' + colspan + '" class="fc_col1">Free Shipping:</td><td class="fc_col2"><span class="fc_discount">&nbsp;</span></td></tr>');
  }
});
</script>

There is just the single variable needing to be updated in this script, FCcode which needs to match what you set in step 1.

Notes for this method

A big note for this second approach using session attributes is that it is essentially having the free shipping coupon included in the source code. While it may be obfuscated, its only one additional step to find the code. If that is an issue for you, and the first method of the $0.01 coupon doesn't work for you either, the next best thing is to vote for free shipping coupons here.

Another thing to note is that while there is a visual cue on the cart, checkout and receipt that the free shipping coupon has been applied, this isn't present on the email templates. While it would be possible to add them in if you created your own email receipts using the XML datafeed, it is not possible using the default email receipts from the admin.

Site Tools