Guides
How to Add Package Tracking to Shopify and WooCommerce Without a Full Platform
Add order tracking to Shopify and WooCommerce with a small API integration instead of a full post-purchase platform: get the tracking number, call a tracking API, and render a status page.
You can add package tracking to a Shopify or WooCommerce store three ways: install a full post-purchase platform, integrate each carrier's official API by hand, or call one universal tracking API and render the result yourself. The first is fast but heavy; the second is precise but explodes in maintenance; the third is usually the right size for a small team.
This guide walks through the third option: pulling the tracking number out of the order, looking it up with a tracking API, and rendering a status page the customer can actually use.
Get the tracking number out of the order
Before you can track anything, you need the tracking number and, ideally, the carrier. On Shopify, fulfillments carry a tracking number and carrier. On WooCommerce, the number usually lives in order metadata set by your shipping plugin — WooCommerce Shipping, ShipStation, and others each write their own fields.
Read that field once per order and store it. If your shipping plugin does not expose it cleanly, that is the first thing to fix: without a reliable tracking number, no tracking API can help you.
Call a universal tracking API
Instead of one integration per carrier, send the tracking number to a single endpoint and get back normalized status and dated events. For common formats the carrier is detected automatically; for ambiguous numeric formats you supply the carrier code.
A free tier matters here: 1,000 lookups a month is enough to prototype and run a small store before you pay anything.
A minimal integration
This is the whole integration: one POST with the order's tracking number. The response carries a normalized carrier code, a status, and a dated event list you can render directly.
Store the result against the order so the status page reads from your database rather than hitting the API on every page view.
const response = await fetch("https://api.traceapi.dev/v1/track", {
method: "POST",
headers: {
Authorization: "Bearer " + process.env.TRACE_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({ tracking_number: order.trackingNumber }),
});
const tracking = await response.json();
console.log(tracking.carrier.code, tracking.status, tracking.events);Render a status page, not a raw log
Map the normalized status to a small set of visual states — pending, in transit, out for delivery, delivered, exception — and show the latest event plus a short timeline. Customers do not need every scan; they need to know where the parcel is and what happens next.
Keep the raw events behind a details toggle for support. This is the difference between a page that answers WISMO questions and one that generates them.
Keep it fresh with webhooks
Polling every shipment on a timer works for tiny stores but gets expensive and slow at scale. A tracking API with signed webhooks pushes tracking.updated and tracking.delivered events when something actually changes.
Verify the signature, deduplicate on the event id, and update your stored status. That gives you near-real-time delivery notifications without polling every shipment around the clock.
What to avoid
Avoid per-carrier integrations until a specific carrier justifies it. Avoid treating a cached or unavailable lookup as a confirmed status. And avoid showing carrier jargon to customers — translate it to plain language.
The goal is a status page a customer reads once and understands, fed by an API you barely think about.
Useful next steps
Build tracking into your product
Create a Trace account, generate an API key, and test package tracking from the dashboard.