Skip to main content

Estimated Arrival Line Item Properties

This document covers the line item properties used to calculate and display estimated arrival dates across the cart, checkout, and tracking page.

Overviewโ€‹

Estimated arrival dates for Made-to-Order (MTO) products flow through three systems:

  1. Hydrogen Storefront - Sets initial properties when adding to cart
  2. Platform Checkout Extension - Recalculates and updates properties at checkout
  3. Theme Tracking Page - Reads properties to display arrival estimates

Line Item Propertiesโ€‹

_PRODUCTION_DAYSโ€‹

Raw number of production days for the item.

AttributeValue
Set byHydrogen Storefront (cart)
Updated at checkoutNo
FormatInteger string (e.g., "56")
Used by tracking pageYes (fallback calculation)

Source Priority:

  1. Product's custom.production_days metafield
  2. Site settings dualSale.standardProductionDays default

_MADE-TO-ORDERโ€‹

Human-readable message with embedded delivery dates.

AttributeValue
Set byHydrogen Storefront (cart)
Updated at checkoutNo
Format"Expected to arrive between MM-dd-yyyy and MM-dd-yyyy"
Used by tracking pageNo (contains stale cart-time dates)

_PROMISED_BY_DATEโ€‹

Human-readable message with embedded delivery dates, recalculated at checkout.

AttributeValue
Set byHydrogen Storefront (cart)
Updated at checkoutYes (recalculated)
Format"Expected to arrive between MM-DD-YYYY and MM-DD-YYYY"
Used by tracking pageYes (V2 parses dates from value)

_MTO_DELIVERY_WINDOWโ€‹

The delivery window range in days (difference between upper and lower delivery estimates).

AttributeValue
Set byHydrogen Storefront (cart)
Updated at checkoutNo
FormatInteger string (e.g., "7")
Used by tracking pageNo

_SHIPPING_SPEEDโ€‹

Human-readable production timeline for display.

AttributeValue
Set byHydrogen Storefront (cart)
Updated at checkoutNo
Format"7-8 weeks" or "8 weeks"
Used by tracking pageNo

Calculation Logicโ€‹

Hydrogen Storefront (Cart)โ€‹

File: app/lib/cart.ts - prepareMTOProperties()

const productionDays = Number(productProperties?.productionDays)
|| siteSettings.dualSale.standardProductionDays;

const now = new Date();

// Upper bound: now + productionDays
const deliveryUpperEnd = new Date(now);
deliveryUpperEnd.setDate(deliveryUpperEnd.getDate() + productionDays);

// Lower bound: upperEnd - mtoDeliveryWindow
const mtoDeliveryWindow = resolveMtoDeliveryWindow(
mtoDeliveryDays,
siteSettings.dualSale.mtoDeliveryWindow
);
const deliveryLowerEnd = new Date(deliveryUpperEnd);
deliveryLowerEnd.setDate(deliveryLowerEnd.getDate() - mtoDeliveryWindow);

const deliveryMessage = mtoDeliveryWindow === 0
? `Expected to arrive ${format(deliveryUpperEnd, 'MM-dd-yyyy')}`
: `Expected to arrive between ${format(deliveryLowerEnd, 'MM-dd-yyyy')} and ${format(deliveryUpperEnd, 'MM-dd-yyyy')}`;

// Both _MADE_TO_ORDER and _PROMISED_BY_DATE get the same value
attributes.push(
{ key: '_PRODUCTION_DAYS', value: productionDays.toString() },
{ key: '_MADE-TO-ORDER', value: deliveryMessage },
{ key: '_PROMISED_BY_DATE', value: deliveryMessage },
{ key: '_SHIPPING_SPEED', value: standardProductionTimeline },
{ key: '_MTO_DELIVERY_WINDOW', value: mtoDeliveryWindow.toString() }
);

Platform Checkout Extensionโ€‹

File: platform/extensions/item-attributes/src/Checkout.jsx

The checkout extension recalculates _PROMISED_BY_DATE based on the current time at checkout, ensuring accurate estimates if items sat in the cart.

// Triggers on each buyer journey step
useEffect(() => {
for (const item of lineItems) {
// Only update items with _MADE-TO-ORDER property
if (item.attributes.some(attr => attr.key === '_MADE-TO-ORDER')) {
// Fetch fresh production days
const productionDays = await getProductionDaysMetafield(productId, query)
|| DEFAULT_MTO_PRODUCTION_DAYS; // from delayed_delivery metaobject

// Get delivery window from line item attributes (set by hydrogen-storefront)
const deliveryWindow = getMtoDeliveryWindow(item.attributes);

// Build message matching hydrogen-storefront format
const promisedByDateMessage = buildPromisedByDateMessage(productionDays, deliveryWindow);

// Update _PROMISED_BY_DATE (not _MADE-TO-ORDER)
await updateLineItemPromisedByDateAttribute(item, promisedByDateMessage, applyCartLinesChange);
}
}
}, [buyerCurrentStep]);

Key behaviors:

  • Recalculates based on checkout time, not cart add time
  • Reads _MTO_DELIVERY_WINDOW from line item attributes (defaults to 7 if not present)
  • Updates only _PROMISED_BY_DATE, leaves _MADE-TO-ORDER unchanged
  • Format matches hydrogen-storefront: "Expected to arrive between..."

Tracking Page (V1)โ€‹

File: theme/assets/tracking--order.js

V1 does not use _PROMISED_BY_DATE or parse dates from _MADE-TO-ORDER. Instead:

// Only uses shipping line code for MTO
if (isMTO) {
const matchedShippingLine = this.order.shipping_lines.find(
(shippingLine) => /(\d+)\s+weeks/.test(shippingLine.code)
);
if (matchedShippingLine) {
const weeks = Number(/(\d+)\s+weeks/.exec(matchedShippingLine.code)[1]);
estimatedDelivery.datetime_max = new Date(
orderProcessed.getTime() + weeks * 7 * 24 * 60 * 60 * 1000
);
estimatedDelivery.type = "until";
}
}

Tracking Page (V2)โ€‹

File: theme/assets/tracking--order-v2.js

V2 parses dates from the _PROMISED_BY_DATE property value (recalculated at checkout):

const getMtoEDDFromLineItems = (lineItems) => {
let earliestDate = null;
let latestDate = null;
let productionDays = null;

for (const lineItem of lineItems) {
for (const property of lineItem.properties) {
const propertyName = String(property?.name || "").toUpperCase();
const propertyValue = String(property?.value || "");

if (propertyName === "_PROMISED_BY_DATE") {
// Extract dates in MM-DD-YYYY format from the message
const datePattern = /\b(\d{1,2})-(\d{1,2})-(\d{4})\b/g;
for (const match of propertyValue.matchAll(datePattern)) {
const [, monthStr, dayStr, yearStr] = match;
const parsedDate = new Date(Date.UTC(
Number(yearStr),
Number(monthStr) - 1,
Number(dayStr)
));
if (!earliestDate || parsedDate < earliestDate) earliestDate = parsedDate;
if (!latestDate || parsedDate > latestDate) latestDate = parsedDate;
}
} else if (propertyName === "_PRODUCTION_DAYS") {
// Fallback: use production days to calculate
const daysMatch = propertyValue.match(/\d+/);
if (daysMatch) productionDays = parseInt(daysMatch[0], 10);
}
}
}

// Return based on what was found
if (earliestDate && latestDate && earliestDate.getTime() !== latestDate.getTime()) {
return { type: "range", datetime_min: earliestDate, datetime_max: latestDate };
}
if (latestDate) {
return { type: "specific", datetime: latestDate };
}
if (Number.isFinite(productionDays)) {
// Calculate from order date + production days
const baseDate = new Date(order.processed_at || order.created_at || Date.now());
return {
type: "until",
datetime_max: new Date(baseDate.getTime() + productionDays * 24 * 60 * 60 * 1000)
};
}
return null;
};

Priority order:

  1. Parse date range from _PROMISED_BY_DATE value (checkout-time dates)
  2. Parse single date from _PROMISED_BY_DATE value
  3. Calculate from _PRODUCTION_DAYS + order date (fallback)

Data Flow Summaryโ€‹

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ HYDROGEN STOREFRONT โ”‚
โ”‚ โ”‚
โ”‚ Add to Cart โ†’ prepareMTOProperties() โ”‚
โ”‚ โ”‚
โ”‚ Sets: โ”‚
โ”‚ โ€ข _PRODUCTION_DAYS = "56" โ”‚
โ”‚ โ€ข _MADE-TO-ORDER = "Expected to arrive between 01-15-2026 and 01-22-2026" โ”‚
โ”‚ โ€ข _PROMISED_BY_DATE = "Expected to arrive between 01-15-2026 and 01-22-2026"โ”‚
โ”‚ โ€ข _MTO_DELIVERY_WINDOW = "7" โ”‚
โ”‚ โ€ข _SHIPPING_SPEED = "7-8 weeks" โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ”‚
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ PLATFORM CHECKOUT EXTENSION โ”‚
โ”‚ โ”‚
โ”‚ On buyer journey step change โ†’ updatePromisedByDate() โ”‚
โ”‚ โ”‚
โ”‚ Reads: โ”‚
โ”‚ โ€ข _MTO_DELIVERY_WINDOW (defaults to 7 if not present) โ”‚
โ”‚ โ”‚
โ”‚ Updates (recalculates from checkout time): โ”‚
โ”‚ โ€ข _PROMISED_BY_DATE = "Expected to arrive between 01-20-2026 and 01-27-2026"โ”‚
โ”‚ โ”‚
โ”‚ Unchanged: โ”‚
โ”‚ โ€ข _MADE-TO-ORDER (still has cart-time dates) โ”‚
โ”‚ โ€ข _PRODUCTION_DAYS โ”‚
โ”‚ โ€ข _MTO_DELIVERY_WINDOW โ”‚
โ”‚ โ€ข _SHIPPING_SPEED โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ”‚
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ THEME TRACKING PAGE โ”‚
โ”‚ โ”‚
โ”‚ V1 (tracking--order.js): โ”‚
โ”‚ โ€ข Reads shipping_lines code only (e.g., "8 weeks") โ”‚
โ”‚ โ€ข Does NOT use _PROMISED_BY_DATE or _MADE-TO-ORDER โ”‚
โ”‚ โ”‚
โ”‚ V2 (tracking--order-v2.js): โ”‚
โ”‚ โ€ข Parses dates from _PROMISED_BY_DATE value (checkout-time dates) โ”‚
โ”‚ โ€ข Falls back to _PRODUCTION_DAYS calculation โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Important Notesโ€‹

Date Format Consistencyโ€‹

All systems now use the same message format:

SourceFormat Example
Hydrogen (cart)"Expected to arrive between 01-15-2026 and 01-22-2026"
Platform (checkout)"Expected to arrive between 01-20-2026 and 01-27-2026"

Delivery Window Calculationโ€‹

All systems now use the same configurable delivery window from _MTO_DELIVERY_WINDOW.

Hydrogen Storefrontโ€‹

// app/lib/cart.ts

// Window comes from product or site settings (e.g., 7, 14, etc.)
const mtoDeliveryWindow = resolveMtoDeliveryWindow(
Number(productProperties?.mtoDeliveryWindow),
siteSettings.dualSale.mtoDeliveryWindow
);

// Sets _MTO_DELIVERY_WINDOW attribute for downstream use
attributes.push({ key: '_MTO_DELIVERY_WINDOW', value: mtoDeliveryWindow.toString() });

Platform Checkout Extensionโ€‹

// platform/extensions/item-attributes/src/Checkout.jsx

// Reads window from line item attributes (set by hydrogen-storefront)
const deliveryWindow = getMtoDeliveryWindow(item.attributes);
// Defaults to 7 if _MTO_DELIVERY_WINDOW not present

const message = buildPromisedByDateMessage(productionDays, deliveryWindow);

Comparison Tableโ€‹

SystemWindow SourceLower Bound FormulaUpper Bound Formula
Hydrogen StorefrontproductProperties.mtoDeliveryWindow or siteSettings.dualSale.mtoDeliveryWindownow + productionDays - mtoDeliveryWindownow + productionDays
Platform Checkout_MTO_DELIVERY_WINDOW attribute (default: 7)now + productionDays - deliveryWindownow + productionDays
Theme cart.utils.jsHardcoded 7now + productionDays - 7now + productionDays

Production Days Source Differencesโ€‹

SystemPrimary SourceFallback
HydrogenproductProperties.productionDayssiteSettings.dualSale.standardProductionDays
Platformcustom.production_days metafielddelayed_delivery metaobject (mto or matte-satin handle)
Themecustom.production_days metafieldwindow.daysDelayedMto (56) or window.daysDelayedMatteSatin (63)

Hydrogen Storefrontโ€‹

  • app/lib/cart.ts - prepareMTOProperties() function
  • app/lib/constants.ts - Attribute key constants
  • app/components/ProductOptions/utils.tsx - calculatePromisedByDate() helper

Platform Repositoryโ€‹

  • extensions/item-attributes/src/Checkout.jsx - Checkout extension that updates _PROMISED_BY_DATE
  • extensions/item-attributes/src/utils.js - Helpers: getMtoDeliveryWindow(), buildPromisedByDateMessage()

Theme Repositoryโ€‹

  • assets/tracking--order.js - V1 tracking page (uses shipping line code)
  • assets/tracking--order-v2.js - V2 tracking page (parses _PROMISED_BY_DATE dates)
  • assets/cart.utils.js - Legacy cart utilities (Liquid theme)