Storefronts and marketplaces
Let the carrier update the order, not a person
The tracking number exists in three places — the carrier's system, a spreadsheet, and eventually the order — and someone moves it between them by hand. That copying is where "where is my parcel" tickets come from: not from late parcels, but from orders whose status stopped updating two days ago. Carrier status arrives as a lookup rather than a push, so the shape here is a poll, and the one step that matters is writing it back where the customer can see it.
- Triggers
- Two
- Runs
- Every 30 minutes
- Stack
- 4 tools
- Durable execution
- Not required
The flow
The top track captures the tracking number once, at fulfilment. The bottom track asks the carrier on a timer and writes back only when the status actually moved.
An order is fulfilled
Shopify Admin API
Record the tracking number
n8n · Make
Write the shipment row
Sheets · Airtable
Every 30 minutes
n8n 排程
Ask the carrier
DHL Shipment Tracking API
Status changed?
n8n IF
Write it back on the order
Shopify Admin API
Leave the row as is
—
Step by step
- 01
An order is fulfilled
Shopify Admin APIA webhook fires when the shipment is created. Treat it as the moment a tracking number came into existence, not as the last word on it — the number is sometimes corrected an hour later.
- 02
Record the tracking number
n8n · MakeStore the number with the carrier it belongs to and the order it came from. The carrier matters as much as the number: the same string means nothing without knowing whose system to ask.
- 03
Write the shipment row
Sheets · AirtableOne row per shipment, holding the last status seen and when it was seen. That second column is what stops the flow re-notifying a customer about a status they already received.
- 04
Every 30 minutes
n8n 排程Poll rather than wait, because carrier status is a lookup. Pace it against your carrier's quota rather than against how fresh you would like the data to be — the quota is the real constraint, and it is smaller than most people assume.
- 05
Ask the carrier
DHL Shipment Tracking APIQuery only shipments that are still in transit. Delivered ones never change again, and a poll that keeps asking about them spends a quota you will want on the parcels that are still moving.
- 06
Status changed?
n8n IFCompare against the last status in the row, not against a fixed list. A carrier that reports the same scan twice must not read as movement, or the customer gets the same email twice and trusts the next one less.
- 07
Write it back on the order
Shopify Admin APIUpdate the tracking information on the fulfilment, and decide deliberately whether this particular change is worth an email. Every intermediate scan is not; dispatch, out for delivery, and a failed attempt are.
What the platform will not allow
Two ceilings sit on this flow: how often a carrier will answer, and what the storefront does with the answer once you write it back.
fulfillmentTrackingInfoUpdate "Updates tracking information for a fulfillment, including the carrier name, tracking numbers, and tracking URLs." With notifyCustomer enabled, "customers receive shipping update emails with tracking details and receive notifications about future updates to the fulfillment" — and if the field is left unspecified, no notification is sent. Whether the customer hears about a scan is a decision the flow has to make on purpose.
Shopify Admin GraphQL API — fulfillmentTrackingInfoUpdateSupplying a supported carrier name in the company field makes Shopify generate the tracking URL for you. Single-package shipments use number and url; multi-package shipments use the numbers and urls arrays — so a split shipment is one call carrying several numbers, not several calls.
Shopify Admin GraphQL API — fulfillmentTrackingInfoUpdateThe initial DHL tracking allocation is "250 calls per day, with a maximum of 1 call every 5 seconds", which the documentation itself describes as "intended for initial development and is not suitable for production use"; over the limit the API returns 429. A half-hourly poll across a few hundred open parcels exceeds that before it becomes a real workflow.
DHL API — Shipment Tracking (Unified)Carriers batch differently, and the batch size sets your poll design. FedEx documents that you should "Limit the number of tracking numbers in a single-track request to 30" — so a thousand open shipments is at least thirty-four calls per pass, per carrier.
FedEx Developer Portal — Track API
When this is not worth building
Three cases where the upkeep costs more than the copying.
Your carrier already writes status back into the storefront. If the integration exists, this flow is a second writer on the same field, and the two will eventually disagree in front of a customer.
You ship a handful of parcels a day with one carrier. Pasting a tracking number takes seconds; a polling loop with a quota, a carrier mapping, and a notification rule does not.
Nobody has decided which statuses deserve a message. Without that decision the flow defaults to notifying on every scan, and customers learn to ignore your shipping emails — which costs more than never having sent them.