Shopify Notification Email Template Generator

Get branded Liquid for your Shopify order confirmation and shipping confirmation emails, with line item properties and metafields.

Describe the result you need. AI will set up the tool and ask for any missing details.

Configure with AI

Enter to submit · Shift + Enter for a new line

Sent to AI. Leave out passwords and private customer data.

Your details

Template
Line items

Engraving, gift notes and other options customers add on the product page. Properties starting with _ stay hidden.

Branding

Falls back to the color above if none is set.

Links to /pages/withdrawal with the order number filled in.

Paste into the template's Email body (HTML)

order-confirmation.liquid
{%- comment -%}
  Order confirmation email body.
  Settings > Notifications > Customer notifications > Order confirmation > Edit code.
  Keep a copy of the default template before replacing it.
{%- endcomment -%}
{%- assign accent_color = '#1f3a5f' -%}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Order {{ order_name }}</title>
<style>
body{margin:0;padding:0;background:#f4f4f4;font-family:-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;color:#222222;-webkit-text-size-adjust:100%}
.wrapper{width:100%;background:#f4f4f4;padding:24px 0}
.container{width:100%;max-width:560px;margin:0 auto;background:#ffffff;border-radius:8px}
.content{padding:32px}
.shop-name{margin:0;font-size:20px;font-weight:700}
h1{font-size:22px;line-height:1.3;margin:12px 0 8px}
p{font-size:15px;line-height:1.55;margin:0 0 12px}
.muted{color:#6b6b6b;font-size:13px}
.button{display:inline-block;padding:12px 22px;border-radius:6px;color:#ffffff;text-decoration:none;font-weight:600;font-size:15px}
.items td{padding:12px 0;border-bottom:1px solid #eeeeee;vertical-align:top;font-size:14px}
.item-image{width:64px;padding-right:12px}
.item-image img{border-radius:6px;display:block}
.item-title{font-weight:600;margin:0 0 2px;font-size:14px}
.item-meta{margin:0;color:#6b6b6b;font-size:13px}
.item-price{text-align:right;white-space:nowrap;padding-left:12px}
.totals td{padding:4px 0;font-size:14px}
.totals .total td{font-size:17px;font-weight:700;padding-top:10px;border-top:1px solid #eeeeee}
.section-title{font-size:12px;text-transform:uppercase;letter-spacing:.06em;color:#6b6b6b;margin:28px 0 8px}
.footer{padding:20px 32px 28px;color:#8a8a8a;font-size:12px;text-align:center}
@media (max-width:600px){.wrapper{padding:0}.container{border-radius:0}.content{padding:20px}}
</style>
</head>
<body>
<table role="presentation" class="wrapper" width="100%" cellpadding="0" cellspacing="0"><tr><td>
<table role="presentation" class="container" align="center" width="100%" cellpadding="0" cellspacing="0"><tr><td class="content">
{%- if shop.email_logo_url -%}
<img src="{{ shop.email_logo_url }}" alt="{{ shop.name | escape }}" width="{{ shop.email_logo_width }}" style="max-width:100%;height:auto;">
{%- else -%}
<p class="shop-name">{{ shop.name }}</p>
{%- endif -%}
<p class="muted" style="margin-top:16px;">Order {{ order_name }} · {{ created_at | date: '%B %-d, %Y' }}</p>
<h1>Thank you for your order</h1>
{%- if customer.first_name != blank -%}
<p>Hi {{ customer.first_name }},</p>
{%- endif -%}
<p>We're getting your order ready. We'll email you again as soon as it ships.</p>
<p style="margin:24px 0;"><a href="{{ order_status_url }}" class="button" style="background-color:{{ accent_color }};">View your order</a></p>
<p class="section-title">Order summary</p>
<table role="presentation" class="items" width="100%" cellpadding="0" cellspacing="0">
{%- for line in subtotal_line_items -%}
<tr>
<td class="item-image">{%- if line.image -%}<img src="{{ line.image | image_url: width: 112, height: 112 }}" alt="{{ line.title | escape }}" width="56" height="56">{%- endif -%}</td><td>
<p class="item-title">{{ line.title }} &times; {{ line.quantity }}</p>
{%- for property in line.properties -%}
  {%- assign property_first_char = property.first | slice: 0 -%}
  {%- if property.last != blank and property_first_char != '_' -%}
<p class="item-meta">{{ property.first | escape }}: {{ property.last | escape }}</p>
  {%- endif -%}
{%- endfor -%}
{%- assign metafield_value = line.product.metafields['custom']['care_instructions'] -%}
{%- if metafield_value != blank -%}
<p class="item-meta">Care: {{ metafield_value }}</p>
{%- endif -%}
{%- for discount_allocation in line.discount_allocations -%}
  {%- if discount_allocation.discount_application.target_selection != 'all' -%}
<p class="item-meta">{{ discount_allocation.discount_application.title | upcase | escape }} (-{{ discount_allocation.amount | money }})</p>
  {%- endif -%}
{%- endfor -%}
</td>
<td class="item-price">{%- if line.original_line_price != line.final_line_price -%}<del class="item-meta">{{ line.original_line_price | money }}</del><br>{%- endif -%}{{ line.final_line_price | money }}</td>
</tr>
{%- endfor -%}
</table>
{%- assign items_total = 0 -%}
{%- for line in subtotal_line_items -%}
  {%- assign items_total = items_total | plus: line.final_line_price -%}
{%- endfor -%}
<table role="presentation" class="totals" width="100%" cellpadding="0" cellspacing="0" style="margin-top:12px;">
<tr><td>Items</td><td align="right">{{ items_total | money }}</td></tr>
{%- for discount_application in discount_applications -%}
  {%- if discount_application.target_selection == 'all' and discount_application.target_type == 'line_item' -%}
<tr><td>Discount ({{ discount_application.title | escape }})</td><td align="right">-{{ discount_application.total_allocated_amount | money }}</td></tr>
  {%- endif -%}
{%- endfor -%}
<tr><td>Subtotal</td><td align="right">{{ subtotal_price | money }}</td></tr>
{%- if requires_shipping -%}
<tr><td>Shipping{% if shipping_method.title != blank %} ({{ shipping_method.title }}){% endif %}</td><td align="right">{{ shipping_price | money }}</td></tr>
{%- endif -%}
{%- for discount_application in discount_applications -%}
  {%- if discount_application.target_type == 'shipping_line' -%}
<tr><td>Shipping discount ({{ discount_application.title | escape }})</td><td align="right">-{{ discount_application.total_allocated_amount | money }}</td></tr>
  {%- endif -%}
{%- endfor -%}
{%- if current_total_duties -%}
<tr><td>Duties</td><td align="right">{{ current_total_duties | money }}</td></tr>
{%- endif -%}
{%- if tax_price > 0 -%}
<tr><td>Taxes</td><td align="right">{{ tax_price | money }}</td></tr>
{%- endif -%}
<tr class="total"><td>Total</td><td align="right">{{ total_price | money_with_currency }}</td></tr>
</table>
{%- if shipping_address -%}
<p class="section-title">Shipping address</p>
<p>{{ shipping_address.name }}<br>{{ shipping_address.address1 }}{% if shipping_address.address2 != blank %}, {{ shipping_address.address2 }}{% endif %}<br>{{ shipping_address.city }}{% if shipping_address.province_code != blank %} {{ shipping_address.province_code }}{% endif %} {{ shipping_address.zip }}<br>{{ shipping_address.country }}</p>
{%- endif -%}
</td></tr>
<tr><td class="footer">Questions? Just reply to this email.</td></tr>
</table>
</td></tr></table>
</body>
</html>

In Shopify admin go to Settings → Notifications → Customer notifications → Order confirmation → Edit code. Replace the Email body (HTML), click Preview, then Send test email before you save. Revert to → Default brings back Shopify's version.

This is a simpler layout than Shopify's default. It leaves out gift cards, tips, local pickup and delivery instructions, payment terms, subscriptions and bundles. Keep the default if you use those.

The custom.care_instructions line only shows for products where that metafield has a value. Single-line and multi-line text metafields work best.

Live preview

What's in the template

The generator writes a complete Email body (HTML) using Shopify's notification variables. In notifications, order fields are used without the order. prefix, so it's {{ order_name }}, not {{ order.name }}.

PartVariables used
Headershop.email_logo_url, shop.name, order_name, created_at
Items (order)subtotal_line_items, line.title, line.final_line_price, line.original_line_price, line.discount_allocations
Items (shipping)fulfillment.fulfillment_line_items, fulfillment_line.quantity
Custom detailsline.properties, line.product.metafields
Totalssubtotal_price, discount_applications, shipping_price, current_total_duties, tax_price, total_price
Trackingfulfillment.tracking_company, fulfillment.tracking_numbers, fulfillment.tracking_urls, fulfillment.estimated_delivery_at

Line item properties are the options shoppers fill in on the product page, such as an engraving. Properties whose name starts with _ stay hidden, the same convention Shopify's own templates follow.

Replacing your template

  1. 01

    Open the template

    Go to Settings → Notifications → Customer notifications, click Order confirmation or Shipping confirmation, then Edit code.

  2. 02

    Keep a copy

    Copy the current Email body (HTML) somewhere safe first.

  3. 03

    Paste and preview

    Replace the body with the generated code, click Preview, then Send test email to see it in a real inbox.

  4. 04

    Save or revert

    Click Save. To undo, use Revert to → Default.

Shopify inlines the CSS in the <style> tag automatically when it sends the email, and keeps the media queries for phones.

Before you switch

  • It's deliberately simpler than the default. Gift cards, tips, local pickup, payment terms, subscriptions and bundles aren't handled. Keep Shopify's template if you use them.
  • Languages. Once you edit the body, it no longer changes with your theme language. If you sell in several languages, update each translation of the template too.
  • Tax numbers. In the EU you may need your VAT number in the email. Add it to the footer text.
  • EU withdrawal link. The optional link sends shoppers to your withdrawal page with the order number filled in. Build the page with the EU withdrawal button generator.

Questions people ask

Where do I edit the Shopify order confirmation email?

In Settings → Notifications → Customer notifications → Order confirmation → Edit code.

How do I show a product metafield in the email?

Enter its namespace and key, for example custom.care_instructions. The line shows only for products where the metafield has a value.

Can I use my logo and brand color?

The template uses the logo from Customize email templates. For color, use your own hex or turn on the option to use the accent color set in admin.

Will this break if a product has no image?

No. The image cell stays empty for items without an image.

Want this builtinto your store?

I'm Emmanuel, a Shopify and WooCommerce developer. If this tool pointed at something you'd rather have fixed for you (a faster store, cleaner product data, a migration, a custom feature), send me a note.

Emmanuel Asika

Emmanuel Asika

Shopify & WooCommerce developer, Dublin

I build and fix online stores: new builds, migrations, speed, SEO and the custom bits apps can't do.

hello@emmanuelasika.com