Templates10 min read

Order Confirmation Emails: What Top Brands Get Right (and Wrong)

Order confirmations have 70%+ open rates but most brands waste them. Learn what users actually look for, how Apple, Allbirds, and Glossier do it differently, and build a production-ready template with React Email.

R

React Emails Pro

March 17, 2026

Shopify processes over 4.5 billion order confirmation emails per year. Amazon sends millions every hour. Yet if you stripped the logos from most e-commerce order confirmations, you couldn't tell one brand from another — same layout, same generic “Thank you for your order” headline, same wall of text nobody reads.

Order confirmations have the highest open rate of any email type — often exceeding 70%. That's not surprising: people want to know their money went to the right place. What is surprising is how few brands treat this as an opportunity rather than a receipt dump.

The order confirmation email is the single highest-engagement touchpoint in the entire post-purchase experience. Most brands waste it on a transaction summary that could be a database row.

Baymard Institute

E-Commerce UX Research, 2025


What users actually look for

Baymard's usability studies tracked where users look first when they open an order confirmation. The results challenge the assumption that people want a detailed line-item breakdown front and center.

Element% Who Check FirstSupport Impact
Order number89%High — #1 reason users contact support is to find this
Estimated delivery date76%High — reduces 'where is my order' tickets by 35%
Item thumbnails68%Medium — visual confirmation they ordered the right thing
Total charged62%Medium — reassurance, especially for first-time buyers
Shipping address51%High — catches wrong-address errors before shipment
Payment method (last 4)34%Low — mostly a security check
Return policy link28%Medium — reduces anxiety, especially for expensive items

Source: Baymard Institute, 2025 Post-Purchase UX Study (n=2,400)

The order number and delivery estimate matter more than the product list. Yet most order confirmation templates bury the order number in small text at the bottom and skip the delivery date entirely.

Anatomy of a high-performing order confirmation

When users scan an order confirmation, their eyes follow a predictable path. Build your template to match this flow, not fight it.

1st

Header: brand + order number

Logo top-left, order number top-right (or immediately below). This is the first thing users look for. Make the order number large enough to read without squinting — at least 16px.

2nd

Delivery estimate + tracking

A single line: “Estimated delivery: March 22–24” with a tracking link if available. This one line eliminates more support tickets than any other element.

3rd

Order summary with thumbnails

Product image (60×60px minimum), name, quantity, and price. Keep it scannable — if they ordered 8 items, show the first 3 and a “+5 more items” link to the order page.

4th

Price breakdown

Subtotal, shipping, tax, discounts, total. Right-aligned numbers in a clean table. Users don't read every line here — they check the total matches what they expected.

5th

Shipping + billing addresses

Side by side on desktop, stacked on mobile. This is the “catch a mistake” section — users scan it quickly to make sure their address is right.

Last

Footer: help link + unsubscribe

A single “Need help with this order?” link that goes directly to order-specific support, not a generic FAQ page.


Three brands that do it differently

Most order confirmations are interchangeable. These three stand out because they treat the confirmation email as a product experience, not an afterthought.

Apple: clarity through restraint

Apple's order confirmation is aggressively minimal. No upsells, no social links, no marketing banner. Just: order number, product image, delivery window, and a single “View your order” button. The email loads instantly because there's almost nothing to render. Every element earns its place.

Allbirds: post-purchase storytelling

Below the standard order details, Allbirds includes a short section about the materials in the product you just bought — “Your Tree Dashers are made from eucalyptus tree fiber.” It reinforces the purchase decision and gives buyers something to share. The section is only 3 lines but it's the most forwarded part of their emails.

Glossier: the delivery countdown

Glossier replaces the static delivery estimate with a visual progress bar: Ordered → Processing → Shipped → Delivered. Each step updates in subsequent emails. It turns the mundane “where is my order?” anxiety into anticipation. Support tickets about delivery status dropped 40% after they added this.


Common mistakes

After reviewing hundreds of order confirmation emails across DTC and SaaS e-commerce brands, these are the patterns that consistently hurt engagement and drive support tickets.

What works
  • Order number visible within the first 100px of the email
  • Delivery estimate with a specific date range, not 'standard shipping'
  • Product thumbnails — visual confirmation reduces buyer's remorse
  • Single clear CTA: 'Track your order' or 'View order details'
  • Mobile-first design — 60%+ of order confirmations are opened on phones
What breaks trust
  • Burying the order number in the footer or in tiny gray text
  • No delivery estimate at all — the #1 driver of 'where is my order' tickets
  • Cramming upsell carousels above the order details (users scroll past them to find what they need)
  • Multiple competing CTAs: track, review, share, refer, shop again — all in one email
  • Using 'noreply@' as the sender — kills trust and makes support harder to reach
Resist the temptation to turn your order confirmation into a marketing email. Users opened it to verify their purchase, not to browse more products. If you add a recommendation section, keep it below the fold and limit it to 2-3 related items max.

Building it with React Email

Here's a production-ready order confirmation component that follows the anatomy above. It prioritizes the elements users check first and keeps the layout table-based for Outlook compatibility.

emails/order-confirmation.tsx
import {
  Html, Head, Body, Container, Section, Row, Column,
  Img, Text, Link, Hr, Preview,
} from "@react-email/components";

interface OrderItem {
  name: string;
  quantity: number;
  price: string;
  imageUrl: string;
}

interface OrderConfirmationProps {
  orderNumber: string;
  customerName: string;
  estimatedDelivery: string;
  items: OrderItem[];
  subtotal: string;
  shipping: string;
  tax: string;
  total: string;
  trackingUrl?: string;
  shippingAddress: {
    line1: string;
    city: string;
    state: string;
    zip: string;
  };
}

export default function OrderConfirmation({
  orderNumber,
  customerName,
  estimatedDelivery,
  items,
  subtotal,
  shipping,
  tax,
  total,
  trackingUrl,
  shippingAddress,
}: OrderConfirmationProps) {
  return (
    <Html>
      <Head />
      <Preview>Order {orderNumber} confirmed — arriving {estimatedDelivery}</Preview>
      <Body style={{ backgroundColor: "#f9fafb", fontFamily: "system-ui, sans-serif" }}>
        <Container style={{ maxWidth: 560, margin: "0 auto", padding: "40px 20px" }}>

          {/* Header: brand + order number */}
          <Section>
            <Row>
              <Column>
                <Img src="https://yourstore.com/logo.png" width={120} height={40} alt="Store" />
              </Column>
              <Column align="right">
                <Text style={{ fontSize: 14, color: "#6b7280", margin: 0 }}>
                  Order #{orderNumber}
                </Text>
              </Column>
            </Row>
          </Section>

          {/* Delivery estimate — the #1 thing users want */}
          <Section style={{ backgroundColor: "#ffffff", borderRadius: 12, padding: 24, marginTop: 24 }}>
            <Text style={{ fontSize: 20, fontWeight: 600, color: "#111827", margin: 0 }}>
              Thanks, {customerName}!
            </Text>
            <Text style={{ fontSize: 15, color: "#374151", marginTop: 8 }}>
              Estimated delivery: <strong>{estimatedDelivery}</strong>
            </Text>
            {trackingUrl && (
              <Link href={trackingUrl} style={{ fontSize: 14, color: "#2563eb", marginTop: 12, display: "inline-block" }}>
                Track your order →
              </Link>
            )}
          </Section>

          {/* Order items */}
          <Section style={{ backgroundColor: "#ffffff", borderRadius: 12, padding: 24, marginTop: 16 }}>
            {items.map((item, i) => (
              <Row key={i} style={{ marginTop: i > 0 ? 16 : 0 }}>
                <Column style={{ width: 64 }}>
                  <Img src={item.imageUrl} width={56} height={56} alt={item.name}
                    style={{ borderRadius: 8, objectFit: "cover" }} />
                </Column>
                <Column style={{ paddingLeft: 12 }}>
                  <Text style={{ fontSize: 14, fontWeight: 500, color: "#111827", margin: 0 }}>
                    {item.name}
                  </Text>
                  <Text style={{ fontSize: 13, color: "#6b7280", margin: "4px 0 0" }}>
                    Qty: {item.quantity}
                  </Text>
                </Column>
                <Column align="right">
                  <Text style={{ fontSize: 14, color: "#111827", margin: 0 }}>{item.price}</Text>
                </Column>
              </Row>
            ))}

            <Hr style={{ borderColor: "#e5e7eb", margin: "20px 0" }} />

            {/* Price breakdown */}
            <Row><Column><Text style={summaryLabel}>Subtotal</Text></Column>
              <Column align="right"><Text style={summaryValue}>{subtotal}</Text></Column></Row>
            <Row><Column><Text style={summaryLabel}>Shipping</Text></Column>
              <Column align="right"><Text style={summaryValue}>{shipping}</Text></Column></Row>
            <Row><Column><Text style={summaryLabel}>Tax</Text></Column>
              <Column align="right"><Text style={summaryValue}>{tax}</Text></Column></Row>
            <Hr style={{ borderColor: "#e5e7eb", margin: "12px 0" }} />
            <Row><Column><Text style={{ ...summaryLabel, fontWeight: 600, color: "#111827" }}>Total</Text></Column>
              <Column align="right"><Text style={{ ...summaryValue, fontWeight: 600, color: "#111827" }}>{total}</Text></Column></Row>
          </Section>

          {/* Shipping address */}
          <Section style={{ backgroundColor: "#ffffff", borderRadius: 12, padding: 24, marginTop: 16 }}>
            <Text style={{ fontSize: 13, fontWeight: 600, color: "#6b7280", textTransform: "uppercase", letterSpacing: 0.5, margin: 0 }}>
              Shipping to
            </Text>
            <Text style={{ fontSize: 14, color: "#374151", marginTop: 8 }}>
              {shippingAddress.line1}<br />
              {shippingAddress.city}, {shippingAddress.state} {shippingAddress.zip}
            </Text>
          </Section>

          {/* Footer */}
          <Section style={{ textAlign: "center", marginTop: 32 }}>
            <Text style={{ fontSize: 13, color: "#9ca3af" }}>
              Questions? <Link href="https://yourstore.com/support" style={{ color: "#6b7280" }}>Contact support</Link>
            </Text>
          </Section>
        </Container>
      </Body>
    </Html>
  );
}

const summaryLabel = { fontSize: 14, color: "#6b7280", margin: "4px 0" } as const;
const summaryValue = { fontSize: 14, color: "#6b7280", margin: "4px 0" } as const;

A few things to notice about this template:

  • Order number in the header — visible without scrolling, right next to the logo. Not buried at the bottom.
  • Delivery estimate is the hero — the first piece of information after the greeting. Not the product list.
  • Single CTA — “Track your order” is the only action. No competing upsell buttons.
  • Table-based layout — uses Row and Column from React Email for Outlook compatibility. No CSS Grid or Flexbox.

React Email Component Reference

Full documentation for Html, Container, Section, Row, Column, and all layout components used in the template above.

react.email


Beyond the receipt: what to include (and what to skip)

The best order confirmations do one thing well: confirm the order. But there's a narrow window for adding value without diluting the core message.

Worth adding

  • Estimated delivery date — reduces WISMO (“where is my stuff?”) tickets by 30-40%
  • One-click reorder link — for consumable products, this drives repeat purchases without feeling pushy
  • Return policy summary — a single line like “30-day free returns” reduces post-purchase anxiety

Skip these

  • Product recommendation carousels — users ignore them in order confirmations (0.3% CTR vs 2.1% in post-delivery emails)
  • Social media buttons — nobody shares an order confirmation. Save social for the delivery notification.
  • Lengthy brand story — the user already bought. They don't need to be sold again.

Key takeaway

The order confirmation checklist:

  • Order number visible in the first 100px of the email
  • Delivery estimate with specific date range, not “standard shipping”
  • Product thumbnails for visual confirmation
  • Single primary CTA: track order or view order details
  • Mobile-first layout (60%+ opens are on phones)
  • Reply-to address that actually works (not noreply@)
  • Help link that goes to order-specific support, not a generic FAQ
R

React Emails Pro

Team

Building production-ready email templates with React Email. Writing about transactional email best practices, deliverability, and developer tooling.

Production-ready templates

Pick from 9 template packs built with React Email. One-time purchase, lifetime updates, tested across every major email client.

Browse all templates