Shipping scripts

Updated · SMART Shipping Rates & Rules (E-TRADE PARTNER)

A shipping script is your own JavaScript that runs at checkout after your zones and combined rates. It reads the cart, addresses, customer, totals, and the rates your zones made, and returns the final list of up to 20 rates. Scripts live in Shipping rates > Scripts on the Pro plan. They run in a sealed sandbox with no internet access and a 5 ms CPU limit. If a script fails, that one checkout gets your zone rates or a backup rate instead.

SMART Shipping Rates does this with zones, calculated rates, and delivery customizations.

Try it free
On this page
  1. Where a script runs
  2. Write a script
  3. What input contains
  4. What to return
  5. Data to load
  6. Templates
  7. Test, save, and versions
  8. If the script fails
  9. Limits
  10. Plan and requirements
  11. Frequently asked questions

Use a script when the zone editor can't express your rule: a fuel surcharge on every rate, freight priced by a metafield, a fee per extra vendor, a price table by postcode, or delivery dates that skip holidays. For the usual weight, cart total, quantity, and postcode rates, zones are simpler. Moving from Shopify's retired Ruby scripts? Read what replaces Shopify shipping scripts.

Where a script runs

Shopify asks the app for rates
  -> zones and their rate conditions
  -> Settings: multiple rates, rounding
  -> combined rates
  -> your active script
  -> Settings again on the script's answer
  -> rates at checkout
  • A script sees and returns the rates this app sends to checkout. It does not see Shopify's own rates or other apps' rates. To hide or rename those, use Delivery customizations.
  • With no active script, checkout gets exactly what the zones and combined rates made.
  • The script still runs when no zone matched, with an empty input.rates, so it can supply rates on its own.
  • One script can be active per store. Activating one turns the others off. A store can keep up to 10 scripts.
  • It runs on the app's servers as part of the carrier-service answer, not as a Shopify Function, so it can set prices and add rates. That also means it needs Carrier Calculated Shipping, like any calculated rate.

Write a script

The code is the body of a function. input is already defined, and the code ends with return. Return a list of rates, or input.rates to keep your zone rates. Returning nothing (undefined or null) also keeps input.rates.

// Freight above 30 kg, otherwise keep the zone rates.
const kg = input.items.reduce((s, i) => s + i.grams * i.quantity, 0) / 1000;
if (kg > 30) return [{ name: "Freight", price: 49 }];
return input.rates;
// Add a 9% fuel surcharge to every rate.
return input.rates.map((rate) => ({
  ...rate,
  price: rate.price * 1.09,
}));

The code must stay one function body. The editor checks this on save and on every Test, without running your code, and rejects code that closes the function early.

What input contains

All money is in the store currency as a decimal (25.5 means 25.50). Input reference in the editor shows the same list.

FieldWhat it holds
input.itemsOne entry per cart line: name, sku, quantity, grams, vendor, price (unit price), requires_shipping, properties (line item properties as name: value), product_id, variant_id
item.productOnly what you tick in Data to load: tags, collections (ids as strings), type, metafields such as "custom.floor_metres"
item.variantmetafields you ticked, and dimensions (length, width, height, unit; longest side first) or null
input.destinationcountry, province, city, postal_code, address1, address2, address3, company_name, phone, latitude, longitude (latitude and longitude are often empty)
input.originThe ship-from location: country, province, city, postal_code, address1, address2, name
input.customerid (null for guests) and tags
input.totalssubtotal, total, discount
input.currency, input.localeCheckout currency and language
input.shopcurrency, weight_unit, dimension_unit, timezone
input.nowdate, time, weekday (Monday is 1) in the store timezone, plus utc_time
input.ratesThe rates your zones and combined rates made: name, price, code, description, min_days, max_days, phone_required, tags

What to return

FieldRule
nameRequired. 1 to 255 characters. Shown at checkout.
priceRequired. A number from 0 to 1,000,000 in the store currency.
codeOptional. Defaults to the name. Codes may repeat.
descriptionOptional. Up to 255 characters, shown under the name.
min_days, max_daysOptional. Whole business days, 0 to 365.
phone_requiredOptional. Asks the customer for a phone number.

Return at most 20 rates. A rate you pass back unchanged from input.rates reaches checkout exactly as the zones made it, so return input.rates gives the same checkout as no script. Rounding from Settings > Rate behavior applies only to rates the script added or changed. The Multiple rates setting (all, highest, lowest, or cheapest and most expensive) applies to the whole list the script returns.

Data to load

Tick only what your code reads, because each ticked item is looked up in Shopify and cached: Product tags, Collections, Product type, Product dimensions, Product metafields, and Variant metafields (up to 10 of each, written as namespace.key). Tags, collections, and dimensions share the app's product data cache with zones (Settings > Product data cache has a Clear cache button). Product type and metafields are cached for up to an hour, so a change can take that long to reach checkout.

Templates

A new script starts with Start from my current rates (returns input.rates, so checkout doesn't change until you edit) or Pick a template. Templates in the page header opens the same list. Picking a template ticks the data it needs.

  • Keep my current rates
  • Fuel surcharge on every rate
  • Free shipping above an amount, except tagged products
  • Freight by floor metres (a variant metafield, or weight when higher)
  • Most expensive item plus a percentage per extra item
  • Fee per extra vendor
  • Price every item by its own weight band
  • Free shipping per product group
  • Stackable items
  • Fallback weight for weightless items
  • Delivery dates with a cutoff and holidays
  • Price table by postcode
  • Same product has a tag and is in a collection

Test, save, and versions

  1. Open Shipping rates > Scripts and click Add script.
  2. Enter a Script name (only you see it; rate names come from your code).
  3. Write or pick the code in the Code card.
  4. Click Test, add products and quantities, set the destination and Ship from location, and click Run test. The result shows the input, the zone rates, your output, and the rates checkout would get.
  5. Set Status to Active and save. Every save is a version.
  6. Check real requests later in Shipping rates > Activity: each request shows a Script card with the result, and rates the script dropped are marked "Removed by your script".

Test runs and save checks are limited to 10 a minute per store. Checkout runs are not limited. The Versions card keeps the last 50 saves; open one to compare it with the editor and click Restore this version. The Checkout simulator also runs the active script, with a checkbox under Rules to run to compare results with and without it.

If the script fails

An error, going over 5 ms of CPU, or returning something that isn't a valid list of rates counts as a failure. Pick what that checkout gets in If the script fails: Use zone rates (the default: the rates your zones and combined rates made) or Show a backup rate with a name and price you set. Only the failing checkout uses the fallback. The script is never switched off automatically, so a shopper's unusual cart can't turn it off for everyone.

Limits

LimitValue
Scripts per store10, one active
Code size100 KB
CPU time per run5 ms (2 seconds of wall time at most)
Network accessNone: no fetch, no external APIs
Rates returned20
Script answer128 KB
console.log output kept20 lines of 200 characters
Versions keptLast 50 per script
Metafields10 product and 10 variant
Test runs and save checks10 a minute per store

Plan and requirements

  • Scripts are part of the Pro plan ($19.99/month or $191.88/year, 7-day free trial). Lite stores see the editor with a Pro banner and can't save.
  • Switching from Pro to Lite is blocked while a script is active. Deactivate it first, along with deleting zones and combined rates.
  • Saving a store's first script connects the app's rates to checkout, the same as saving a first zone. Carrier Calculated Shipping must be available on the store; see Carrier Calculated Shipping.
  • Uninstalling the app deletes your scripts and their versions. Copy the code somewhere first if you may reinstall.

Write your own shipping rate logic

Shipping scripts are on the Pro plan. 7-day free trial. Free on development stores.

Try the app free

Frequently asked questions

›Is this the same as Shopify Scripts?

No. Shopify Scripts were Ruby, Plus-only, and stopped running on June 30, 2026. SMART shipping scripts are JavaScript that runs on the app's own rates, and they can raise or lower prices and add rates. Shopify's shipping scripts could only hide, rename, reorder, and discount existing rates.

›Can a script change Shopify's own rates or another app's rates?

No. A script works on the rates this app sends to checkout. Use Delivery customizations to hide, rename, or reorder rates from Shopify or other apps.

›Can a script call an API or read my inventory?

No. Scripts have no internet access. They can read the cart, addresses, customer, totals, the zone rates, and the product data you tick in Data to load, including up to 10 product and 10 variant metafields.

›What happens if my script throws an error at checkout?

That checkout gets the fallback you picked in If the script fails: your zone rates or one backup rate. The next checkout runs the script again.

›Which plan do I need?

Pro, with Carrier Calculated Shipping available on the store. Delivery customizations alone work on Lite.

Related articles