Shipping rates by postcode on Shopify — how it actually works

Why you can’t charge more to the Scottish Highlands using Shopify’s own settings, what you can do for free, and the two routes that genuinely solve it.

Why Shopify can’t do it natively

Shopify’s shipping zones are built from countries and regions. You can give Northern Ireland its own zone and its own rates, because Northern Ireland is a region in Shopify’s geography data. You can’t do the same for the Scottish Highlands and Islands, because it isn’t a region — it’s a collection of postcode districts inside Scotland, and zones don’t go below region level.

That’s the whole reason one works and the other doesn’t. It isn’t a missing setting or a tick box someone forgot about — there’s nothing below region level for a postcode range to attach to.

The usual workaround is to make the whole of Scotland a separate zone and surcharge that. It does work, and it means a customer in Glasgow pays the same as one in Stornoway. For plenty of shops that trade is worse than the original problem.

This has been requested on Shopify’s own forums continuously since January 2023. Staff acknowledged it within 48 hours of that thread opening and it hasn’t moved since. It’s reasonable to plan as though it isn’t coming.

What you can do for free first

Before paying for anything, take the ground that’s already yours. A surprising amount of what people ask for is native:

Work out what’s actually left after that. For a lot of shops it’s only the Highlands and Islands, and knowing that makes the next decision much easier.

Route one: the Carrier Service API

This is the mechanism Shopify provides for rates it can’t work out itself. At checkout, Shopify sends the basket and the destination to an external service, and that service returns the options — name, price, service code. Because that service sees the postcode and every line in the basket, almost anything becomes possible: postcode zones, weight bands, per-product routing, surcharges, different carriers for different goods.

Every app that genuinely solves postcode pricing is using this, ours included.

The catch: it’s plan-gated

Shopify restricts access to third-party calculated rates. You need Advanced or Plus — or Grow on annual billing, which is much the cheapest way in and rarely gets mentioned. On Basic, or on Grow paid monthly, no app using this route can help you.

That gate is Shopify’s decision rather than the app developer’s, and it’s the thing that causes most of the frustration in these discussions. The app isn’t the expensive part; the plan upgrade is.

Route two: pre-created rates and a Function

There’s a second approach, and it isn’t plan-gated at all.

Rather than calculating a rate when the customer reaches checkout, an app creates real Shopify shipping rates in advance — one for every combination you need — then uses a delivery customization Function to hide all of them except the right one, based on the delivery postcode. Nothing is worked out live. The prices already exist and the Function simply picks.

No third-party calculated rate is involved, so this works on every plan, Basic included.

Where it runs out

It’s a lookup rather than a calculation, so every combination has to exist up front. Four zones with three weight bands and two price bands is twenty-four rates sitting in your settings, and adding one more band multiplies the lot again. It suits a few zones and simple banding. It doesn’t suit genuinely calculated pricing, and it becomes unwieldy faster than people expect.

Which one you want

 Carrier Service APIPre-created rates + Function
PlansAdvanced, Plus, or Grow billed annuallyAny, including Basic
How the price is decidedCalculated live from the basket and postcodeChosen from rates built in advance
Weight bandsAny number, calculatedEach band is another pre-built rate
Different carriers per productYesAwkward — multiplies the combinations again
Mixed basketsHandled by whatever rule you chooseHard
Best forAnything involving weight, mixed baskets or several carriersA few zones, simple banding, a tight budget

Short version: if you’re on Basic and your needs are simple, route two is a genuine answer and you shouldn’t let anyone tell you otherwise. If weight matters, or baskets mix light and heavy goods, or different products need different carriers, route one is the only one that holds up.

Things that catch people out

Shopify sends one package size, not one per product

If you’re using a carrier’s own calculated rates — Royal Mail’s, say — Shopify sends your default package’s dimensions with every quote. It doesn’t pick a box per product based on what’s in the order. Your rates are therefore only ever as accurate as that one default box, which is why they feel wrong across a varied range.

Your courier’s surcharge list isn’t “Scotland”

Every carrier publishes its own list of Highlands and Islands postcodes, and they differ. Get your own courier’s list before building zones around someone else’s. It matters more than which tool you choose.

Talk to your courier before you buy software

Some business accounts price on your average weight across the volume you send rather than per parcel, which can make a bulky-but-light problem disappear without any software at all. Worth a phone call before an app.

Charging the customer and buying the label are separate

Whatever sets your checkout price has nothing to do with what you pay the courier. Charge £5.95, buy a £7 label, and nothing anywhere will tell you. Check the two against each other from time to time.

Where we come into this. We make Tidal Shipping Rates, which uses the Carrier Service API — route one, with the plan requirement that comes with it. This is written the way we’d want it explained to us, including the parts where the answer isn’t us.

There are other capable Carrier Service API apps on the Shopify App Store, and for route two there’s Zapiet’s Rates by Zip Code — which is where to look if you’re on Basic. Pick on fit rather than on anyone’s say-so, ours included.

← Tidal Shipping Rates