DEV Community

seller-mind
seller-mind

Posted on

How I Built a Beginner-Friendly Shopify Tracking Widget from Scratch

When I first started helping a friend manage their Shopify store, I thought the hardest part would be getting the first sale. I was completely wrong. The real nightmare started after the sale. My phone wouldn't stop buzzing with customer emails asking the exact same question: "Where is my order?"

In the e-commerce world, this is known as WISMO. We were spending hours every week just copy-pasting tracking numbers from carrier websites into emails. It was exhausting, repetitive, and felt incredibly unprofessional to our buyers. I knew there had to be a better way to handle this without forcing customers to navigate clunky third-party carrier sites. So I decided to build something.

The Hidden Cost of the Post-Purchase Experience

In e-commerce, the "post-purchase experience" is everything that happens after a customer clicks 'Buy'. Think of it like ordering a pizza. If the restaurant takes your money and then goes silent for 45 minutes, you start worrying. Did they forget? Did they burn it? E-commerce is the exact same way. When a customer buys something, they enter a waiting period. If you don't give them a clear, easy way to check on their package, they will email you.

These WISMO tickets act as a hidden tax on your time and support resources. But beyond just the annoyance, a clunky post-purchase experience makes customers feel like they bought from a faceless dropshipper. They want to see your brand, your colors, and your logo while they wait. Solving this means keeping the customer in your ecosystem, building trust, and reducing support overhead.

A Beginner-Friendly Technical Approach

I wanted to create a branded tracking widget that store owners could easily add to their order status pages. The goal was to make it feel like a native part of their store theme, without requiring them to write a single line of code.

Shopify has a feature called "App Embed blocks" which is perfect for this. It allows apps to inject code into a merchant's theme seamlessly. Let's look at how the actual widget injection works. Here is a simplified version of the Liquid and JavaScript code we 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>
Enter fullscreen mode Exit fullscreen mode

Let's break this down for beginners. First, the HTML div acts as our empty container. We pass in crucial data using data- attributes. {{ order.id }} and {{ order.name }} are Shopify Liquid variables. If you're new to Liquid, it's just Shopify's templating language. These variables automatically pull the current order's details directly from the database and inject them into the HTML before the page even loads.

Next is the JavaScript part. We dynamically create a script tag to load our widget logic from a CDN. Using script.async = true is a crucial detail; it ensures our tracking script loads in the background and doesn't block the rest of the page from rendering. This keeps the store feeling fast and responsive.

Once the script loads, we call Parcelglance.init() and pass in the order details we grabbed from the HTML container. This tells our backend exactly which order's tracking data to fetch and display inside that specific div.

One major design decision was how to handle the visual styling. Instead of forcing a rigid, generic template, we built the widget to read the store's existing CSS variables. This way, the tracking page automatically adapts to the store's fonts, colors, and button styles without the merchant having to configure a complex design editor.

Practical Results and Lessons Learned

A notable surprise during this process was how much merchants valued the simplicity of the App Embed block. In the past, installing tracking apps meant digging into theme code and hoping you didn't accidentally break your checkout page. Being able to just toggle a switch in the Shopify theme editor was a huge help for non-technical store owners.

What worked really well was the dynamic styling approach. Seeing a tracking page that closely matched a store's unique branding made the whole experience feel much more premium and cohesive.

If I were to do it again, I would spend more time on the mobile layout initially. I assumed most people would check tracking on a desktop computer, but early feedback showed the vast majority were checking on their phones while on the go. I had to quickly refactor the CSS to be much more mobile-first, ensuring the tracking timeline and maps scaled down properly on smaller screens.

Bringing It to Your Store

If you're building a Shopify store and want to improve your post-purchase experience without writing custom Liquid code, I've packaged this tracking widget into a free tool. You can easily add the branded Shipment Tracking Widget to your store via the theme editor to help reduce those WISMO tickets and keep your customers engaged with a seamless, real-time tracking experience.

You can check it out and add it to your store at parcelglance.com.


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

Top comments (0)