Type something to search...
How to Configure WooCommerce Shipping Zones and Rates?

How to Configure WooCommerce Shipping Zones and Rates?

Shipping is where small online stores quietly lose money. Charge too little, and every heavy order eats your margin. Charge too much, and customers abandon the cart at the last step. Show the wrong options, such as a paid rate next to free shipping, or no options at all for an address you do ship to, and you lose the sale or spend your morning answering emails.

WooCommerce's built-in shipping system handles most stores' needs without any extension, once you understand its three building blocks: zones decide where a customer is, methods decide which options they get, and shipping classes decide how different products affect the price.

This article covers configuring WooCommerce shipping from scratch: how zone matching works, creating zones with regions and postcodes, setting up Flat rate with cost formulas, using shipping classes for heavy or bulky items, offering free shipping with minimum order amounts and coupons, configuring local pickup for the Checkout block, the store-wide shipping options, and code snippets to control which rates customers see.

How WooCommerce Shipping Works

When a customer enters an address at the cart or checkout, WooCommerce:

  1. Compares the address against your shipping zones, from the top of the list to the bottom, and picks the first zone that matches.
  2. Shows the enabled shipping methods in that zone, each with a calculated cost.
  3. Preselects the first enabled method in that zone.
Building blockAnswers the questionExample
Shipping zoneWhere is the customer?Domestic, Europe, Rest of the world
Shipping methodWhat options do they get?Flat rate, Free shipping, Local pickup
Shipping classHow do products affect cost?Heavy, Fragile, Oversized

A customer only ever matches one zone. That single rule explains most shipping setups that behave unexpectedly, so it is worth remembering before you build anything.

If you are still setting up the store itself, how to use WordPress for e-commerce covers the bigger picture.

Opening the Shipping Settings

Go to WooCommerce → Settings → Shipping. You will see tabs across the top:

  • Shipping zones: your zones and the methods inside them.
  • A store-wide settings tab with calculation and destination options.
  • Classes: your shipping classes.
  • Local pickup: pickup locations for the block-based Checkout.

Before configuring zones, make sure shipping is enabled at all. Under WooCommerce → Settings → General, the Shipping location(s) option must not be set to disable shipping, and Selling location(s) should include the countries you ship to.

Creating Shipping Zones

Plan Zones from Most Specific to Least Specific

Because the first matching zone wins, order matters. Put narrow zones above broad ones:

  1. Local delivery (a few postcodes near your shop)
  2. Domestic (your whole country)
  3. Europe (a continent or a list of countries)
  4. Rest of the world (everything else)

If "Domestic" sat above "Local delivery," every local customer would match Domestic first, and the local zone would never be used.

Adding a Zone

  1. On the Shipping zones tab, click Add zone.
  2. Enter a Zone name, such as Domestic. Customers do not see this name; it is for you.
  3. In Zone regions, type and select countries, states, or continents. For a US store, choose United States (US). For regional rates, choose individual states instead.
  4. Click Add shipping method to add the first method (covered below).
  5. Save the zone.

Limiting a Zone to Postcodes

To create a local delivery zone, select your country in Zone regions, then click Limit to specific zip/postcodes and enter one pattern per line:

# Zip/postcode patterns, one per line
10001
10002
100*
90210...99000
CB23*
  • A plain value matches exactly: 10001.
  • A trailing asterisk is a wildcard: CB23* matches CB23 1EX, and 902* matches 90210 and 90288-1234.
  • Three dots define a numeric range: 90210...99000.
  • Wildcards inside ranges, such as 902*...990*, are not supported.

Reordering Zones

Drag zones by their handles to reorder them. Narrow zones should be at the top.

The "Rest of the World" Zone

At the bottom of the list is a built-in zone for locations not covered by your other zones. You cannot rename or delete it. If you add no methods to it, customers outside your zones see a message that no shipping options are available, which is exactly what you want if you do not ship internationally.

Adding Shipping Methods

Each zone can hold any number of methods. WooCommerce includes three:

MethodUse it for
Flat rateA fixed or formula-based cost, optionally varying by shipping class
Free shippingNo charge, optionally requiring a minimum order or a coupon
Local pickupCustomers collect the order themselves (legacy zone-based version)

Inside a zone, click Add shipping method, choose a method, and configure it. Each method has an Enabled toggle so you can turn it off without deleting its settings.

Live carrier rates from UPS, FedEx, USPS, DHL, and others require an extension. The built-in methods cover fixed and formula pricing.

Configuring Flat Rate

Flat rate has three main fields:

  • Name: what customers see at checkout, such as Standard Shipping or Express (2–3 days).
  • Tax status: Taxable or None. Many jurisdictions tax shipping; check yours.
  • Cost: the amount charged for the entire cart.

The Cost field accepts a plain number or a formula.

Cost Formulas

FormulaMeaningCart with 3 items, 60.00 subtotal
55.00 per order5.00
5 + ( 2 * [qty] )5.00 base plus 2.00 per item11.00
[fee percent="10"]10 percent of the cart cost6.00
10 + [fee percent="10" min_fee="4"]10.00 plus 10 percent, at least 4.0016.00
[fee percent="10" max_fee="8"]10 percent, capped at 8.006.00

The placeholders:

  • [qty] is the number of items in the cart.
  • [cost] is the cost of the items in the cart.
  • [fee percent="" min_fee="" max_fee=""] is a percentage of the cart cost, with optional minimum and maximum amounts.

Formulas let one Flat rate method scale with the order. For example, 4.99 + ( 1.50 * [qty] ) is a common setup for small-item stores where packaging grows with every item.

A Typical Domestic Setup

In a Domestic zone, add two Flat rate methods:

  1. Standard Shipping, cost 4.99
  2. Express Shipping, cost 14.99

Then add Free shipping (configured below). Customers see all three, with the first enabled one preselected. Order the methods by dragging so the one you want preselected is first.

Using Shipping Classes

Shipping classes let some products cost more to ship than others under the same Flat rate method.

Create the Classes

  1. Go to WooCommerce → Settings → Shipping → Classes.
  2. Click Add shipping class.
  3. Enter the Shipping Class name (such as Heavy), a Slug, and a Description explaining what belongs in it.
  4. Click Create.

Assign Products to Classes

Edit a product, open Product data → Shipping, and choose the class from the Shipping class dropdown. For variable products, each variation has its own Shipping class dropdown, so a large size can ship as Heavy while small sizes do not. Variations are covered in detail in how to set up product variations in WooCommerce.

Set Class Costs in Flat Rate

Once at least one class exists, each Flat rate method shows extra fields:

  • A cost field for each shipping class, such as Heavy shipping class cost.
  • No shipping class cost for products without a class.
  • Calculation type:
    • Per class: charge shipping for each shipping class individually.
    • Per order: charge shipping for the most expensive shipping class.

Class costs are added to the base Cost. Class cost fields also accept formulas, where [qty] and [cost] refer to items of that class only.

Worked Example

Base cost 5, Heavy class cost 10, No shipping class cost 0, and a cart with one regular item and one heavy item:

  • Per class: 5 + 0 (regular items) + 10 (heavy items) = 15.00
  • Per order: 5 + 10 (the most expensive class) = 15.00

Now add a Fragile class costing 6 and a fragile item to the same cart:

  • Per class: 5 + 0 + 10 + 6 = 21.00
  • Per order: 5 + 10 = 15.00

Per class reflects real packing costs when classes ship in separate boxes. Per order is simpler and keeps costs predictable.

Configuring Free Shipping

Add Free shipping to a zone, then choose what Free shipping requires:

  • No requirement: always free in this zone.
  • A valid free shipping coupon
  • A minimum order amount
  • A minimum order amount OR a coupon
  • A minimum order amount AND a coupon

With a minimum order amount, enter the threshold, for example 50. The option Apply minimum order rule before coupon discount decides which total is checked: when unchecked, the discounted total must meet the minimum; when checked, the total before coupons counts.

To create a free shipping coupon:

  1. Go to Marketing → Coupons and click Add coupon.
  2. Enter the coupon code.
  3. Tick Allow free shipping.
  4. Publish the coupon.

The coupon only works if a Free shipping method in the customer's zone accepts coupons.

Configuring Local Pickup

WooCommerce has two local pickup systems, and you should use only one:

Block-based Local pickupLegacy zone-based Local pickup
Where configuredShipping → Local pickup tabInside each shipping zone
Works withThe Checkout blockThe classic shortcode checkout
Shipping addressNot required to choose pickupCustomer enters an address
Multiple locationsYes, with addresses and detailsNo
TaxesBased on the pickup locationBased on the store address

For stores using the block-based Checkout, which is the default on new installs:

  1. Go to WooCommerce → Settings → Shipping → Local pickup.
  2. Tick Enable local pickup.
  3. Set a Title, such as Pick up in store.
  4. Optionally add a price for customers who choose local pickup, with its tax status.
  5. Under Pickup locations, click Add pickup location and enter a name, address, and pickup details such as opening hours.
  6. Save changes.

The Checkout block then shows a choice between shipping and pickup, and customers who choose pickup do not need to enter a shipping address. WooCommerce warns you if both the block-based and the legacy pickup methods are enabled, because customers would see duplicate options.

Store-Wide Shipping Options

The settings tab under WooCommerce → Settings → Shipping holds options that apply to every zone:

  • Enable the shipping calculator on the cart page lets customers estimate shipping before checkout.
  • Hide shipping costs until an address is entered prevents showing a cost based on the store's default location.
  • Shipping destination chooses whether orders default to the customer's shipping address or billing address, or force shipping to the billing address.
  • Enable debug mode shows which zone matched and bypasses shipping rate caching. Turn it on while testing and off before going live.

Controlling Rates with Code

The built-in options cover most stores, but two adjustments come up constantly. Add these to a site-specific plugin or a snippets plugin, as explained in how to add custom code snippets to WordPress safely.

Hide Paid Rates When Free Shipping Is Available

Showing "Standard Shipping 4.99" next to "Free shipping" confuses customers. This filter removes paid options once a free shipping rate qualifies, while keeping pickup available:

// wp-content/plugins/store-tweaks/shipping.php
add_filter( 'woocommerce_package_rates', 'wsm_hide_paid_rates_when_free', 100 );

function wsm_hide_paid_rates_when_free( $rates ) {
$keep = array();

foreach ( $rates as $rate_id => $rate ) {
if ( 'free_shipping' === $rate->get_method_id() ) {
$keep[ $rate_id ] = $rate;
}
}

if ( empty( $keep ) ) {
return $rates; // No free shipping available; show everything.
}

// Keep pickup options alongside free shipping.
foreach ( $rates as $rate_id => $rate ) {
if ( in_array( $rate->get_method_id(), array( 'local_pickup', 'pickup_location' ), true ) ) {
$keep[ $rate_id ] = $rate;
}
}

return $keep;
}

local_pickup is the legacy zone-based method and pickup_location is the block-based Local pickup. WooCommerce caches calculated rates, so after adding this code, enable debug mode or update the cart contents to see the change.

Show How Much More Qualifies for Free Shipping

A "Spend 12.00 more for free shipping" message is one of the most effective ways to raise average order value:

// wp-content/plugins/store-tweaks/shipping.php
add_action( 'woocommerce_before_cart', 'wsm_free_shipping_progress_notice' );

function wsm_free_shipping_progress_notice() {
$threshold = 50; // Match the minimum in your Free shipping method.
$subtotal  = (float) WC()->cart->get_displayed_subtotal();

if ( $subtotal <= 0 || $subtotal >= $threshold ) {
return;
}

wc_print_notice(
sprintf(
/* translators: %s: amount remaining for free shipping */
esc_html__( 'Spend %s more to get free shipping.', 'store-tweaks' ),
wp_strip_all_tags( wc_price( $threshold - $subtotal ) )
),
'notice'
);
}

This hook targets the classic cart page. The block-based Cart does not run woocommerce_before_cart, so on block carts, show the same message with a notice block or an extension that supports the Cart block.

Creating Zones with the REST API

If you set up many stores with identical shipping rules, the WooCommerce REST API can create zones, locations, and methods automatically. With API keys generated under WooCommerce → Settings → Advanced → REST API:

# Terminal
SITE="https://example.com"
AUTH="ck_xxxxxxxx:cs_xxxxxxxx"

# 1. Create the zone and note the returned "id"
curl -u "$AUTH" -X POST "$SITE/wp-json/wc/v3/shipping/zones" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Domestic" }'

# 2. Set its locations (replace 1 with the zone id)
curl -u "$AUTH" -X PUT "$SITE/wp-json/wc/v3/shipping/zones/1/locations" \
  -H "Content-Type: application/json" \
  -d '[ { "code": "US", "type": "country" } ]'

# 3. Add a Flat rate method with a cost
curl -u "$AUTH" -X POST "$SITE/wp-json/wc/v3/shipping/zones/1/methods" \
  -H "Content-Type: application/json" \
  -d '{ "method_id": "flat_rate", "settings": { "title": "Standard Shipping", "cost": "4.99" } }'

Keep API keys out of version control and give them the minimum permissions needed.

Testing Your Shipping Setup

Before launch, test every zone with real addresses:

  1. Enable debug mode in the shipping settings.
  2. Add products to the cart, including one from each shipping class.
  3. Enter an address from each zone at checkout, including a local postcode, a domestic address outside it, and an international one.
  4. Confirm the matched zone, the methods shown, and each cost.
  5. Test free shipping just below and just above the threshold, and with a coupon.
  6. Disable debug mode.

Common Problems and Fixes

  • "No shipping options were found." The customer's address matched a zone with no enabled methods, often Rest of the world. Add methods to that zone, or confirm the address belongs in another zone.
  • The wrong zone's rates appear. A broader zone sits above a narrower one. Drag the narrow zone higher.
  • Postcode zone never matches. The country is not selected in Zone regions, or the pattern format is wrong. Select the country and recheck wildcard and range syntax.
  • Shipping class costs are ignored. Products are not assigned to the class, or the variation is set to a different class. Check Product data → Shipping and each variation.
  • Free shipping does not appear at the threshold. Coupons reduced the total below the minimum. Tick Apply minimum order rule before coupon discount if the pre-discount total should count.
  • Changes do not show at checkout. Rates are cached in the customer session. Enable debug mode while testing, or change the cart contents.
  • Customers see two pickup options. Both the block-based and legacy local pickup are enabled. Disable the legacy method in your zones.

WooCommerce Shipping FAQ

No. WooCommerce checks zones from top to bottom and uses the first one that matches the address. Put specific zones, such as postcode-based local delivery, above broader country or continent zones.

Create a shipping class such as Heavy, assign it to the heavy products or variations, and enter a cost for that class in your Flat rate method. The class cost is added to the base cost.

Per class adds the cost of every shipping class in the cart, which suits items packed separately. Per order charges only the most expensive class in the cart, which keeps costs simpler and lower for mixed carts.

Not with the built-in methods, which use fixed costs and formulas. Live rates from carriers such as UPS, FedEx, USPS, or DHL require a shipping extension that connects to the carrier.

Use the block-based Local pickup from the Local pickup tab if your store uses the Checkout block. It supports multiple locations and does not require a shipping address. The legacy zone-based method is for the classic checkout. Do not enable both.

Limit Selling locations and Shipping locations under WooCommerce general settings, and leave the Rest of the world zone without shipping methods so unsupported addresses get no options.

Conclusion

WooCommerce shipping becomes predictable once you design around its core rule: every address matches exactly one zone, from top to bottom. Build zones from the most specific to the least specific, give each zone the methods its customers need, and use Flat rate formulas and shipping classes to make costs reflect what you actually pay to ship.

Add free shipping with a minimum order amount to lift order values, use the block-based Local pickup for in-store collection, and use small, well-scoped filters such as hiding paid rates when shipping is free. Test every zone with real addresses and debug mode before launch, and your checkout will show the right options at the right price for every customer.

Here are some useful references for going deeper on WooCommerce shipping:

  1. WooCommerce Docs: Setting up Shipping Zones — zone matching, regions, and postcode patterns.
  2. WooCommerce Docs: Flat Rate Shipping — cost formulas and shipping class costs.
  3. WooCommerce Docs: Free Shipping — minimum order amounts and coupon requirements.
  4. WooCommerce Docs: Local Pickup — pickup locations for the Checkout block.
  5. WooCommerce REST API Docs: Shipping zones — creating zones, locations, and methods programmatically.
Tags :
Share :

Related Posts

WordPress optimization with specific recommended approach

WordPress optimization with specific recommended approach

Whether you run a high traffic WordPress installation or a small blog on a low cost shared host, you should optimize WordPress and your server to run

Continue Reading
Creating and Customizing WordPress Child Themes

Creating and Customizing WordPress Child Themes

Creating a child theme in WordPress is a best practice for making modifications to a theme. By using a child theme, you can update the parent theme w

Continue Reading
Understanding the Distinction Categories vs. Tags in WordPress

Understanding the Distinction Categories vs. Tags in WordPress

WordPress, a powerful content management system, offers a plethora of features to organize content effectively. Among these features, categories and

Continue Reading