When I first started helping a friend manage their Shopify store, I quickly realized that the hardest part of e-commerce isn't getting the initial sale. It's what happens after the customer clicks "Buy."
I was struggling with a massive influx of "Where is my order?" (WISMO) emails. Every afternoon, I would spend nearly two hours manually checking carrier websites, copying tracking numbers, and pasting them into reply templates. It was tedious, highly repetitive, and completely unscalable. I was acting as a human bridge between the carrier's system and the customer's inbox.
So I decided to build something.
The Hidden Cost of the Post-Purchase Black Hole
The problem with WISMO tickets isn't just the time they consume. It's the context in which they happen. The post-purchase phase is when customer excitement is at its peak. But if they have to hunt for shipping information or wait a full day for a support reply, that excitement quickly turns into anxiety.
Ignoring this friction has a tangible cost. Every manual WISMO reply is a drain on productivity. For a solo developer or a small team, those two hours a day add up to ten hours a week—time that could be spent on product development, marketing, or just taking a well-deserved break. Furthermore, sending customers off to a generic, unbranded carrier website breaks the immersion of your store. You lose the opportunity to keep them engaged with your brand during a critical touchpoint.
Automating this process wasn't just about saving time; it was about shifting from reactive firefighting to proactive customer engagement.
Automating the Tracking Experience
My goal was to completely remove myself from the tracking update loop. I needed a system that automatically captured fulfillment data from Shopify and presented it to the customer in a clean, branded widget right on the order status page.
The first step was handling the backend automation. Shopify provides webhooks for order fulfillments, which is the perfect trigger for updating tracking statuses. However, handling webhooks securely is critical. You have to verify the HMAC signature to ensure the request is actually coming from Shopify.
Here is the Node.js webhook handler I built to automatically ingest fulfillment data:
const crypto = require('crypto');
function verifyShopifyWebhook(rawBody, hmacHeader, secret) {
const hash = crypto
.createHmac('sha256', secret)
.update(rawBody, 'utf8')
.digest('base64');
return hash === hmacHeader;
}
// Handle fulfillment update webhook
app.post('/webhooks/orders/fulfilled',
express.raw({ type: 'application/json' }),
async (req, res) => {
const verified = verifyShopifyWebhook(
req.body,
req.headers['x-shopify-hmac-sha256'],
process.env.SHOPIFY_WEBHOOK_SECRET
);
if (!verified) return res.status(401).send('Invalid');
const order = JSON.parse(req.body.toString('utf8'));
// Store fulfillment data for tracking lookup
await db.fulfillments.upsert({
orderId: order.id,
trackingNumber: order.fulfillments[0]?.tracking_number,
carrier: order.fulfillments[0]?.tracking_company,
status: 'shipped',
});
res.status(200).send('OK');
}
);
By verifying the HMAC and upserting the tracking number and carrier into our database, the backend is fully automated. The moment a label is created in Shopify, our system knows about it.
The second step was getting this data to the frontend without bloating the page load time. Shopify's App Embed blocks are great for this, but injecting third-party scripts requires care to avoid blocking the main thread.
Here is the Liquid and JavaScript snippet used to render the widget on the order status page:
{% comment %}
Renders shipment tracking widget on order status pages
{% endcomment %}
<div id="parcelglance-widget"
data-order-id="{{ order.id }}"
data-order-number="{{ order.name }}"
data-store-name="{{ shop.name }}"
style="min-height: 200px;">
</div>
<script>
(function() {
const script = document.createElement('script');
script.src = 'https://cdn.parcelglance.com/widget.js';
script.async = true;
script.onload = function() {
Parcelglance.init({
orderId: document.getElementById('parcelglance-widget').dataset.orderId,
orderNumber: document.getElementById('parcelglance-widget').dataset.orderNumber,
storeName: document.getElementById('parcelglance-widget').dataset.storeName,
container: 'parcelglance-widget',
});
};
document.head.appendChild(script);
})();
</script>
This approach uses Liquid to securely pass the order data as attributes. The JavaScript then dynamically creates the script tag and sets it to async. This ensures the tracking widget loads in the background, fetching real-time tracking status from major carriers without delaying the rest of the page rendering.
Practical Results and Lessons Learned
The productivity gains were immediate. By automating the webhook ingestion and the frontend widget rendering, the manual WISMO workflow was completely eliminated. What used to take two hours of daily copy-pasting was now handled entirely by code. Support tickets related to shipping status dropped significantly, as customers could simply visit their order status page to see real-time updates.
What surprised me most was the engagement metric. I expected customers to just glance at the tracking number and leave. Instead, because the widget was customizable and matched the store's theme, customers actually spent time on the post-purchase page. It turned a purely utilitarian check into a branded experience.
If I were to do it over, I would change how I initially handled webhook retries. In my first iteration, I built a complex custom queue for failed webhook deliveries. I later realized that relying on Shopify's built-in retry mechanism and keeping my endpoint idempotent was much more practical and required less maintenance.
Moving Forward
Building this automation solved my immediate problem, but I realized many other Shopify merchants were dealing with the exact same WISMO headaches. I ended up packaging the core functionality—the branded tracking page, real-time carrier integration, and easy App Embed installation—into a dedicated tool.
If you are looking to automate your post-purchase experience and reduce those tedious support tickets, you can check out the free Shipment Tracking Widget at parcelglance.com. It is designed to be a simple, effective way to keep your customers in the loop without adding to your workload.
Full disclosure: I'm the developer of Parcelglance. I built this because I needed it myself.
Top comments (0)