When I first launched my Shopify store, I genuinely thought the hardest part was getting that initial sale. I was wrong. The real headache started about two weeks after launch, when my support inbox suddenly flooded with "Where is my order?" (WISMO) emails.
At first, I handled it manually. I’d log into the carrier’s site, copy the tracking link, and paste it into an email reply. It was a terrible use of time. So, I tried to be smart and hardcode a custom tracking display directly into my theme’s order status files. It worked for a bit, until I updated my theme and completely broke the tracking layout.
After spending a weekend untangling Liquid logic and comparing a few different tracking approaches, I realized there had to be a cleaner way. So I decided to build something.
The Problem with Post-Purchase Tracking
The WISMO problem is a silent margin-killer for e-commerce stores. It’s not just about the annoyance of reading the same email ten times a day; it’s about the operational cost. If you are spending your own valuable development time answering logistics questions, you are losing money.
When looking for a solution, I compared three main architectural approaches for handling post-purchase tracking on Shopify:
- Manual Handling: Obviously unsustainable. It doesn't scale and leads to slow response times, which frustrates customers.
- Deep Theme Edits: Hardcoding tracking logic into your theme files. The trade-off here is full control, but the cost is high maintainability. Every time you switch themes or update your current theme, you risk breaking the tracking page. Plus, querying carrier APIs directly from Liquid is a bad practice that slows down page rendering.
- Heavy Third-Party Iframes: Many existing apps inject a massive, unbranded iframe into the order status page. While easy to install, they often look disjointed from your store's design and can negatively impact your Core Web Vitals due to heavy external scripts.
I needed an approach that offered the branding control of a theme edit, but the maintainability of a lightweight app.
The Technical Approach: App Embed Blocks
This led me to Shopify’s App Embed blocks. App Embeds allow developers to inject UI components into a store without modifying the core theme files. The merchant simply toggles the block on in the theme editor.
The main trade-off with App Embeds is that they rely on the merchant remembering to enable the block in the theme editor. However, the architectural benefits far outweigh this minor friction. It completely decouples the tracking UI from the theme, meaning theme updates will never break the tracking widget.
To make this work, I had to rethink how data flows from Shopify to the frontend. Instead of doing heavy lifting in Liquid, the theme passes basic order identifiers to a lightweight JavaScript widget, which then fetches the real-time tracking status.
Here is the App Embed block implementation I use to render the tracking 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> Let's break down the technical decisions here. First, notice the min-height: 200px on the container. When I first built this, I didn't include a height constraint, which caused a massive Cumulative Layout Shift (CLS) when the script loaded and injected the tracking UI. Setting a minimum height reserves the space and keeps the page stable.
Second, the script is loaded asynchronously. We don't want the tracking widget to block the main thread or delay the rendering of the primary order confirmation details. The onload callback ensures we only initialize the widget once the external script is fully parsed and ready.
On the backend, the architecture relies on Shopify webhooks rather than Liquid API calls. When an order is fulfilled, Shopify sends a webhook to our backend. We verify the HMAC signature to ensure the request is legitimate, parse the fulfillment data, and store the tracking number and carrier in our database. When the frontend widget initializes, it uses the order ID to fetch this pre-processed data, resulting in a near-instant load time for the customer.
Practical Results and Takeaways
Switching to the App Embed architecture completely changed how I manage the post-purchase experience. What worked really well was the separation of concerns. I can now update the tracking widget's CSS, add new carrier integrations, or tweak the JavaScript logic without ever touching the merchant's theme files.
What surprised me was the performance gain. By moving the tracking logic out of Liquid and into an async JavaScript widget, the order status page renders significantly faster. The initial paint happens immediately with the basic order details, and the tracking widget populates a fraction of a second later.
If I were to do it again, I would have implemented a skeleton loader from day one. While the min-height trick solved the layout shift, a subtle pulsing skeleton while the script loads would make the transition feel even more polished. It's a small UX detail, but in the post-purchase experience, every little bit of reassurance counts.
Wrapping Up
Building this architecture solved my WISMO problem and gave me a lot of insight into how Shopify stores handle post-purchase logistics. I ended up packaging this exact App Embed approach into a free tool called Parcelglance.
If you are a Shopify merchant tired of dealing with WISMO tickets, or a developer looking to see how App Embeds can be used for tracking, you can check out the free Shipment Tracking Widget at parcelglance.com. It’s designed to be lightweight, fully branded to your store, and easy to install via the theme editor.
Full disclosure: I'm the developer of Parcelglance. I built this because I needed it myself.
