DEV Community

seller-mind
seller-mind

Posted on

How I Built a Custom Shopify Tracking Widget to Crush WISMO

When I first started helping a few friends manage their Shopify stores, I assumed the hardest part of the business would be driving initial traffic and getting those first sales. I was completely wrong. The real operational nightmare started after the checkout.

My inbox—and theirs—would inevitably flood with variations of the same question: "Where is my order?"

I found myself acting as a manual routing hub. A customer would email asking for an update, and I’d have to log into the Shopify admin, copy the tracking number, open a new tab, navigate to the carrier’s website, paste the number, check the status, and then draft a reply. It was a terrible use of time, and honestly, it was a frustrating experience for the customer who just wanted a quick update.

I realized that relying on generic carrier pages was breaking the brand experience. Customers expect a seamless, Amazon-level post-purchase journey, but most small stores just send a confirmation email and leave them in the dark until the package arrives.

So I decided to build something.

The WISMO Problem and the Technical Gap

The "Where Is My Order" (WISMO) problem is a silent killer for small e-commerce brands. It’s not just about the annoyance of support tickets; it’s about trust. When a customer can’t easily find their tracking information, they assume the worst. They assume the store is a scam, or that their package is lost.

From a technical perspective, solving this on Shopify presents a unique challenge. You need to fetch real-time tracking data from various carriers, process it, and then display it in a way that matches the merchant's store theme.

Historically, adding a tracking widget meant editing the store’s theme.liquid file or injecting custom code into the order status page. This is a nightmare for developers and merchants alike. If the theme updates, the custom code breaks. If the merchant switches themes, the tracking disappears. It’s brittle and difficult to maintain at scale.

I needed an architecture that was completely decoupled from the theme, secure, and easy for merchants to install without touching a single line of code.

Building the Widget with App Embed Blocks

The breakthrough came with Shopify’s Online Store 2.0 architecture, specifically App Embed blocks. This allowed me to inject UI elements directly into the storefront via the theme editor, keeping the core logic isolated in my app while letting the merchant control the placement.

Here is a look at the core App Embed block I use to render the tracking widget on the order status pages. It bridges the gap between Shopify’s Liquid templating engine and our frontend JavaScript widget.

{% 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>
Enter fullscreen mode Exit fullscreen mode

Let’s break down the technical decisions here:

  1. Data Passing via Liquid: We use Liquid variables ({{ order.id }}, {{ order.name }}) to pass the necessary context directly into the DOM as data-* attributes. This avoids making an extra API call just to figure out which order we are looking at.
  2. Non-Blocking Script Injection: Instead of using a standard <script src="..."></script> tag in the head, we dynamically create the script element and set script.async = true. This ensures that loading our tracking widget never blocks the main thread or delays the rendering of the critical order status page.
  3. Stateless Initialization: The Parcelglance.init() function takes the container ID and the data attributes. The widget then handles its own state management, fetching the real-time tracking status from our backend and rendering the UI.

On the backend, we rely heavily on Shopify webhooks to keep our database in sync. When an order is fulfilled, Shopify fires a webhook. We verify the HMAC signature to ensure the request is legitimate, parse the fulfillment data (like the tracking number and carrier), and upsert it into our database. This means when the frontend widget initializes, the tracking data is already pre-fetched and ready to serve instantly, keeping the UI snappy.

Practical Results and Lessons Learned

Moving to the App Embed block architecture was a game-changer. What used to take hours of debugging broken theme code now takes a merchant about three clicks in the Shopify theme editor. They just toggle the embed on, and the branded tracking page appears.

What surprised me the most wasn't the technical execution, but the psychological impact on the buyers. Just having a clean, branded tracking page that matches the store's theme significantly reduced anxiety. For example, stores using the widget often see a noticeable drop in WISMO support tickets in the first week, simply because the customer doesn't have to go digging for their tracking number.

If I were to rebuild this today, I’d probably optimize the initial payload size of the widget script even further. While it’s already async, shaving off a few more kilobytes by lazy-loading the carrier logo assets would make the initial render even faster on mobile connections.

Try It Yourself

If you're running a Shopify store and are tired of manually answering "Where is my order?" emails, or if you're a developer looking to see how App Embed blocks work in practice, I've packaged this solution into a free tool.

You can check out the free Shipment Tracking Widget at parcelglance.com. It’s designed to be a simple, effective way to improve the post-purchase experience and keep your customers in the loop without adding to your support queue.


Full disclosure: I'm the developer of Parcelglance. I built this because I needed it myself.

Top comments (0)