A shipment notification that omits tracking information is worse than no notification at all: it tells the customer the package has left the warehouse but gives them nothing to act on. Without tracking data in the email, the customer must contact support or log in to the account page to find the tracking number — and if they can't find it, the next call is to their credit card company. This is an iso-25010:2011 reliability gap: the email was sent but failed to deliver the information that makes it useful. The tracking number and carrier captured at the 'shipped' transition (see tracking-info) must flow directly into the email template.
High because a shipment email without tracking data gives customers no ability to monitor delivery, turning every 'where is my order?' contact into a preventable support ticket.
Wire the shipment notification into lib/orders/shipping.ts so the tracking data captured at ship time is passed directly to the email in lib/email/order-emails.ts.
// lib/email/order-emails.ts
export async function sendShipmentNotificationEmail(params: {
to: string
orderNumber: string
trackingNumber: string
carrier: string
trackingUrl: string
}) {
await emailService.send({
to: params.to,
subject: `Your order ${params.orderNumber} has shipped`,
template: 'shipment-notification',
data: params,
})
}
// In markOrderShipped() (lib/orders/shipping.ts):
await sendShipmentNotificationEmail({
to: order.user.email,
orderNumber: order.id,
trackingNumber,
carrier,
trackingUrl: `https://yoursite.com/orders/${order.id}/track`,
})
ID: ecommerce-order-management.notifications.shipment-email
Severity: high
What to look for: Find the code path that marks orders as shipped. This is typically an admin action or an API call from a fulfillment service. Count the email service calls in this path. Look for an email call that includes tracking information — enumerate which tracking fields are passed to the email template (at least 2 of: order number, tracking number, carrier name, tracking URL). Quote the exact email function name called. Check whether the tracking information captured during the shipped transition (see tracking-info check) is actually passed into the email or whether hardcoded placeholders are used.
Pass criteria: When an order transitions to shipped status, at least 1 email notification is sent to the customer that includes at least 2 tracking data fields (tracking number and carrier, or tracking number and tracking URL). The email trigger exists alongside the status update in the same handler or is queued reliably. A shipment email that sends no tracking data (just "your order shipped") does not count as pass.
Fail criteria: No email is sent when an order is marked shipped (0 email calls in the shipped handler). Or an email is sent but includes 0 tracking fields, making it an ineffective notification. Or the email service call uses a hardcoded placeholder tracking number rather than the actual tracking data.
Skip (N/A) when: The project delegates shipment tracking and notifications entirely to a third-party shipping platform (e.g., ShipStation, EasyPost) that sends its own carrier notifications, and the project does not send a separate notification. No shipped status transition exists in application code.
Detail on fail: "The admin 'Mark as Shipped' handler at src/app/api/admin/orders/[id]/ship/route.ts updates order status and tracking number but makes 0 email calls. Customers have no way to know their order has shipped unless they check their account."
Remediation: Add shipment notification alongside the shipped transition in lib/email/order-emails.ts and wire it from the shipping handler:
// lib/email/order-emails.ts
export async function sendShipmentNotificationEmail(params: {
to: string
orderNumber: string
trackingNumber: string
carrier: string
trackingUrl: string
}) {
await emailService.send({
to: params.to,
subject: `Your order ${params.orderNumber} has shipped`,
template: 'shipment-notification',
data: params,
})
}
// In markOrderShipped() (lib/orders/shipping.ts):
await sendShipmentNotificationEmail({
to: order.user.email,
orderNumber: order.id,
trackingNumber,
carrier,
trackingUrl: `https://yoursite.com/orders/${order.id}/track`,
})