Skip to content

Delivery Region (Delivery Areas) ​

Overview ​

The Delivery Region section of the Delivery settings form holds an ordered list of delivery areas. Each area names a piece of geography — a radius, a driving distance, a set of postcodes, or a list of streets — and optionally prices it. An area can also be a refusal: somewhere you explicitly do not deliver.

Key Purpose: Describe where you deliver, and what delivery costs there, by building a list of named areas and putting them in the order you want them checked.

The order of the list is the rule. Areas are checked from top to bottom and the first one that matches an address decides — both whether you deliver there and what the fee is. If the first match is an area marked "Do not deliver here", the address is refused outright. Drag an area to move it.

For the delivery fee model itself (free / flat charge / free over a threshold, and distance-based pricing), see Delivery Settings.

Purpose ​

This section lets you define your delivery coverage as a list rather than as a single mode. Because you own the order, you can express things a single mode could not: serve a handful of streets that fall outside your radius, refuse one street inside a postcode you otherwise cover, or charge more for an outer band than an inner one.

Key Concepts ​

  • Delivery area (a "zone"): One row in the list. It has a Name, a shape, an optional Delivery fee, and a "Do not deliver here" switch.
  • First match wins: Coverage and price are decided by the first area in the list that matches the address. Nothing below it is consulted.
  • Refusal area (Do not deliver here): An area that, when matched, refuses the address immediately. Put refusals above the broader areas they carve out of — an exclusion placed below the area that already covers the address never gets a say.
  • Area shape: One of four — Radius, Driving distance, Postcodes, Streets. An area carries exactly one shape; switching shape clears the previous shape's values.
  • Per-area fee: The delivery fee charged when this area is the one that matched. Leave it blank to use the default fee instead. 0 means genuinely free for that area — blank and zero are not the same thing.
  • The list is capped at 10 areas, and at least one of them must be an area you do deliver to.

Actions ​

Add a delivery area ​

Under Delivery Region, next to "Add area", choose the shape you want: Radius, Driving distance, Postcodes or Streets. The new area is added at the bottom of the list and opens for editing. The buttons stop working once the list holds 10 areas.

Name an area ​

Every area needs a Name (up to 80 characters). It is added pre-filled with its shape's name; rename it to something you will recognise in the list ("Town centre", "Outer ring", "Not the industrial estate").

Set what an area covers ​

Expand the area and fill in the field for its shape:

  • Radius — "I deliver within an area of … km". A straight-line distance from the location.
  • Driving distance — "I deliver within a driving route distance of … km". Uses real driving route distance, not a straight line.
  • Postcodes — add the postcodes this area covers, one at a time. At least one is required.
  • Streets — start typing a street name and pick it from the list. At least one is required.

Radius and driving distance must be at least 0.1 km.

Price an area ​

With the expanded area open, enter a Delivery fee in euros. Leaving it empty shows "Use the default fee" and falls back to the delivery fee configured below the area list. The fee field is hidden when your delivery fee type is Free delivery, and on refusal areas (which cannot carry a fee).

Refuse an area ​

Turn on "Do not deliver here". The row is outlined in red and its fee is removed. Order still matters: a refusal only takes effect if it sits above whatever else would have covered that address.

Reorder the list ​

Drag an area by its handle, or focus the handle and use the up/down arrow keys. The number to the left of each area shows its position.

Remove an area ​

Expand it and choose Delete.

Business Rules ​

  • Coverage and fee are decided by the first matching area, reading top to bottom. A matching refusal area denies the address; a matching ordinary area delivers to it.
  • An address that matches nothing in the list is refused.
  • The list holds at most 10 areas, and at least one must be an area you deliver to — a list of nothing but refusals is rejected on save. (Close delivery entirely with the delivery toggle instead.)
  • Every area needs a name and a filled-in area value. An area marked "Do not deliver here" cannot also carry a fee.
  • Changing an area's shape discards the values you entered for the old shape.
  • A blank per-area fee means "use the default fee". A fee of 0 means free delivery for that area. Fees cannot be negative.
  • Coverage is enforced when the order is placed, not only in the browser, and it applies to all four shapes. While the customer is typing, an uncovered address is refused with "We do not deliver to this address."; if one reaches checkout anyway, the order is refused with "This address is outside the delivery area."
  • An address that could not be placed on the map — or a location with no map pin — never matches a Radius area.
  • If the driving distance cannot be worked out (no map pin, an unroutable address, a lookup that fails), a Driving distance area simply does not match and the rest of the list is still checked. A failed lookup never widens your delivery area, and never refuses an address one of your other areas covers.
  • Street matching compares the street name ignoring case and extra spaces. Where your stored street carries a postcode, that must match too — this is what keeps the same street name in two towns apart; failing that the city is used, and failing both the name alone decides.
  • Per-postcode custom delivery fees no longer exist as a separate list. A price now lives on the area it applies to.
  • A location whose area list is still empty keeps the delivery area it already had. Its previous single-mode setup is read as an equivalent list, so the same addresses are covered and nothing needs re-entering. The one thing that does change is where the rule is applied: coverage is now checked when the order is placed as well as in the browser, for every shape.

Ordering, worked through ​

A merchant who delivers across three postcodes, refuses one street inside them, and also serves two streets just outside would build:

1. "Not Kerkstraat"     Streets       Do not deliver here
2. "Nearby streets"     Streets       €4.50
3. "Town"               Postcodes     €2.50

Read top to bottom: Kerkstraat is refused before anything can cover it; the two outside streets are served at €4.50 even though no postcode covers them; everything else in the three postcodes pays €2.50. Moving row 1 to the bottom would break the carve-out — row 3 would already have covered the address.

How the delivery fee is decided ​

Once an area has matched, the fee is resolved in this order:

  1. The matched area's own fee, if it has one (including 0).
  2. Otherwise distance-based pricing, if you have it switched on. Beyond your widest distance tier there is no configured rate, so the default fee applies rather than nothing.
  3. Otherwise the default delivery fee.

Free delivery and free over a certain amount are settled against the order total before any of this, so they still win where they apply. See Delivery Settings.

Streets: how the address is built ​

When a customer picks one of your streets, they type only a house number and the rest of the address is rebuilt from your stored entry — so neither the area nor its fee can be worked around by a crafted request.

  • A street that is not one of yours → "We do not deliver to this address.", and "This address is outside the delivery area." if the order is submitted anyway.
  • A missing or blank house number → "Please enter your house number.", and "A house number is required." on submit. House numbers are cut off at 20 characters.

Fields ​

Delivery areas ​

PropertyValue
Field IDdelivery_region.zones
LabelDelivery Region (the list itself has no visible heading)
TypeOrdered array of area objects
Default[] (empty)
RequiredNo — an empty list falls back to the location's previous single-mode setup
Validationnullable, array, maximum 10 entries; at least one entry must not be a refusal

Per-area fields ​

Field IDLabelTypeRequiredValidation
zones[].nameNameStringYesMax 80 characters
zones[].shape(the four shape buttons)EnumYesOne of radius, distance, postcode, street
zones[].excludeDo not deliver hereBooleanNo—
zones[].feeDelivery feeNumber (euros) or blankNo≥ 0; rejected outright on a refusal area
zones[].radiusI deliver within an area of …Number (km)When shape is radius≥ 0.1; rejected on any other shape
zones[].max_distanceI deliver within a driving route distance of …Number (km)When shape is distance≥ 0.1; rejected on any other shape
zones[].postal_codesPostcodesArray of stringsWhen shape is postcodeAt least one; rejected on any other shape
zones[].streetsStreetsArray of street entriesWhen shape is streetAt least one; rejected on any other shape

Each street entry stores its own street name, city, postcode, country and coordinates, picked from autocomplete in the back office.

A blank fee is not zero. Blank means "inherit the default fee"; 0 means free.


Legacy single-mode fields ​

These remain on locations whose area list is still empty, and are read as the fallback. New configuration is done through the area list.

Field IDMeaning
delivery_region.typeThe old single mode: Postal Code, Radius, Distance or Street
delivery_region.postal_codesPostcodes delivered to (old Postal Code mode)
delivery_region.streets / excluded_streetsStreet include / exclude lists
delivery_region.excluded_postal_codesPostcodes refused
delivery_region.radiusStraight-line km (old Radius mode)
delivery_region.max_distanceDriving-route km (old Distance mode)

The old setup is read as an equivalent ordered list — street rules first (refusals, then inclusions), then postcode rules, then the mode itself as the widest area last — so a location that has not been set up as areas yet behaves exactly as it always did.


Location ​

  • Backoffice Page: Online → Online Ordering → Delivery settings → Delivery Region (route /online/online-ordering)
  • Backend Request: app/Http/Requests/BackOffice/OnlineOrdering/StoreOnlineOrderingRequest.php (validates the delivery_region.zones block)
  • Backend Support: app/Support/DeliveryCoverage.php (resolve()), app/Support/DeliveryFeeResolver.php, app/Support/LegacyRegionZones.php
  • Backend Defaults: app/Constants.php ($DEFAULT_ONLINE_ORDERING_SETTING['delivery_region'])
  • Vue Components: src/views/online/online-ordering/forms/DeliveryZoneList.vue, DeliveryZoneEditor.vue, utils/deliveryZones.ts

There is no separate "Delivery Zones" back-office page. The area list is a section inside the Online Ordering settings form, saved through the online ordering settings endpoint.

FAQs ​

  • Can I charge different fees in different areas? Yes — that is what the list is for. Give each area its own delivery fee, and leave the fee blank on any area that should just use your default.
  • How do I stop delivering to one street inside a postcode I cover? Add a Streets area holding that street, switch on "Do not deliver here", and drag it above the postcode area. Order is what makes the carve-out work.
  • How do I serve a street that falls outside my radius? Add a Streets area for it and put it above the radius area. Give it its own fee if it should cost more.
  • What's the difference between Radius and Driving distance? Radius is straight-line distance from your location. Driving distance follows real driving routes. Use driving distance where roads, rivers or one-way systems make the crow's-flight distance misleading.
  • Why is my exclusion being ignored? Almost always because it sits below the area that covers the address. Only the first matching area has a say — drag the exclusion higher.
  • I left an area's fee empty. Is delivery free there? No. Empty means "Use the default fee". Enter 0 if you really want free delivery in that area.
  • How many areas can I have? Ten.
  • What format should postcodes be in? The postcode field accepts digits only and needs at least 4 of them. Duplicates are rejected.
  • My area list is empty — have I lost my delivery settings? No. Until areas are set up, the location keeps delivering on the setup it had before, unchanged.

Troubleshooting ​

Problem: "We do not deliver to this address." / "This address is outside the delivery area." ​

Causes:

  1. No area in the list matches the address.
  2. The first area that matches is one marked "Do not deliver here".
  3. In a Streets area, the customer's street is not one of the streets you listed.
  4. The address could not be placed on the map, or the location has no map pin — a Radius area cannot match either way.

Solutions:

  1. Add or widen an area that covers the address.
  2. Check whether a refusal area sits above the area that should have covered it, and whether that refusal is really meant to include this address.
  3. Add the street to the relevant Streets area.
  4. Set the location's map pin under Settings → Locations.

Problem: A customer was charged the wrong delivery fee ​

Causes:

  1. A different area matched first than you expected — the fee always comes from the same area that decided coverage.
  2. The area that matched has a blank fee, so the default fee (or distance-based pricing) applied.
  3. Free delivery, or free over a certain amount, applied to the order total first.

Solutions:

  1. Read the list top to bottom and find the first area that covers that address; reorder if it is not the one you wanted.
  2. Put an explicit fee on that area.
  3. Check the delivery fee type and threshold under Delivery Settings.

Problem: Save is refused with "Add at least one area you do deliver to" ​

Cause: Every area in the list is marked "Do not deliver here", so no address could ever be served.

Solution: Add at least one ordinary area, or turn off delivery entirely with the delivery toggle if that is what you meant.


Problem: Cannot add a postcode ​

Causes:

  1. The value contains non-digit characters.
  2. The value is shorter than 4 characters.
  3. The postcode is already in the list.

Solutions: Enter at least 4 digits, digits only, not already listed.


Relations ​

Depends On ​

  • Locations: Areas are stored per-location, inside the location's online ordering setting. A Radius or Driving distance area also needs the location's map pin.
  • Online Ordering: Delivery must be enabled for the area list to matter.

Affects ​

  • Delivery eligibility at checkout: Whether an address can be delivered to at all.
  • Delivery fee: The matched area is what prices the order.

Examples ​

A single radius area (the simplest setup) ​

json
{
  "delivery_region": {
    "zones": [
      { "id": "a1", "name": "Delivery area", "shape": "radius", "radius": 5, "exclude": false, "fee": null }
    ]
  }
}

Two priced bands ​

json
{
  "delivery_region": {
    "zones": [
      { "id": "a1", "name": "Town centre", "shape": "postcode", "postal_codes": ["1012", "1013"], "exclude": false, "fee": 2.5 },
      { "id": "a2", "name": "Outer ring", "shape": "radius", "radius": 8, "exclude": false, "fee": 4.5 }
    ]
  }
}

The town-centre postcodes pay €2.50; anything else within 8 km pays €4.50. Swapping the two rows would make every town-centre address pay €4.50, because the radius would match first.

A carve-out and an extension ​

json
{
  "delivery_region": {
    "zones": [
      { "id": "a1", "name": "Not Kerkstraat", "shape": "street", "streets": [{ "id": "s1", "street": "Kerkstraat", "postal_code": "1012" }], "exclude": true },
      { "id": "a2", "name": "Nearby streets", "shape": "street", "streets": [{ "id": "s2", "street": "Molenweg", "postal_code": "1099" }], "exclude": false, "fee": 4.5 },
      { "id": "a3", "name": "Town", "shape": "postcode", "postal_codes": ["1012", "1013", "1014"], "exclude": false, "fee": 2.5 }
    ]
  }
}

For the delivery fee model these areas fall back to — base fee, free-delivery threshold, distance tiers, flat rate per km — see Delivery Settings.