less than a minute read • Updated 11 minutes ago

Custom Shipping Code Examples

Ready to use code snippets to get started with your Custom Shipping Code.


Overview

These examples cover the most common shipping scenarios you can implement with Custom Shipping Code. Each one is self contained and can be pasted directly into the code editor in your Foxy admin. Combine and adapt them to fit your store's needs.

All examples use the two globals available in Custom Shipping Code: rates (the shipping rates collection) and cart (the cart payload). For the full API reference, see [Custom Shipping Code API Reference]. For the complete payload structure, see [Shipping Payload Reference].


Add a fallback rate

If no carriers return rates (for example, because of a network issue or unsupported destination), you can add a fallback so customers always have at least one option:

if (!rates.exists()) {
  rates.add(10001, 15, '', 'Standard Shipping');
}

Free shipping above a cart total

Add standard and express options, then make standard free when the cart subtotal reaches a threshold:

rates.add(10001, 5, 'FoxyPost', 'Standard');
rates.add(10002, 15, 'FoxyPost', 'Express');

if (cart['_embedded']['fx:shipment']['total_item_price'] >= 40) {
  rates.filter(10001).price(0).service('Free Shipping');
}

Tiered rates by cart total

Set different price points based on how much the customer is spending:

const total = cart['_embedded']['fx:shipment']['total_item_price'];
rates.add(10001, 75, 'FoxyPost', 'Standard');

if (total <= 200)       rates.filter(10001).price(0).service('Customer Pickup');
else if (total <= 500)  rates.filter(10001).price(75);
else if (total <= 1000) rates.filter(10001).price(150);
else                    rates.filter(10001).price(300);

Adjust rates by weight

Change prices when the total weight exceeds a threshold:

rates.add(10001, 5, 'FoxyPost', 'Standard');
rates.add(10002, 9.45, 'FoxyPost', 'Priority');
rates.add(10003, 10, 'FoxyPost', 'Express (Next Day)');

if (cart['_embedded']['fx:shipment']['total_weight'] > 10) {
  rates.filter(10001).price(6);
  rates.filter(10002).price(10);
  rates.filter(10003).price(11.99);
}

Hide a rate by item count

Remove an option when there are too many items (for example, disabling express for large orders):

rates.add(10001, 5, 'FoxyPost', 'Standard');
rates.add(10002, 9.45, 'FoxyPost', 'Priority');
rates.add(10003, 10, 'FoxyPost', 'Express (Next Day)');

if (cart['_embedded']['fx:shipment']['item_count'] > 5) {
  rates.filter(10003).hide();
}

Free shipping with a coupon code

Check for a specific coupon code (or any code ending in -fs) and replace all rates with a free option:

const discounts = cart['_embedded']['fx:discounts'];
for (const d in discounts) {
  const code = discounts[d]['code'];
  if (code === 'freeshipping' || code.match(/-fs$/i)) {
    rates.hide();
    rates.add(11000, 0, '', 'Free Shipping');
  }
}

Country based tiered rates

Group countries into tiers and set a different rate for each:

const tier1 = ['GB'];
const tier2 = ['AL','AD','AT','BE','BG','CH','CZ','DE','DK','EE','ES','FI','FR','GR','HU','HR','IE','IS','IT','LT','LU','LV','NL','NO','PL','PT','RO','SE','SI','SK'];

const country = cart['_embedded']['fx:shipment']['country'];

if (tier1.includes(country))      rates.add(10001, 10, 'FoxyPost', 'Standard');
else if (tier2.includes(country)) rates.add(10002, 20, 'FoxyPost', 'International');
else                               rates.add(10003, 30, 'FoxyPost', 'International');

Replace international rates with a flat rate

Hide all carrier rates for non domestic shipments and show a single custom rate instead:

if (cart['_embedded']['fx:shipment']['country'] !== 'US') {
  rates.hide();
  rates.add(10001, 25, 'FoxyPost', 'Standard');
}

Modify carrier rate labels

Append text to all rates from a specific carrier (useful for adding notes like "Signature Required"):

rates.filter('fedex').each(function() {
  this.service(this.service() + ' (Signature Required)');
});

Add a surcharge to all rates

Apply a flat handling surcharge on top of whatever rates are already present:

rates.price('+3.50');

Or a percentage:

rates.price('+15%');

Only show rates from one carrier

If you have multiple carriers enabled but want to limit what the customer sees based on a condition:

if (cart['_embedded']['fx:shipment']['country'] === 'US') {
  rates.filter('fedex').hide();
} else {
  rates.filter('usps').hide();
}

Block shipping to specific countries

Return an error instead of rates for unsupported destinations:

const blocked = ['CU', 'IR', 'KP', 'SY'];
const country = cart['_embedded']['fx:shipment']['country'];

if (blocked.includes(country)) {
  rates.error('Sorry, we are unable to ship to your country.');
}

Category specific surcharges

Check what categories are in the cart and adjust rates accordingly. Each item has an embedded category code:

const items = cart['_embedded']['fx:items'];
const country = cart['_embedded']['fx:shipment']['country'];

const hasFragile = items.some(item => item['_embedded']['fx:item_category']['code'] === 'fragile');
const hasOversized = items.some(item => item['_embedded']['fx:item_category']['code'] === 'oversized');

let baseRate = 7.99;
if (hasFragile) baseRate += 5;
if (hasOversized) baseRate += 10;

rates.add(10001, baseRate, 'Shipping', 'Standard');

// Only offer express for non oversized domestic orders
if (!hasOversized && country === 'US') {
  rates.add(10002, baseRate + 8, 'Shipping', 'Express');
}

Weight based tiered pricing with international markup

Combine weight tiers with a multiplier for international shipments:

const totalWeight = cart['_embedded']['fx:shipment']['total_weight'];
const country = cart['_embedded']['fx:shipment']['country'];

let standardPrice = 5;
let expressPrice = 12;

if (totalWeight > 20) {
  standardPrice = 15;
  expressPrice = 30;
} else if (totalWeight > 10) {
  standardPrice = 10;
  expressPrice = 20;
} else if (totalWeight > 5) {
  standardPrice = 7.50;
  expressPrice = 15;
}

// Double the price for international
if (country !== 'US') {
  standardPrice *= 2;
  expressPrice *= 2;
}

rates.add(10001, standardPrice, 'Shipping', 'Standard');
rates.add(10002, expressPrice, 'Shipping', 'Express');

Per item pricing (base + additional items)

Charge a base rate for the first item plus a smaller amount for each additional item:

const shipment = cart['_embedded']['fx:shipment'];
const itemCount = shipment['item_count'];
const country = shipment['country'];

if (country === 'US') {
  const standardCost = 10 + ((itemCount - 1) * 0.50);
  const expressCost = 12 + ((itemCount - 1) * 1.50);
  rates.add(10001, standardCost, 'FoxyPost', 'Standard');
  rates.add(10002, expressCost, 'FoxyPost', 'Express');
} else {
  const intlCost = 15 + ((itemCount - 1) * 2);
  rates.add(10003, intlCost, 'FoxyPost', 'International');
}

Per product shipping cost via item options

If products carry their own shipping cost as a hidden item option named "shipping," sum them up:

let productShipping = 0;
const items = cart['_embedded']['fx:items'];

for (const item of items) {
  if (item['_embedded'] && item['_embedded']['fx:item_options']) {
    for (const option of item['_embedded']['fx:item_options']) {
      if (option['name'] === 'shipping' && !isNaN(parseFloat(option['value']))) {
        productShipping += parseFloat(option['value']) * item['quantity'];
      }
    }
  }
}

if (productShipping > 0) {
  if (rates.exists()) {
    rates.price('+' + productShipping);
  } else {
    rates.add(10001, productShipping, '', 'Standard Shipping');
  }
}

Category based shipping lookup table

Map each category to a per item shipping cost:

const categoryRates = {
  'business-cards': 20,
  'letterheads': 35,
  'envelopes': 35,
  'banners': 15,
  't-shirts': 25,
};

let shipping = 0;
for (const item of cart['_embedded']['fx:items']) {
  const categoryCode = item['_embedded']['fx:item_category']['code'];
  if (categoryRates[categoryCode]) {
    shipping += item['quantity'] * categoryRates[categoryCode];
  }
}

if (shipping > 0) {
  rates.add(10001, shipping, '', 'Standard Shipping');
} else {
  rates.error("Sorry, we're unable to calculate shipping. Please contact us.");
}

Free shipping for a specific category

Check if all items belong to a promotional category and offer free shipping:

const items = cart['_embedded']['fx:items'];
const country = cart['_embedded']['fx:shipment']['country'];

const allPromo = items.every(item => item['_embedded']['fx:item_category']['code'] === 'promo');

if (allPromo && country === 'US') {
  rates.hide();
  rates.add(10001, 0, '', 'Free Promotional Shipping');
} else {
  if (!rates.exists()) {
    rates.add(10001, 7.99, 'Shipping', 'Standard');
  }
}

Free domestic shipping, paid international

Combine a domestic free shipping threshold with separate international rates:

const country = cart['_embedded']['fx:shipment']['country'];
const totalPrice = cart['_embedded']['fx:shipment']['total_item_price'];

if (country === 'US') {
  if (totalPrice >= 50) {
    rates.add(10001, 0, '', 'Free Shipping');
  } else {
    rates.add(10001, 5.99, 'Shipping', 'Standard');
  }
  rates.add(10002, 14.99, 'Shipping', 'Express');
} else {
  rates.add(10003, 19.99, 'Shipping', 'International Standard');
  rates.add(10004, 34.99, 'Shipping', 'International Express');
}

Percentage markup on carrier rates

Apply a markup to rates from a specific carrier:

// 15% markup on all USPS rates
rates.filter('USPS').price('*1.15');

// Flat $3 surcharge on FedEx only
rates.filter('FedEx').price('+3');

Discount specific carrier services

// 20% discount on ground shipping
rates.filter('Ground').price('*0.8');

// Subtract $2 from Priority Mail
rates.filter('USPS Priority').price('-2');

Hide specific carrier services

// Hide all FedEx rates
rates.filter('FedEx').hide();

// Hide express and overnight options
rates.filter('Express').hide();
rates.filter('Overnight').hide();

Hide expensive rates by price

Filter out any rate above a threshold:

rates.filter('FedEx').each(function() {
  if (this.price() > 100) {
    this.hide();
  }
});

Hide rates by state or region

Restrict certain shipping methods based on the customer's state or region. This example hides express and overnight options for non contiguous US states, but the same pattern works for any region based rule:

const contiguous = [
  'AL','AZ','AR','CA','CO','CT','DE','FL','GA','ID','IL','IN','IA','KS',
  'KY','LA','ME','MD','MA','MI','MN','MS','MO','MT','NE','NV','NH','NJ',
  'NM','NY','NC','ND','OH','OK','OR','PA','RI','SC','SD','TN','TX','UT',
  'VT','VA','WA','WV','WI','WY','DC'
];

const country = cart['_embedded']['fx:shipment']['country'];
const region = cart['_embedded']['fx:shipment']['region'];

if (country === 'US' && !contiguous.includes(region)) {
  rates.filter('Express').hide();
  rates.filter('Overnight').hide();
}

Restrict shipping methods by category

If certain product categories require specific shipping methods (for example, perishable items that must ship express), hide the methods that don't apply:

const items = cart['_embedded']['fx:items'];
const hasPerishable = items.some(item =>
  item['_embedded']['fx:item_category']['code'] === 'perishable'
);

if (hasPerishable) {
  rates.filter('Ground').hide();
  rates.filter('Standard').hide();

  if (!rates.exists('Express')) {
    rates.add(10001, 24.99, 'Express Shipping', 'Required for Perishable Items');
  }
}

Restrict shipping methods by item option

If products carry an option flag (for example, a "type" option set to "hazmat"), restrict which shipping methods are available:

let hasHazmat = false;
for (const item of cart['_embedded']['fx:items']) {
  for (const option of (item['_embedded']['fx:item_options'] || [])) {
    if (option['name'] === 'type' && option['value'].toLowerCase() === 'hazmat') {
      hasHazmat = true;
    }
  }
}

if (hasHazmat) {
  rates.hide();
  rates.filter('Ground').show();
  rates.filter('Home Delivery').show();
}

Click and collect / in store pickup

Always offer pickup, plus delivery with a free threshold:

rates.add(10001, 0, '', 'Pickup From Store');

const totalPrice = cart['_embedded']['fx:shipment']['total_item_price'];
if (totalPrice >= 50) {
  rates.add(10002, 0, '', 'Free Delivery');
} else {
  rates.add(10002, 7.99, '', 'Standard Delivery');
}

Postal code zone based local delivery

Define ZIP code zones for free, paid, or pickup only delivery:

const postalCode = Number(cart['_embedded']['fx:shipment']['postal_code']);
const country = cart['_embedded']['fx:shipment']['country'];

const localDeliveryZips = [80001, 80002, 80003, 80004, 80005];
const extendedDeliveryZips = [80023, 80026, 80027, 80301, 80302];

if (country === 'US') {
  if (localDeliveryZips.includes(postalCode)) {
    rates.add(10001, 0, '', 'Free Local Delivery');
  }
  if (extendedDeliveryZips.includes(postalCode)) {
    rates.add(10002, 5, '', 'Extended Delivery');
  }
  // Always offer pickup
  rates.add(10003, 0, '', 'In Store Pickup');
}

Local delivery by postal code prefix

Use the first few characters of the postal code to define local delivery zones. This works for any country with alphanumeric postal codes (Canada, UK, etc.):

const freeDeliveryPrefixes = ['L5H', 'L4T', 'L4W', 'L4X', 'L4Y', 'L4Z', 'L5A', 'L5B'];
const postcode = cart['_embedded']['fx:shipment']['postal_code'].toUpperCase().substring(0, 3);
const orderTotal = cart['_embedded']['fx:shipment']['total_item_price'];

if (freeDeliveryPrefixes.includes(postcode) && orderTotal > 200) {
  rates.add(10001, 0, '', 'Free Local Delivery');
}

Adjust rates based on a custom field

Read a custom checkout field (added with data-fc-shipping-custom-field) and modify rates accordingly. This example adds shipping insurance as a percentage of the cart total when the customer checks a box:

const cartTotal = cart['_embedded']['fx:shipment']['total_item_price'];
let addInsurance = false;

for (const field of (cart['_embedded']['fx:custom_fields'] || [])) {
  if (field['name'] === 'add_insurance') {
    addInsurance = true;
  }
}

if (addInsurance) {
  const insuranceAmount = cartTotal * 0.01;
  rates.each(function() {
    this.price('+' + insuranceAmount)
        .service(this.service() + ' (incl. insurance)');
  });
}

Require a custom quote for heavy orders

const totalWeight = cart['_embedded']['fx:shipment']['total_weight'];

if (totalWeight > 50) {
  rates.error('Orders over 50kg require a custom shipping quote. Please contact us.');
}

Distance based shipping with Google Maps

Use await request() to call the Google Maps Distance Matrix API and set rates based on distance from your store:

const google_maps_api_key = 'YOUR_API_KEY';
const origin_address = '123 Main St, City, STATE, Country, 12345';
const unit_type = 'imperial'; // 'metric' or 'imperial'

const shipment = cart['_embedded']['fx:shipment'];
let address1 = '';
for (const c of (cart['_embedded']['fx:custom_fields'] || [])) {
  if (c['name'] === 'shipping_address1') {
    address1 = c['value'];
    break;
  }
}

const customer_address = [address1, shipment['city'], shipment['region'],
    shipment['country'], shipment['postal_code']].join(', ');

const maps_url = 'https://maps.googleapis.com/maps/api/distancematrix/json'
    + '?origins=' + encodeURIComponent(origin_address)
    + '&destinations=' + encodeURIComponent(customer_address)
    + '&units=' + unit_type
    + '&key=' + google_maps_api_key;

let distance = -1;
await request(maps_url, function(error, response, body) {
  const payload = JSON.parse(body);
  if (response && response.statusCode === 200
      && payload.status === 'OK'
      && payload.rows[0].elements[0].status === 'OK') {
    distance = payload.rows[0].elements[0].distance.value;
    distance = (unit_type === 'metric') ? distance / 1000 : distance / 1609.34;
  }
});

if (distance > 60) {
  rates.error('Sorry, you are too far away for delivery.');
} else if (distance > -1) {
  let shipping = 0;
  if (distance > 25) shipping = 5;
  if (distance > 40) shipping = 10;
  rates.add(10001, shipping, '', 'Local Delivery');

  if (shipment['total_item_price'] >= 150) {
    rates.filter(10001).price(0).service('Free Delivery');
  }
} else {
  rates.error("Sorry, we're unable to calculate delivery to your address.");
}

rates.add(10000, 0, '', 'Pickup From Store');

External carrier API (EasyPost)

Use await request() to get multi carrier rates from EasyPost:

const easypostApiKey = 'YOUR_EASYPOST_KEY';
const shipment = cart['_embedded']['fx:shipment'];

const shipmentData =
  'shipment[to_address][name]=' + shipment['first_name'] + ' ' + shipment['last_name'] +
  '&shipment[to_address][street1]=' + shipment['address1'] +
  '&shipment[to_address][city]=' + shipment['city'] +
  '&shipment[to_address][state]=' + shipment['region'] +
  '&shipment[to_address][zip]=' + shipment['postal_code'] +
  '&shipment[to_address][country]=' + shipment['country'] +
  '&shipment[from_address][state]=' + shipment['origin_region'] +
  '&shipment[from_address][zip]=' + shipment['origin_postal_code'] +
  '&shipment[from_address][country]=' + shipment['origin_country'] +
  '&shipment[parcel][length]=5&shipment[parcel][width]=5&shipment[parcel][height]=5' +
  '&shipment[parcel][weight]=' + (shipment['total_weight'] * 16); // lbs to oz

try {
  await request({
    url: 'https://api.easypost.com/v2/shipments',
    method: 'POST',
    body: shipmentData,
    auth: { 'user': easypostApiKey }
  }, function(error, response, body) {
    const payload = JSON.parse(body);
    for (let i = 0; i < payload.rates.length; i++) {
      rates.add(10000 + i, payload.rates[i]['rate'],
          payload.rates[i]['carrier'], payload.rates[i]['service']);
    }
  });
} catch (e) {
  rates.error("Sorry, we're unable to get shipping rates. Please try again or contact us.");
}

Full combined example

A more complete example that ties multiple patterns together (carrier markup, free shipping by coupon and threshold, non contiguous US restrictions, and fallback rates):

const shipment = cart['_embedded']['fx:shipment'];
const country = shipment['country'];
const region = shipment['region'];
const totalPrice = shipment['total_item_price'];
const discounts = cart['_embedded']['fx:discounts'] || [];

const contiguous = [
  'AL','AZ','AR','CA','CO','CT','DE','FL','GA','ID','IL','IN','IA','KS',
  'KY','LA','ME','MD','MA','MI','MN','MS','MO','MT','NE','NV','NH','NJ',
  'NM','NY','NC','ND','OH','OK','OR','PA','RI','SC','SD','TN','TX','UT',
  'VT','VA','WA','WV','WI','WY','DC'
];

const hasFreeShipCoupon = discounts.some(d =>
  d['code'] === 'freeshipping' || d['code'].endsWith('-fs')
);

// Apply 10% markup to carrier rates and clean up labels
if (rates.exists()) {
  rates.price('*1.10');

  if (country === 'US' && !contiguous.includes(region)) {
    rates.filter('Overnight').hide();
    rates.filter('Express').hide();
  }
}

// Free shipping logic
if (hasFreeShipCoupon && country === 'US') {
  rates.hide();
  rates.add(10001, 0, '', 'Free Shipping (Coupon)');
} else if (country === 'US' && totalPrice >= 75) {
  rates.add(10001, 0, '', 'Free Standard Shipping');
}

// Fallback if no rates at all
if (!rates.exists()) {
  if (country === 'US') {
    rates.add(10090, 7.99, 'Shipping', 'Standard');
    rates.add(10091, 14.99, 'Shipping', 'Express');
  } else if (country === 'CA' || country === 'MX') {
    rates.add(10092, 14.99, 'Shipping', 'North America Standard');
  } else {
    rates.add(10093, 24.99, 'Shipping', 'International Standard');
  }
}

Need Help?

Did this article answer your questions? Need help with anything? Please click below to contact us.