# Custom Shipping Rate Based on Product Category

Member
in Help edited November 2012
I need to implement a custom shipping rate based on whether an order contains items of a certain category. If it doesn't, a standard flat-rate will apply.

Specifics:

If the order includes any items within the "coffee" category, the shipping price should be calculated as follows: 1 coffee item = \$5 flat rate, <=5 coffee items = \$11 flat rate, >6 coffee items = free. Note: This shipping rate applies to the entire, so ordering 6 coffee items makes the entire purchase (including non-coffee items) ship free-of-charge.

If the order does not include any items within the "coffee" category, the order should have a \$12 flat-rate charge.

Any help implementing this would be much appreciated.

Here's the code:
```/* BEGIN CUSTOM SHIPPING LOGIC */
var hasCoffee = false;
var amount = fc_json.product_count;
for (var p in fc_json.products) {
if (fc_json.products[p].category == "coffee") {
hasCoffee = true;
}
}
if (hasCoffee) {
if (amount == 1) {
shippingCost += 5 ; // \$5 for one coffee product
} else if (amount < 6) {
shippingCost += 11; // \$11 for less than 6 coffee products
} else { // free for more than 6 coffee products
shippingCost = 0; // Free shipping because they bought so much
}
}
});

/* END CUSTOM SHIPPING LOGIC */
```
Tagged:
• FoxyCart Team
edited November 2012

I'd modify your script as follows:
```/* BEGIN CUSTOM SHIPPING LOGIC */
shippingCost = 12;

var coffeeProducts = 0;
for (var p in fc_json.products) {
if (fc_json.products[p].category == "coffee") {
coffeeProducts += fc_json.products[p].quantity;

}
}

if (coffeeProducts > 0) {
if (coffeeProducts == 1) {
shippingCost = 5 ; // \$5 for one coffee product
} else if (coffeeProducts < 6) {
shippingCost = 11; // \$11 for less than 6 coffee products
} else { // free for more than 6 coffee products
shippingCost = 0; // Free shipping because they bought so much
}
}
/* END CUSTOM SHIPPING LOGIC */
```

• Member
edited November 2012
Thanks! That worked perfectly. I'm really impressed with the FC support.

So, if these rates should be adjusted based on whether the shipping address is within the US or Canada, do I just create another conditional statement?
• FoxyCart Team

Yeah, you'd add an if/else block as required.
• Member
Thanks!
• Member
edited November 2012
I did two things: (a) added an if statement to set the shipping to a flat rate if a coupon is used and (b) added custom a custom country code switch statement. The first one (a) works, the second one (b) does not.

Any thoughts?

Here is my code:
```/* BEGIN CUSTOM SHIPPING LOGIC */
shippingCost = 12;

var coffeeProducts = 0;
for (var p in fc_json.products) {
if (fc_json.products[p].category == "coffee") {
coffeeProducts += fc_json.products[p].quantity;

}
}

if (coffeeProducts > 0) {
if (coffeeProducts == 1) {
shippingCost = 5 ; // \$5 for one coffee product
} else if (coffeeProducts < 6) {
shippingCost = 11; // \$11 for less than 6 coffee products
} else { // free for more than 6 coffee products
shippingCost = 0; // Free shipping because they bought so much
}
}

if (fc_json.hasOwnProperty('coupons')) {
shippingCost = 11;
}

if (typeof(country_code) === "undefined") {country_code = "";}
new_country_code = (jQuery("#use_different_addresses").is(":checked") ? \$("#shipping_country").val() : \$("#customer_country").val());
if (country_code != new_country_code) { // The shipping country has changed!
country_code = new_country_code;
switch (country_code) {
case "CA":
shippingCost = 32.95;
break;
default:
shippingCost = shippingCost;
}
}

/* END CUSTOM SHIPPING LOGIC */
```
• FoxyCart Team
Just wanted to let you know that we are looking at your code to see why it is not fully working. Some of our team is on the road today, but someone will respond soon.

Thanks,
Josh
• Member
edited November 2012
Thanks for the update.
• FoxyCart Team

Could you link us to your checkout where this is included please? I'd like to see it in action how you've included it if possible.
• Member
Sent via whisper.
• FoxyCart Team

So the issue is that the code doesn't know to run when the location changes. In your code, set the "onLocationChange" variable to true. That should work fine for you, but I'd suggest switching your country code to this:
```country_code = (jQuery("#use_different_addresses").is(":checked") ? \$("#shipping_country").val() : \$("#customer_country").val());
console.log(country_code);
switch (country_code) {
case "CA":
shippingCost = 32.95;
break;
}
```

That just simplifies it a bit for what you need.
• Member
Worked like a charm, thanks!
• Member
This is an older thread, but I've been using it to try and figure out how to do something similar with two categories instead of one. My shipping is free for everything else except the posters & stickers categories.

For posters; \$5 shipping for one poster, \$3 shipping per poster if you buy 2 or more.
For stickers; \$1.50 shipping per stickers (we actually sell them in three sticker packs, but consider that one sticker product)

I've tried pulling the quantities for each individual category, multiple the category quantity by the category price, and then tried adding the two separate category prices together to equal the total shippingCost.

I'm also a complete javascript noob and have to bumble my way through it to try to get it to work, so bare with me.

here's what I have... and it doesn't work

:
```/* BEGIN CUSTOM SHIPPING LOGIC */

var posterProducts = 0;
var posterAmount = 0;
var posterShipping = 0;
var stickerProducts = 0;
var stickerAmount = 0;
var stickerShipping = 0;

for (var p in fc_json.products) {
if (fc_json.products[p].category == "posters") {
posterProducts += fc_json.products[p].quantity;
posterAmount += fc_json.products[p].quantity;
}
}

for (var p in fc_json.products) {
if (fc_json.products[p].category == "stickers") {
stickerProducts += fc_json.products[p].quantity;
stickerAmount += fc_json.products[p].quantity;
}
}

if (posterProducts > 0) {
if (posterProducts == 1) {
posterShipping = 5; // \$5 for one poster
} else if (posterProducts > 1) {
posterShipping = 3 * posterAmount; // \$3 for each poster
}
}

if (stickerProducts > 0) {
stickerShipping = 1.5 * stickerAmount;
)

shippingCost = paseFloat(posterShipping) + parseFloat(stickerShipping);

/* END CUSTOM SHIPPING LOGIC */
```

Any help would be greatly appreciated.
• FoxyCart Team
@CPavel,

You can simplify what you had to this:
```/* BEGIN CUSTOM SHIPPING LOGIC */

var posterProducts = 0;
var stickerProducts = 0;

for (var p in fc_json.products) {
if (fc_json.products[p].category == "posters") {
posterProducts += fc_json.products[p].quantity;
}

if (fc_json.products[p].category == "stickers") {
stickerProducts += fc_json.products[p].quantity;
}
}

if (posterProducts > 0) {
if (posterProducts == 1) {
shippingCost += 5; // \$5 for one poster
} else if (posterProducts > 1) {
shippingCost += 3 * posterProducts; // \$3 for each poster
}
}

shippingCost += 1.5 * stickerProducts;

/* END CUSTOM SHIPPING LOGIC */
```

But what you had should be working fine as well - could you link me to your site so I can see it in action please?
• Member
Thanks for the super quick response! I just implemented the code you posted and it works!

I think I had goofed something on the actual cart page and didn't have the exact code that I pasted in the forum.
• FoxyCart Team
edited March 2013
@CPavel,

Awesome - glad it worked! Great looking site too!