Free delivery for certain zip codes if 6 or more products ordered?

davidzupecdavidzupec Member
in Help edited August 2014
Hello, Is there a way to allow the free delivery for certain zip codes if the customer orders 6 or more products? I found a great start here: https://forum.foxycart.com/discussion/6926/free-local-delivery-for-certain-zip-codes/p1 but I need the free shipping only to be available if they order 6 or more products. Is that possible? If so any help would be appreciated, thank you!
Tagged:
«1
Comments
  • Also I'm doing Live Rate Shipping if that helps. Thank you!
  • davidzupecdavidzupec Member
    edited August 2014
    I found these snippets...not sure if this would work the way I have it presented though?

    FC.customLiveShipping.logic = function() {
        /* BEGIN CUSTOM SHIPPING LOGIC */
    
    FC.customLiveShipping.hide('free');
    if(fc_json.product_count > 6) {
    	FC.customLiveShipping.show('free');
    }
    
    var zip = (jQuery("#use_different_addresses").is(":checked") ? $("#shipping_postal_code").val() : $("#customer_postal_code").val());
    var valid_zips = [92101, 92102, 92106, 92107, 92110];
     
    if (jQuery.inArray(zip, valid_zips) === -1) {
      // Not in the free shipping zip range
      FC.customLiveShipping.remove(60);
    }
    
       /* END CUSTOM SHIPPING LOGIC */
      }
    
  • fc_adamfc_adam FoxyCart Team
    @davidzupec,

    So that custom logic (as long as you've also added the 'live rate shipping modification' snippet to your checkout as well) will firstly only show the free shipping option if more than 6 products are in the cart, but then remove it if the customers shipping zip code is not within that specific range of codes. Is that what you're after?
  • Hi Adam, what I'm trying to achieve is at checkout give the customers that are in those specific zip codes free shipping if their cart contains 6 cases or more. Everybody else outside those zip codes receives the live shipping rates regardless of quantity ordered. So yes I believe you have it correct. Sorry it's been a long day : )
  • fc_adamfc_adam FoxyCart Team
    @davidzupec,

    To be a bit more specific with it, you could do this:
    FC.customLiveShipping.hide(60);
     
    var zip = (jQuery("#use_different_addresses").is(":checked") ? $("#shipping_postal_code").val() : $("#customer_postal_code").val());
    var valid_zips = [92101, 92102, 92106, 92107, 92110];
     
    if (jQuery.inArray(zip, valid_zips) > -1 && fc_json.product_count > 6) {
      // In valid zips and has more than 6 products
      FC.customLiveShipping.show(60);
    }
    
  • As long as this achieves what I'm after I'll be forever grateful to you Adam : ) I'll implement this code tomorrow! Thank you Adam!
  • Hi Adam, for some reason it's not working at all. Here's what I have in my live shipping snippet:
    <!-- Allows only US to be selected  -->
    <script type="text/javascript" charset="utf-8">
    	//<![CDATA[
    	jQuery(document).ready(function() {
     
    		/* BEGIN CUSTOM LOCATION LOGIC */
    		FC.locations.limitCountriesTo(["US"]);
    
    FC.customLiveShipping.hide(60);
     
    var zip = (jQuery("#use_different_addresses").is(":checked") ? $("#shipping_postal_code").val() : $("#customer_postal_code").val());
    var valid_zips = [11980,11931,11932,11933,11935,11937,11939,11942,11941,11901,11944,11946,11947,11948,11952 ,11954,11956,11957,11958,11978,11959,11960,11963,11962,11964,11965,11966,11970,11968,11971,11972,11792,11975,11976,11977,10026,10027,10030,10037,10039,10001,10011,10018,10019,10020,10036,10029,10035,10010,10016,10017,10022,10012,10013,10014,10004,10005,10006,10007,10038,10280,10002,10003,10009,10021,10028,10044,10138,10023,10024,10025,10031,10032,10033,10034,10040];
     
    if (jQuery.inArray(zip, valid_zips) > -1 && fc_json.product_count > 6) {
      // In valid zips and has more than 6 products
      FC.customLiveShipping.show(60);
    }
    
    		 
    		/* END CUSTOM LOCATION LOGIC */
     
    		FC.locations.updateFoxyComplete(true);
    	});
    	//]]>
    </script>
     
    <script type="text/javascript" charset="utf-8">
    	//<![CDATA[
    	// Country/State Helper Functions v1.1
    	// Do not modify the following functions
     
    	FC.locations.removeCountries = function(countries, locationArrayNames) {
    		if (typeof countries == "undefined") { return false }
    		if (typeof countries == "string") { countries = [countries]; }
    		locationArrayNames = FC.locations.validateLocationArrayNames(locationArrayNames);
     
    		for (l in locationArrayNames) {
    			var locationArray = FC.locations.getLocationArray(locationArrayNames[l]);
    			for (var c in countries) {
    				if (typeof locationArray[countries[c]] == "undefined") { break; }
    				delete locationArray[countries[c]];
    			}
    		}
     
    		return true;
    	}
     
    	FC.locations.limitCountriesTo = function(countries, locationArrayNames) {
    		if (typeof countries == "undefined") { return false }
    		if (typeof countries == "string") { countries = [countries]; }
    		locationArrayNames = FC.locations.validateLocationArrayNames(locationArrayNames);
     
    		for (l in locationArrayNames) {
    			var newLocations = {};
    			var locationArray = FC.locations.getLocationArray(locationArrayNames[l]);
    			for (var c in countries) {
    				if (typeof locationArray[countries[c]] == "undefined") { break; }
    				newLocations[countries[c]] = locationArray[countries[c]];
    			}
     
    			// Prevent the countries being set to nothing
    			if (newLocations == {}) { return false; }
     
    			if (locationArrayNames[l] == "customer") {
    				FC.locations.config.locations = newLocations;
    			} else {
    				FC.locations.config.shippingLocations = newLocations;
    			}
    		}
    		return true;
    	}
     
    	FC.locations.removeStates = function(country, states, locationArrayNames) {
    		if (typeof country == "undefined" || typeof states == "undefined") { return false }
    		if (typeof states == "string") { states = [states]; }
    		locationArrayNames = FC.locations.validateLocationArrayNames(locationArrayNames);
     
    		for (l in locationArrayNames) {
    			var locationArray = FC.locations.getLocationArray(locationArrayNames[l]);
    			if (typeof locationArray[country] == "undefined") { return false; }
    			for (var s in states) {
    				if (typeof locationArray[country].r[states[s]] == "undefined") { break; }
    				delete locationArray[country].r[states[s]];
    			}
    		}
    		return true;
    	}
     
    	FC.locations.limitStatesTo = function(country, states, locationArrayNames) {
    		if (typeof country == "undefined" || typeof states == "undefined") { return false }
    		if (typeof states == "string") { states = [states]; }
    		locationArrayNames = FC.locations.validateLocationArrayNames(locationArrayNames);
     
    		for (l in locationArrayNames) {
    			var newLocations = {};
    			var locationArray = FC.locations.getLocationArray(locationArrayNames[l]);
    			if (typeof locationArray[country] == "undefined") { return false; }
    			for (var s in states) {
    				if (typeof locationArray[country].r[states[s]] == "undefined") { break; }
    				newLocations[states[s]] = locationArray[country].r[states[s]];
    			}
     
    			if (locationArrayNames[l] == "customer") {
    				FC.locations.config.locations[country].r = newLocations;
    			} else {
    				FC.locations.config.shippingLocations[country].r = newLocations;
    			}
    		}
    		return true;
    	}
     
    	FC.locations.updateFoxyComplete = function(blockErrors) {
    		FC.checkout.config.evaluateAjaxRequests = false;
     
    		FC.checkout.setAutoComplete("customer_country");
    		if (jQuery("#customer_country_name") != "") {
    			FC.checkout.validateLocationName("customer_country");
    		}
    		if (jQuery("#customer_state_name").val() != "") {
    			FC.checkout.validateLocationName("customer_state");
    		}
    		if (blockErrors) {
    			FC.checkout.updateErrorDisplay("customer_country_name", false);
    			FC.checkout.updateErrorDisplay("customer_state_name", false);
    		}
    		if (!FC.checkout.config.hasMultiship) {
    			FC.checkout.setAutoComplete("shipping_country");
    			if (jQuery("#shipping_country_name") != "") {
    				FC.checkout.validateLocationName("shipping_country");
    			}
    			if (jQuery("#shipping_state_name") != "") {
    				FC.checkout.validateLocationName("shipping_state");
    			}
    			if (blockErrors) {
    				FC.checkout.updateErrorDisplay("shipping_country_name", false);
    				FC.checkout.updateErrorDisplay("shipping_state_name", false);
    			}
     
    			FC.checkout.config.evaluateAjaxRequests = true;
    			FC.checkout.updateShipping(-1);
    			FC.checkout.updateTaxes(-1);
    		} else {
    			for (var i = 0; i < FC.checkout.config.multishipDetails.length; i++) {
    				FC.checkout.setAutoComplete("shipto_" + i + "_country");
    				if (jQuery("#shipto_" + i + "_country_name") != "") {
    					FC.checkout.validateLocationName("shipto_" + i + "_country");
    				}
    				if (jQuery("#shipto_" + i + "_state_name") != "") {
    					FC.checkout.validateLocationName("shipto_" + i + "_state");
    				}
    				if (blockErrors) {
    					FC.checkout.updateErrorDisplay("shipto_" + i + "_country_name", false);
    					FC.checkout.updateErrorDisplay("shipto_" + i + "_state_name", false);
    				}
    			}
     
    			FC.checkout.config.evaluateAjaxRequests = true;
    			for (var i = 0; i < FC.checkout.config.multishipDetails.length; i++) {
    				FC.checkout.updateShipping(i);
    				FC.checkout.updateTaxes(i);
    			}
    		}
    	}
     
    	FC.locations.getLocationArray = function(locationArrayNames) {
    		return (locationArrayNames == "customer") ? FC.locations.config.locations : FC.locations.config.shippingLocations;
    	}
     
    	FC.locations.validateLocationArrayNames = function(locationArrayNames) {
    		if (typeof locationArrayNames == "undefined" || locationArrayNames == "" || locationArrayNames == "both") { locationArrayNames = ["customer", "shipping"]; }
    		if (typeof locationArrayNames == "string") { locationArrayNames = [locationArrayNames]; }
    		return locationArrayNames;
    	}
    	//]]>
    </script>
    
    
    <script>
    
    //<![CDATA[
     
      FC.customLiveShipping = {}
     
      FC.customLiveShipping.config = {
        autoSelect: true  // Set to true if you'd like the top shipping option to be automatically selected for the user
      };
     
      FC.customLiveShipping.logic = function() {
        /* BEGIN CUSTOM SHIPPING LOGIC */
    
        var beverages  = 0;
        var multiplier = 1
        for ( p in fc_json.products ) {
          switch ( fc_json.products[p].category ) {
            case "BEVERAGE":
              beverages += fc_json.products[p].quantity;
              break;
          }
        }
    
        if ( beverages > 0 ) { 
          multiplier = Math.ceil( beverages / 6 ); // 1-6 > 1, 7-12 > 2, 13-18 > 3, etc
          FC.customLiveShipping.update('all', '+' + ( multiplier * 13 ) );
        }
         
     
        /* END CUSTOM SHIPPING LOGIC */
      }
     
      //]]>
    </script>
     
      /**
    
    //]]>
    
    </script>
    
  • fc_adamfc_adam FoxyCart Team
    @davidzupec,

    It's not working for a couple reasons there. Firstly, it doesn't look like you've included the live rates shipping modification snippet as a whole. Secondly, you've put the custom logic we discussed earlier along with the locations modification section. You'll need to put the live rates logic inside the FC.customLiveShipping.logic function. Finally, you've also got a closing script tag at the end there that doesn't match up to anything.

    If you fix those things, it should start working for you then. If not, if you could confirm the store you're working with, I can take a closer look.
  • Hey Adam, hmmm I made those changes and for some reason It's still not working! Here's my store if you could take a look whenever you have a chance, thank you! captainsneck.foxycart.com
  • fc_adamfc_adam FoxyCart Team
    @davidzupec,

    Ah - you don't have the free option enabled for your store. You'll need to check the 'custom' shipping option group and enable 'free ground shipping'.
  • Hey Adam, I went in and did that and thought that was going to work but unfortunately no luck yet!
  • I seen on a previous post of yours, you had the person change this line:
    jQuery.inArray(zip, valid_zips)
    
    To this :
    jQuery.inArray(parseInt(zip), valid_zips)
    

    Would that be the problem?
  • fc_adamfc_adam FoxyCart Team
    @davidzupec,

    Ah - great catch, yeah that looks like it!
  • davidzupecdavidzupec Member
    edited August 2014
    Hey Adam, that worked but unfortunately it shows free ground shipping to all zip codes. It should be just the restricted zip codes. Also I added just 1 item to the cart and the "Free Ground Shipping" displayed but it shouldn't have because the customer needs to have 6 or more items to get the free shipping.
  • fc_adamfc_adam FoxyCart Team
    @davidzupec,

    Ok - one more thing hopefully that I just noticed - you're missing an opening bracket on this line:
    if jQuery.inArray(parseInt(zip), valid_zips) > -1 && fc_json.product_count > 6) {
    

    It should be:
    if (jQuery.inArray(parseInt(zip), valid_zips) > -1 && fc_json.product_count > 6) {
    
  • davidzupecdavidzupec Member
    edited August 2014
    Hey Adam, that did it and it worked but when I added 8 items it showed free ground shipping with a cost then all the other shipping options.

    It worked fine when I just put it 6 for the quantity but when I put in more it gives me the options I mentioned above?
  • Hey Adam, would the error that I mentioned above have something to do with this logic that's in the live shipping modification as well?
    var beverages  = 0;
        var multiplier = 1
        for ( p in fc_json.products ) {
          switch ( fc_json.products[p].category ) {
            case "BEVERAGE":
              beverages += fc_json.products[p].quantity;
              break;
          }
        }
    
        if ( beverages > 0 ) { 
          multiplier = Math.ceil( beverages / 6 ); // 1-6 > 1, 7-12 > 2, 13-18 > 3, etc
          FC.customLiveShipping.update('all', '+' + ( multiplier * 13 ) );
        }
    
  • fc_adamfc_adam FoxyCart Team
    @davidzupec,

    Yeah - that will be adding a cost to the free option. You can fix that by updating it like this:
    var beverages  = 0;
        var multiplier = 1
        for ( p in fc_json.products ) {
          switch ( fc_json.products[p].category ) {
            case "BEVERAGE":
              beverages += fc_json.products[p].quantity;
              break;
          }
        }
     
        if ( beverages > 0 ) { 
          multiplier = Math.ceil( beverages / 6 ); // 1-6 > 1, 7-12 > 2, 13-18 > 3, etc
          FC.customLiveShipping.update('all', '+' + ( multiplier * 13 ) );
          FC.customLiveShipping.update(60, 0);
        }
    
  • Hey Adam, we're getting closer! It did show the free shipping at $0 cost but it still displayed the other shipping options below that. Will that be possible to remove?
  • fc_adamfc_adam FoxyCart Team
    @davidzupec,

    Just to make sure I'm understanding you correctly - if the free shipping option is displayed, you only want that displayed, no other rates. Is that right?
  • davidzupecdavidzupec Member
    edited August 2014
    Hey Adam, that is correct! When I added 6 items to the cart it only displays the free shipping option (which is what I want), but when I add more than 6 it displays the other shipping options which I don't want.
  • fc_adamfc_adam FoxyCart Team
    @davidzupec,

    Update this part:
    if (jQuery.inArray(parseInt(zip), valid_zips) > -1 && fc_json.product_count > 6) {
      // In valid zips and has more than 6 products
      FC.customLiveShipping.show(60);
    }
    

    to instead look like this:
    if (jQuery.inArray(parseInt(zip), valid_zips) > -1 && fc_json.product_count > 6) {
      // In valid zips and has more than 6 products
      FC.customLiveShipping.hide('all');
      FC.customLiveShipping.show(60);
    }
    

    That will hide all the rates and just display the free one when it's allowed to be displayed.
  • Hey Adam, great I will implement this and thank you so much again for all your help, very much appreciated!

    David
  • Hey adam a quick question... would I be able to add a coupon promo code for free shipping regardless of quantity that would also apply to only those zip codes? So on the cart if they added the promo code "Free" they would get free shipping regardless of quantity. I've added the appropriate code to my cart and have this in my checkout but it doesn't seem to be working correctly:
    <script type="text/javascript">
    FCcode = "fs";
    FConly = true;
    
    		var zip = (jQuery("#use_different_addresses").is(":checked") ? $("#shipping_postal_code").val() : $("#customer_postal_code").val());
    		var valid_zips = [11980,11931,11932,11933,11935,11937,11939,11942,11941,11901,11944,11946,11947,11948,11952,11954,11956,11957,11958,11978,11959,11960,11963,11962,11964,11965,11966,11970,11968,11971,11972,11792,11975,11976,11977,10026,10027,10030,10037,10039,10001,10011,10018,10019,10020,10036,10029,10035,10010,10016,10017,10022,10012,10013,10014,10004,10005,10006,10007,10038,10280,10002,10003,10009,10021,10028,10044,10138,10023,10024,10025,10031,10032,10033,10034,10040];
     
    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 (jQuery.inArray(parseInt(zip), valid_zips) > -1 && 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']").show();
      }
    }
    

  • fc_adamfc_adam FoxyCart Team
    @davizupec,

    Actually you wouldn't need another snippet in this case - you'd want to actually roll it into your existing shipping logic.

    Change this:
    if (jQuery.inArray(parseInt(zip), valid_zips) > -1 && fc_json.product_count > 6) {
      // In valid zips and has more than 6 products
      FC.customLiveShipping.hide('all');
      FC.customLiveShipping.show(60);
    }
    


    To this (changing "free shipping" to match all or part of the name of your free shipping coupon):
    if (jQuery.inArray(parseInt(zip), valid_zips) > -1) {
      var hasCoupon = false;
      if(fc_json.hasOwnProperty('coupons')) {
        jQuery.each(fc_json.coupons, function(i, coupon){
          if(coupon.name.search(/free shipping/i) > -1) {
            hasCoupon = true;
          }
        });
      }
    
      if (fc_json.product_count > 6 || hasCoupon) {
        // In valid zips and has more than 6 products or a free ship coupon
        FC.customLiveShipping.hide('all');
        FC.customLiveShipping.show(60);
      }
    }
    
  • davidzupecdavidzupec Member
    edited August 2014
    Hey adam, I revised the code to match yours and for some reason it didn't work. After I submitted one of the restricted zip codes upon checkout it just displayed the live shipping rates instead! Here's is my entire code for that:
    <script>
    
    //<![CDATA[
     
      FC.customLiveShipping = {}
     
      FC.customLiveShipping.config = {
        autoSelect: true  // Set to true if you'd like the top shipping option to be automatically selected for the user
      };
     
      FC.customLiveShipping.logic = function() {
        /* BEGIN CUSTOM SHIPPING LOGIC */
    
    		var beverages  = 0;
        var multiplier = 1
        for ( p in fc_json.products ) {
          switch ( fc_json.products[p].category ) {
            case "BEVERAGE":
              beverages += fc_json.products[p].quantity;
              break;
          }
        }
     
        if ( beverages > 0 ) { 
          multiplier = Math.ceil( beverages / 6 ); // 1-6 > 1, 7-12 > 2, 13-18 > 3, etc
          FC.customLiveShipping.update('all', '+' + ( multiplier * 13 ) );
          FC.customLiveShipping.update(60, 0);
        }    
    		
    		FC.customLiveShipping.hide(60);
    		 
    		var zip = (jQuery("#use_different_addresses").is(":checked") ? $("#shipping_postal_code").val() : $("#customer_postal_code").val());
    		var valid_zips = [11980,11931,11932,11933,11935,11937,11939,11942,11941,11901,11944,11946,11947,11948,11952,11954,11956,11957,11958,11978,11959,11960,11963,11962,11964,11965,11966,11970,11968,11971,11972,11792,11975,11976,11977,10026,10027,10030,10037,10039,10001,10011,10018,10019,10020,10036,10029,10035,10010,10016,10017,10022,10012,10013,10014,10004,10005,10006,10007,10038,10280,10002,10003,10009,10021,10028,10044,10138,10023,10024,10025,10031,10032,10033,10034,10040];
    		 
    		if (jQuery.inArray(parseInt(zip), valid_zips) > -1) {
    		  var hasCoupon = false;
    		  if(fc_json.hasOwnProperty('coupons')) {
    		    jQuery.each(fc_json.coupons, function(i, coupon){
    		      if(coupon.name.search(/Neighbor/i) > -1) {
    		        hasCoupon = true;
    		      }
    		    });
    		  }
    		 
    		  if (fc_json.product_count > 5 || hasCoupon) {
    		    // In valid zips and has more than 5 products or a free ship coupon
    		    FC.customLiveShipping.hide('all');
    		    FC.customLiveShipping.show(60);
    		  }
    		}     
    		
        /* END CUSTOM SHIPPING LOGIC */
      }
     
      //]]>
    </script>
    
  • fc_adamfc_adam FoxyCart Team
    @davidzupec,

    I just tested out your checkout, and with 6 or more products, it works fine. You've entered "neighbor" for the coupon matching - but your coupon name doesn't include the string "neighbor" when I look at the coupons for your store. If you update that to match a portion of the coupon name, it should work.
  • Hi Adam, Sorry but I'm not sure what you mean regarding the string? I have the coupon set to be Neighbor in my Cart...
    <script type="text/javascript">
    FCcode = "fs";
    FCtoken = "Arvtuobe";
     
    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>
    
  • Hey Adam, I also went into my admin and created that coupon but still no luck!
  • fc_adamfc_adam FoxyCart Team
    @davidzupec,

    The other snippet you're utilising on your cart - you don't actually need that for the code I suggested - in fact that's actually the reason it's not working. That snippet you're utilising essentially fakes a coupon request, where as the approach I'm suggesting uses an actual traditional coupon and triggers off of that for the shipping logic.

    Try removing that snippet from your cart and trying again.
Sign In or Register to comment.