How to Add a Delivery Date Picker to Shopify Order Confirmation Email
Why a Delivery Date in the Order Confirmation Email Cuts WISMO Tickets
The order confirmation email is the most-read message you will ever send a customer. It lands in the inbox within seconds of checkout, when attention is at its peak, and it sets expectations for everything that follows. If it says "we'll be in touch" and nothing else, the next thing the customer sends you is a "when will my order arrive?" email — a WISMO ticket.
Adding an estimated delivery date to that email moves the question from the customer's outbox to your inbox template. It also reduces the second-order problem: customers who know the date stop refreshing tracking pages, stop opening support chats, and stop filing chargebacks when a package is two days behind. The mechanics are straightforward — a metafield, a Liquid block, and a fallback — and you can ship it in an afternoon.
What You Need Before You Start (Metafields, Liquid Access, and a Delivery Date Source)
Before touching the email template, confirm you have these four things:
- A Shopify plan that allows metafield definitions and email template editing. Order metafields and the notification template editor are available on standard plans; check your plan's features in Settings → Plan if you're unsure.
- A delivery date source. This is the part most guides skip. You need something that produces a date per order: a delivery-date app, a fulfillment/route planning tool, or a manual process your team follows. A metafield with nothing writing to it is just an empty box.
- A metafield definition with the right namespace and type. Use a custom namespace such as
deliveryand thedatetype so Shopify validates the value and the Liquid renders cleanly. - Access to the order confirmation template. In Shopify admin, go to Settings → Notifications → Order confirmation → Edit code. You'll be editing the
Order confirmationemail template, which is Liquid with HTML around it.
If you use a delivery-date or shipping-rules app, check its documentation for whether it already writes a metafield — many do, and you can skip Step 2 entirely. If it doesn't, you'll populate the field yourself.
Step 1: Create the Delivery Date Metafield Definition in Shopify
- In Shopify admin, go to Settings → Custom data → Orders.
- Click Add definition.
- Name it something readable, e.g. Estimated delivery date. Shopify generates the namespace and key — set them to
delivery.estimated_date(or accept the generated key and note it exactly). - Set the type to Date.
- Leave "Storefront access" off — this is internal order data, not a storefront field.
- Save.
Write down the full key (delivery.estimated_date). Liquid is unforgiving about typos, and a wrong key renders nothing rather than throwing an error, which is the hardest kind of bug to spot.
Step 2: Populate the Metafield at Checkout or Fulfillment
You have three realistic options, in order of reliability:
Option A — App-driven. If your delivery-date app supports order metafields, enable that setting. This is the most reliable path because the app calculates the date using your cutoff times, carrier transit rules, and holiday calendar, then writes it automatically.
Option B — Flow automation. Shopify Flow can write order metafields on triggers like "Order created." Build a workflow that calculates or assigns a date and uses the Update order metafield action. This works well if you have simple rules, e.g. "orders before 2pm ship same day, plus 3 business days." Note that Flow's date math is limited — for anything involving business days or carrier calendars, an app is usually less work.
Option C — Manual. Your team sets the date on each order in the admin under the order's Metafields section, or in bulk via the order list. Fine for low volume or made-to-order products; not fine at scale.
Whichever route you choose, verify the value is actually being written before you build the email. Open a recent test order and check the metafield shows a date.
Step 3: Add the Delivery Date Block to Your Order Confirmation Email Template
- Go to Settings → Notifications → Order confirmation.
- Click Edit code.
- Find a sensible spot — typically after the order summary table and before the shipping address block. A short line under the order total reads naturally.
- Paste a placeholder block first, then wire up Liquid in Step 4:
<p style="margin:16px 0;font-size:15px;line-height:1.5;">
Estimated delivery: <strong>{{ order.metafields.delivery.estimated_date.value | date: "%A, %B %-d" }}</strong>
</p>
- Save.
Keep the styling inline and consistent with the rest of your template. Shopify's default templates use inline CSS because many email clients strip <style> blocks. If your template already has a wrapper class, reuse it rather than inventing new styles.
Step 4: Write the Liquid Logic (With Fallbacks for Missing Dates)
A raw metafield reference will print a blank line when the field is empty, which looks broken. Wrap it in a conditional with a fallback range based on your standard processing and transit times.
{% assign delivery_date = order.metafields.delivery.estimated_date.value %}
{% if delivery_date %}
<p style="margin:16px 0;font-size:15px;line-height:1.5;">
Estimated delivery: <strong>{{ delivery_date | date: "%A, %B %-d" }}</strong>
</p>
{% else %}
<p style="margin:16px 0;font-size:15px;line-height:1.5;">
Estimated delivery: <strong>3–5 business days</strong> after your order ships.
You'll get a tracking link as soon as it's on its way.
</p>
{% endif %}
A few practical notes:
date: "%-d"removes the leading zero on single-digit days, which reads better in prose. Use%eif your email client renders oddly.- If your metafield stores a datetime rather than a date, the
datefilter still works — just confirm the timezone behavior with a test order, since Shopify renders dates in the store's timezone. - If you want to show a range, store two metafields (
delivery.estimated_date_startanddelivery.estimated_date_end) and render them together, e.g. "Between June 3 and June 5." - Don't put the fallback in a
<strong>tag with a specific date — a hardcoded date in a template is a future support ticket.
Step 5: Test the Email With a Real Order and Preview Tools
Testing sequence that catches the real problems:
- Place a real test order using a test payment method or a 100% discount code, and make sure your automation or app writes the metafield.
- Trigger the confirmation email by checking out normally — do not rely on the preview alone, because previews don't always resolve order metafields.
- Check the rendered email in your inbox on both desktop and mobile. Look for the date formatting, the fallback behavior, and spacing around the block.
- Test the fallback path by placing an order that intentionally skips the metafield write (e.g., disable the Flow workflow temporarily) and confirm the fallback text appears.
- Use Shopify's preview in the notification editor for quick layout checks, but treat it as a secondary tool — it can show sample data that differs from a real order.
If you use a transactional email testing service like Litmus or Email on Acid, run the template through it once to catch client-specific rendering issues. Check current pricing on those tools before committing to a plan.
Common Errors and How to Fix Them
| Symptom | Likely cause | Fix |
|---|---|---|
| Blank line where the date should be | Metafield key typo or wrong namespace | Compare the Liquid key character-for-character with Settings → Custom data → Orders |
| Date shows as "1970-01-01" or similar | Empty or invalid value passed to the date filter |
Add the {% if delivery_date %} guard from Step 4 |
| Date is off by a day | Timezone difference between store and customer | Confirm store timezone in Settings → Store details; consider rendering date-only values |
| Everything after the block renders as plain text | Unclosed tag or malformed Liquid | Re-check that every {% if %} has a matching {% endif %} |
| Date never appears even with a value set | App writes to a different namespace than the template reads | Check the app's documentation for its exact metafield key |
| Preview looks right, real email doesn't | Preview uses sample data | Send a real test order through checkout |
Bonus: Let Customers Pick Their Delivery Date at Checkout
If you're already writing a date to the order, the next step is letting the customer choose it. Add a date picker to the cart or checkout using a cart attribute — a line item property or cart attribute field populated by a date input. On order creation, that value is available as an order attribute or line item property, and you can reference it in the confirmation email the same way you reference a metafield.
Two cautions. First, Shopify's checkout is locked down on non-Plus plans, so most date pickers live on the cart page or via an app that injects a widget — check what your theme and plan support before promising the feature. Second, only offer dates you can actually hit. A picker that lets customers choose next Tuesday when your cutoff is Thursday creates more WISMO tickets than it prevents. Gate the picker with your real cutoff rules and disable dates outside your window.
Conclusion
Adding a delivery date to your order confirmation email is a metafield definition, a Liquid conditional, and a reliable source writing the value — nothing more. The work is in the plumbing, not the template. Get the metafield populated automatically, add the fallback so the email never looks broken, and test with a real order before you call it done.
FAQ
Do I need a paid app to add a delivery date to the confirmation email? No. The email side is pure Liquid and works on standard Shopify plans. You only need an app if you want the date calculated automatically from carrier transit times and cutoff rules, or if you want a customer-facing date picker at checkout.
Will the delivery date show for orders placed before I set this up? No. Orders created before the metafield existed won't have a value, so they'll render the fallback text. That's expected and harmless.
Can I show a delivery range instead of a single date? Yes. Create two date metafields — a start and an end — and render both in the template, e.g. "Between June 3 and June 5." Keep the same fallback logic so the email stays clean when either value is missing.