Leveraging systems thinking to improve the Shop Promise buyer experience
I led a project to bring Shop Promise into the customer post-purchase experience across Shopify merchants’ online stores. What began as a simple graphical UI “fix” quickly morphed into an ambitious systems-wide project that involved multiple parts of the platform, resulted in the creation of a new design pattern, and netted upwards of 43,000 impressions for a burgeoning brand within a month of shipping.
The problem
Shop Promise developed as a program to offer Shopify merchants with the proven trust-building and conversion-boosting benefits delivery predictions had earned for brands like Amazon. Thanks to Prime, delivery dates became table stakes in e-commerce, but Shopify’s merchants were missing out.
The program went into general access in early 2024, serving to highlight merchants who are exceptional shippers with estimated delivery dates backed by a purple badge and delivery guarantee. The dates and badge appear across product pages and checkouts for orders a predictive model determines will arrive in 5 days or less. If the model has low confidence an order will arrive in that timeframe, a delivery date won’t be shown. If an order backed by Shop Promise arrives late, the customer can claim $5 Shop Cash as recompense for the broken promise.
As Promise proliferated across merchant storefronts, it became clear there was a significant gap in the customer experience: the badge and dates were completely missing from key post-purchase surfaces, specifically the Order Details Page where customers could track the status of their order once it was in transit. This meant customers who saw the Promise badge guaranteeing a specific on-time delivery in checkout never saw it again as their order was en route—a scenario that could erode the buyer’s trust in the merchant and the merchant’s trust in Shopify.
Holy sunset, Batman!
The Classic Order Status Page. I’d later realize the pattern the team shipped onto this page was wrong, having assigned meaning to the wrong object.
As I started working through the problem, the first thing I had to do was ground myself in the reality that we were racing against the clock.
At the time I was preparing to take on work for the Order Details Page, or the ODP, Shopify was preparing to sunset the ODP's predecessor, the Classic Order Status Page, or the OSP. The Order Details Page was replacing the Order Status Page, but had also been partially rolled out. So, both the OSP and the ODP were live in production, showing up on online stores, at the same time. Some merchants were using the OSP. Others were already using the new ODP.
That means teams at Shopify building features in the customer post-purchase experience had to design for both the OSP and the ODP until the full migration would take place a year later.
Shop Promise was no exception. But, by the time I took on the ODP project, the team had already integrated the Promise badge onto the OSP. The way I figured it, we'd adapt the same pattern solution onto the ODP since the OSP already established precedent. This seemed like a relatively simple copy/paste situation.
Initial explorations
My initial explorations centered on how we could display the Promise badge on the ODP, replete with own unique form factors and constraints. But there was a lot more to consider than just the placement of the badge:
Scalability: Whatever solution I landed on for Promise needed to scale to Buy with Prime, our partner and the first of our third-party branded promise providers we onboarded to the Promise program
Relevance: I needed to design for every order status and demonstrate parity across each of those use cases. Thing is, our Shipping Platform team was preparing to introduce a delayed status to the fulfillment schema that would appear on the OSP and, eventually, the ODP. We wanted to protect the Promise brand, so there was no appetite for associating the badge with a delay. So, what happens to the badge in that use case, which isn't an edge case? Does it disappear? Does it move? How would I avoid repeating the same disappearing badge problem I was actually trying to solve?
Alignment: We needed cross-organizational alignment. Through the entire process, I kept in close contact with Design managers, product designers, engineers, and content designers across three teams: mine, of course, but also Checkout, which owned the old Order Status Page, and Customer Accounts, which owned the new Order Details Page. Whatever design decision I landed on needed alignment from three product teams, all with their own stakes and perspectives on the ODP.
I tried several different directions: putting the badge next to the top-line delivery date header; placing it beneath tracking information to represent Promise underwriting the delivery; utilizing the order status timeline text to reiterate details of the delivery guarantee and the option to claim Shop Cash if the order arrives late.
Clarifying the real problem
Just when I drove general alignment on a possible path forward—placing the Promise badge beneath order tracking information—my product manager asked a single question that changed everything: "what about carrier dates?"
That’s when it hit me: I had been solving the wrong problem. Yes, it was true that Promise needed to be represented on the ODP, but there was a crucial piece of logic I failed to factor in: a first party delivery date generated by Shopify the platform is NOT the same as a delivery date generated by a shipping carrier that's actually delivering the order.
Promise dates ≠ carrier dates: Adding a badge on the ODP would never work because the dates on the oDP aren’t the same dates on merchants’ product pages or in checkout.
Promise dates are static; carrier dates are dynamic: Dates that appear in pre-purchase and post-purchase experiences represent two different states of the customer journey. Pre-purchase dates that Shop Promise generates are delivery predictions intended to motivate customers to check out. When they see that date in checkout, it's the platform promising to deliver that order by that date, absent any other factors.
However, shipping is a complex logistical process beset by so many factors outside the platform's control. Once an order is in the hands of a carrier, the carrier provides the most up-to-date, accurate, real-time information re: the status of that order. They relay that information in an expected delivery date that's passed along to Shopify through an API, so it appears in the tracking experience. But that date is fluid. And depending on a number of variables—weather, staffing, oil spills—that date might change several times during the delivery process. It's not a promise.These dates may and often do conflict: delivery promises in checkout can and often do conflict with delivery dates from the carrier. But both would appear on the ODP, and only one would actually be accurate in a given moment.
Shop Promise as a feature created a bit of a delivery date dilemma because now two different types of dates coexist in the same context. Plus, pairing Promise with a carrier-generated date visually signified that carriers were making a delivery promise, which they did not want Shopify doing for them. Adding a Prime badge next to "carrier dates" on the ODP is fine because Amazon's got its own extensive fulfillment network and has pioneered two-day delivery. But the vast majority of Shopify merchants aren't Amazon, and their carriers are not incentivized to deliver faster simply because they made the customer a promise.
Identifying what to solve
The problems I was actually solving for became a lot more clear and complicated. I needed to:
Decouple Promise from carrier dates; they weren't the same and shouldn't appear together
Clearly articulate what the different dates mean, taking into account that delivery promises will never change, but carrier dates may change often
And remember that platform-generated dates and carrier-generated dates will and often do conflict. I needed to reconcile that disparity for the customer.
Codifying concepts and principles
It became clear that this was an information hierarchy and concept definition, not a graphical one. I stepped away from the UI and developed a super-simple, low-fi, and low-frills object map to visualize the different types coexisting on the OSP and ODP. I used that to codify guiding principles for how these objects should or shouldn’t interact.
A new iterative path
I started iterating again, keeping things really simple as I kept our product requirements in mind. We didn’t want only rectify the date disparity, but also include education about Shop Promise in the experience; create an easy ingress to Shop Cash claiming; and create a pattern that would scale for Amazon and other would-be third-party promise providers.
I decided to focus on my most formidable design tool to solve this informational problem: words. I decided to keep Promise the concept contained within the same order information card, but visually separated from the other shipping and delivery elements outside of Promise’s purview. This was the beginning of homing in on the right design, but it was still too clunky. It didn’t pass the elegance test.
Landing the pattern
After more iteration that included heavy collaboration with my cross-functional partners, I developed the pattern that solved the problem. I created a simple statement that reinforced to the customer that their delivery was guaranteed by Shop Promise. I added an info icon that would expand into a modal upon click on web and tap on mobile.
Sharpening the details
The modal included general details about Shop Promise while also restating the original delivery promise the customer saw at checkout. That way, it never truly disappears but does get deprioritized in the post-purchase experience in favor of the carrier date at the top of the order information card.
For customers eligible to claim Shop Cash because of a late order, I designed a state in which the original delivery promise does appear at the same surface-layer of the carrier date, but the statement changes to say that the item was delivered after the original promise date.
My design partner helped me polish the modals while I sketched out this pattern across various order statuses and use cases to stress-test it. It worked and because the content was constructed as "Delivery guaranteed by {insert promise provider logo}, it could scale to any future third-party provider that may want to utilize this text in post-purchase experiences displayed by the platform. I also documented a content framework that provided the foundation for the tech design
The outcome
Because the primary goal was to raise awareness and build trust for Shop Promise among customers, we primarily tracked impressions as clicks into the modal. Within the first month of this pattern shipping, we measured upwards of 43,000 of them.
Similarly, we instrumented clicks for the Shop Cash claim link and measured about 1,600 of those.
And while this project wasn't devoted to increasing Shop Cash redemptions, we can attribute the 2% increase in claim rate to this work. Shop Cash claiming is an important signal for potential repurchasing behavior. This work created a launchpad for opportunities the team explored to increase the claim rate and motivate customers with late Promise orders to spend again in the Shop app.