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:
- Hydrogen Storefront - Sets initial properties when adding to cart
- Platform Checkout Extension - Recalculates and updates properties at checkout
- Theme Tracking Page - Reads properties to display arrival estimates
Line Item Propertiesโ
_PRODUCTION_DAYSโ
Raw number of production days for the item.
| Attribute | Value |
|---|---|
| Set by | Hydrogen Storefront (cart) |
| Updated at checkout | No |
| Format | Integer string (e.g., "56") |
| Used by tracking page | Yes (fallback calculation) |
Source Priority:
- Product's
custom.production_daysmetafield - Site settings
dualSale.standardProductionDaysdefault
_MADE-TO-ORDERโ
Human-readable message with embedded delivery dates.
| Attribute | Value |
|---|---|
| Set by | Hydrogen Storefront (cart) |
| Updated at checkout | No |
| Format | "Expected to arrive between MM-dd-yyyy and MM-dd-yyyy" |
| Used by tracking page | No (contains stale cart-time dates) |
_PROMISED_BY_DATEโ
Human-readable message with embedded delivery dates, recalculated at checkout.
| Attribute | Value |
|---|---|
| Set by | Hydrogen Storefront (cart) |
| Updated at checkout | Yes (recalculated) |
| Format | "Expected to arrive between MM-DD-YYYY and MM-DD-YYYY" |
| Used by tracking page | Yes (V2 parses dates from value) |
_MTO_DELIVERY_WINDOWโ
The delivery window range in days (difference between upper and lower delivery estimates).
| Attribute | Value |
|---|---|
| Set by | Hydrogen Storefront (cart) |
| Updated at checkout | No |
| Format | Integer string (e.g., "7") |
| Used by tracking page | No |
_SHIPPING_SPEEDโ
Human-readable production timeline for display.
| Attribute | Value |
|---|---|
| Set by | Hydrogen Storefront (cart) |
| Updated at checkout | No |
| Format | "7-8 weeks" or "8 weeks" |
| Used by tracking page | No |
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_WINDOWfrom line item attributes (defaults to 7 if not present) - Updates only
_PROMISED_BY_DATE, leaves_MADE-TO-ORDERunchanged - 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:
- Parse date range from
_PROMISED_BY_DATEvalue (checkout-time dates) - Parse single date from
_PROMISED_BY_DATEvalue - 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:
| Source | Format 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โ
| System | Window Source | Lower Bound Formula | Upper Bound Formula |
|---|---|---|---|
| Hydrogen Storefront | productProperties.mtoDeliveryWindow or siteSettings.dualSale.mtoDeliveryWindow | now + productionDays - mtoDeliveryWindow | now + productionDays |
| Platform Checkout | _MTO_DELIVERY_WINDOW attribute (default: 7) | now + productionDays - deliveryWindow | now + productionDays |
| Theme cart.utils.js | Hardcoded 7 | now + productionDays - 7 | now + productionDays |
Production Days Source Differencesโ
| System | Primary Source | Fallback |
|---|---|---|
| Hydrogen | productProperties.productionDays | siteSettings.dualSale.standardProductionDays |
| Platform | custom.production_days metafield | delayed_delivery metaobject (mto or matte-satin handle) |
| Theme | custom.production_days metafield | window.daysDelayedMto (56) or window.daysDelayedMatteSatin (63) |
Related Documentationโ
- Business Rules - Overall tracking page business logic
- Production Timeline - MTO production timeline phases
- UI & Display - Tracking page display logic
Related Filesโ
Hydrogen Storefrontโ
app/lib/cart.ts-prepareMTOProperties()functionapp/lib/constants.ts- Attribute key constantsapp/components/ProductOptions/utils.tsx-calculatePromisedByDate()helper
Platform Repositoryโ
extensions/item-attributes/src/Checkout.jsx- Checkout extension that updates_PROMISED_BY_DATEextensions/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_DATEdates)assets/cart.utils.js- Legacy cart utilities (Liquid theme)