# Event date and delivery zones

Chapter 10 of the Hooray user guide.

Party orders are about a day. Hooray puts a small panel in the cart drawer and on the cart page, above the subtotal, where the shopper chooses **pickup or delivery**, picks the **event date** on a calendar that knows your lead times and closed days, and, for delivery, **checks their postcode** against your delivery zones. Their choices travel with the order as cart attributes.

> **Important:** Shopify's checkout doesn't know about any of this. The theme can't change what checkout charges or offers, and a shopper who reaches checkout another way (a saved checkout link, or an express button if you show them) skips the panel. Always check the date and the fulfilment on each order, and set up Shopify's own **Local delivery** and **Pickup in store** so the prices and areas match (below).

## What shoppers see

The panel shows as soon as the cart has something in it:

1. **The heading**, "When's the party?".
2. **Pickup or Delivery**, as two buttons, when you offer both. With only one, there's no choice to make. With Pickup chosen, your **Pickup note** ("Pick up from 12 Streamer Lane, Marrickville") shows under it.
3. **A month calendar** with arrows for the previous and next month. Days that can't be chosen stay readable but greyed, and tell screen readers why: **Past**, **Closed**, **Too soon** or **Too far ahead**. The chosen day is a small balloon in the accent colour.
4. **The reason line**: "Your order needs 2 days, so the first date is Fri 13 Nov." When the slowest thing in the cart is a garland from the builder, it says "Your garland needs 3 days…".
5. **A time slot**, a dropdown, when you've written slots for the chosen method.
6. **For delivery, a postcode field** and a **Check** button. A postcode in a zone shows the zone and its fee text: "Inner West: $25 delivery and setup". One outside every zone shows your **Message outside the zones** ("Outside our delivery area. Choose pickup or contact us."), with a **Switch to pickup** button (when you offer pickup) and a **Contact us** link (when you've chosen a **Contact page**).
7. **The saved line**: each choice saves straight away, and the panel confirms it: "Saved. Delivery on Sat 12 Dec to 2040, Inner West."

If a saved date stops being possible (a slower product goes in the cart, the cutoff passes, or the shopper switches to delivery, which adds days), the panel clears it and says so: "Your order needs 3 days, so we've cleared Fri 13 Nov. Please pick a new date." A date is never moved without telling the shopper.

## Settings

All in **Theme settings › Event date and delivery**:

| Setting | Default | What it does |
| --- | --- | --- |
| Show the event date panel in the cart | On | Off removes the panel, and **Hide Buy it now and express buttons** then does nothing |
| Offer pickup | On | |
| Offer delivery | On | With both off, there's no panel |
| Heading in the cart | "When's the party?" | |
| Lead time | 2d | 0 to 30 days. Used for products with no `custom.lead_days` metafield. |
| Daily order cutoff | 2 pm | **No cutoff**, or any hour from 6 am to 10 pm. Orders after this time count from the next day, in the store time zone. |
| Store time zone | Sydney | Dates are worked out in this zone, wherever the shopper is. 32 cities, from Auckland to Honolulu. |
| Other time zone | | Overrides the list, for example Asia/Singapore. Leave blank to use the list. A name the browser doesn't recognise is ignored, with a note in the theme editor. |
| Closed days and dates | Monday | One per line (see below) |
| Furthest date shoppers can pick | 180d | 15 to 365 days, in steps of 5, counted from today |
| Pickup time slots | | One per line, such as `10 am to 12 pm`. Leave blank for no time slot. |
| Delivery time slots | | One per line. Leave blank for no time slot. |
| Extra days for delivery | 1d | 0 to 7 days, added to the lead time when the shopper picks delivery |
| Pickup note | Each preset's sample address | Shown when the shopper picks pickup, and under the Delivery zones table |
| Delivery zones | Three sample Sydney zones | One zone per line (see below) |
| Message outside the zones | "Outside our delivery area. Choose pickup or contact us." | |
| Contact page | | The page the outside message's **Contact us** link opens. Blank hides the link. |
| Delivery zones page | | A page to link to from the menu drawer and the product page's **Delivery note**. Give it the `page.delivery` template. |
| Require a date and zone before checkout | Off (on in the Garland preset) | See **Holding Check out** below |
| Hide Buy it now and express buttons | On | Hides Buy it now on product pages and in quick view, and the express payment buttons in the cart, because they skip the cart and so skip the date |

## How the first date is worked out

In this order:

1. **Today**, in the store time zone.
2. **One more day** if it's past the **Daily order cutoff**.
3. **Plus the lead time**: the largest `custom.lead_days` of anything in the cart, or **Lead time** for products without one. Lead time is a fallback, not a minimum: a product with `custom.lead_days` 1 counts as 1 even when **Lead time** is 2.
4. **Plus Extra days for delivery**, when the shopper picks delivery.
5. **Then forward past closed days** to the first open day.

Lead time is in calendar days, and closed days don't add to it: they only move the first date forward onto an open day. So with a 2-day lead, closed Mondays and an order on Saturday morning, the first date is Tuesday. The latest date is **Furthest date shoppers can pick** days from today.

A Los Angeles shopper on a Sydney store sees Sydney's dates, and daylight saving is handled for you.

## Closed days and dates

One per line, in any of these forms:

```
Monday
Sun
2026-12-25
2026-12-24 to 2027-01-02
```

* **A weekday**, in English, written in full or as its first three letters. That day is closed every week.
* **A date**, written year-month-day.
* **A range**, two dates with `to` between them. Both days are included, and the end must not be before the start.

A line the theme can't read is listed for you in the theme editor ("these lines in Closed days and dates weren't understood") and ignored for shoppers. Closed means shoppers can't choose that day for a pickup or a delivery.

## Delivery zones

**Delivery zones** is a list, one zone per line, in three parts separated by `|`:

```
Name | postcodes | fee text
```

For example:

```
Inner West | 2040, 2041, 2042, 2044, 2048, 2049, 2050, 2203, 2204 | $25 delivery and setup
City and East | 2000, 2007, 2008, 2010, 2021 | $35 delivery and setup
North Shore | 2060, 2061, 2062, 2065 to 2068 | $45 delivery and setup
```

* **Name** is what the shopper sees and what's saved on the order as **Delivery zone**.
* **Postcodes** are separated by commas. **`2065 to 2068`** (or `2065-2068`) is a range, both ends included. Ranges work only for postcodes that are all digits.
* **Fee text** is shown beside the zone name, word for word. It can be anything: "$25 delivery and setup", "Free over $150", "Quote on request". Leave it out (`North Shore | 2060, 2061`) to show the name alone.

How a postcode is matched:

* Spaces are ignored and capitals don't matter, so `sw1a 1aa` matches `SW1A1AA`.
* A postcode must be 3 to 10 letters or digits; anything else gets "Enter a postcode, like 2040."
* Postcodes are matched whole. There is no prefix matching, so for letter-and-number postcodes (UK, Canada) list each full postcode you serve, or use pickup and a contact link for the rest.
* The first zone that holds the postcode wins, so put smaller, cheaper zones first if they overlap.
* A line without a name or without a postcode it can read is skipped, and listed for you in the theme editor ("Line 3 isn't in the Name | postcodes | fee format").

**Fees here are text only.** The theme doesn't add a delivery fee to the cart or change what checkout charges. What the shopper pays for delivery is whatever your Shopify shipping settings say, so set up Local delivery to match (below).

**The Delivery zones table**: the **Delivery zones** block (chapter 5) prints your zones as a table, Zone, Postcodes and "Delivery and setup", with the pickup note under it. The `page.delivery` template already has one: create a page in **Online Store › Pages** called Delivery, give it that template and choose it as the **Delivery zones page**.

## Holding Check out

With **Require a date and zone before checkout** on, the cart's **Check out** button stays off until the shopper has:

* chosen a date,
* for delivery, checked a postcode that's inside a zone,
* and, if you've written time slots for their method, chosen a slot.

A short line right under the button says what's missing: "Choose your event date and check your postcode to check out.", "Choose your event date to check out." or "Choose a time to check out." The cart is checked again the moment the shopper presses the button, so a date that went stale while the cart sat open is caught.

It only holds the theme's own Check out button. Keep **Hide Buy it now and express buttons** on, or shoppers can pay with an express button and skip the date. Even then, a checkout link a shopper saved earlier, or an abandoned checkout email, goes straight to checkout. Shopify doesn't let a theme block those, so treat an order without a date as a reason to get in touch.

With it off, the panel is optional: shoppers can check out without a date.

## What you get on the order

The choices are saved as **cart attributes**, which become part of the order:

| Attribute | Example | Notes |
| --- | --- | --- |
| `Event date` | Sat 12 Dec 2026 | Blank if the shopper didn't choose one |
| `Fulfilment` | Pickup or Delivery | What the shopper asked for in the cart |
| `Delivery postcode` | 2040 | Delivery only. Spaces removed, capitals. |
| `Delivery zone` | Inner West | The zone's name, or "Outside area" for a postcode checked outside every zone. Delivery only. |
| `Time slot` | 10 am to 12 pm | Only when you've written slots |

In Shopify admin, open the order: cart attributes are listed in the order's **Additional details**. Pickup clears the postcode and zone, so a pickup order doesn't carry a stale delivery address.

To show the date on your order emails, edit the template in **Settings › Notifications** and add a line such as `Event date: {{ attributes['Event date'] }}`.

## Set up Shopify's local delivery to match

The theme tells shoppers where you deliver and what it costs. Shopify's **Local delivery** is what offers delivery at checkout and charges for it. Make them say the same thing.

1. In Shopify admin, go to **Settings › Shipping and delivery**.
2. Under **Additional delivery methods**, click **Local delivery**, then your shop's location.
3. Under **Location status**, turn on **Deliver orders to customers directly from this location**.
4. Under **Delivery zones**, choose **Use postal codes**, then **Add zone**. For each line of the theme's **Delivery zones**:
   * **Zone name**: the same name, such as Inner West.
   * **Postal codes**: the same postcodes, separated by a comma and a space. Shopify doesn't take ranges, so write `2065 to 2068` out as `2065, 2066, 2067, 2068`. Shopify does accept a prefix with an asterisk, such as `206*`, but that covers every postcode starting 206, so only use one if the theme's zone lists all of them.
   * **Delivery price**: the price in the theme's fee text. Enter 0 for free delivery.
   * **Minimum order price** and conditional pricing, if you use them, and say so in the fee text ("Free over $150").
   * **Delivery information**: optional words shown in the order confirmation, such as "We'll text a two-hour window the day before."
5. **Save**.

Shopify allows up to 10 zones per location, with up to 3,000 characters of postal codes each. Shopify also offers **Set a delivery radius** instead of postal codes, but the theme can only check postcodes, so zones by postal code are the way to keep the two in step.

At checkout, Shopify offers **Local delivery** when the customer's delivery address is inside one of your zones. It goes by the address typed at checkout, not the postcode checked in the cart, so a shopper can check one postcode and deliver to another: the order's **Delivery postcode** and its shipping address tell you if they differ. Shopify's own checkout has no delivery date: the date only exists as the theme's `Event date` attribute. Express checkouts other than Shop Pay don't offer Local delivery, another reason to leave **Hide Buy it now and express buttons** on.

If you deliver only locally, also review your other shipping rates in **Settings › Shipping and delivery**, so checkout doesn't offer standard shipping you don't want to send.

## Set up Shopify's pickup to match

1. In **Settings › Shipping and delivery**, under **Additional delivery methods**, click **Pickup in store**, then your location.
2. Under **Location status**, turn on **Let customers pick up orders directly at this location**.
3. Choose an **Expected pickup date** that matches your **Lead time**.
4. Write your pickup instructions under **Ready for pickup notification**: the address, where to park, your hours. Keep them in step with the theme's **Pickup note** and **Pickup time slots**.
5. **Save**.

With pickup turned on, the product page's **Pickup availability** block shows which of your locations have the variant in stock (chapter 6).
