Applying a Loyalty Reward Through Shopify Checkout WebMCP: What Worked and What Broke

Direct Answer We applied a $10 Stabile reward through Shopify's browser checkout tools and verified that the completed test order settled its 300-point hold. Before that worked, we found a lifecycle mismatch: Stabile still offered a reward whose Shopify discount had expired. This was one demo-store test with synthetic loyalty data and a human paying with a Shopify test card. Here is what worked, what stopped us first, and what remains unfinished.
Why test the browser checkout?
Our October 17 server-side checkout test ended with a question: could a reward also work through Shopify's browser-based interface?
Shopify provides two interfaces to its Universal Commerce Protocol (UCP) checkout capability. Checkout MCP serves agents or clients running on a server. Checkout WebMCP exposes tools in the buyer's browser. They share a checkout model, but each path needs its own verification.
Shopify's September 28 announcement described browser-based agents reading and updating checkout, with the buyer authorizing the order, as reported by PYMNTS. We tested the browser tools directly, using Chrome 155's developer console on our demo store.
The first stop: a reward Shopify had already expired
The October 17 test had left an unused $10 reward for 300 points as a negative control. We had manually deactivated its Shopify discount code. The Stabile record still marked the reward active, and its 300-point hold remained in place.
On October 18, the issuance flow selected that reward for reuse. A read-only inspection confirmed the mismatch: Shopify reported the discount as expired, while Stabile still considered the reward active. We stopped before applying the code or attempting an order.
We added a check against Shopify before offering an existing reward for reuse. The discount must be active and below its usage limit. If its status cannot be verified, the checkout bridge stops before reuse or new issuance. This checks the discount's current status; checkout must still establish whether it applies to the particular cart.
After that change, the flow excluded the expired code and offered the $10-for-300-points tier. A human typed yes, a fresh reward was issued, and we continued.
This fixed reward reuse selection. Releasing points held by abandoned or deactivated rewards remains a separate lifecycle task. The lookup did not modify the old reward, its hold, or the points balance.
The run, step by step
This was a Stabile MCP integration using Shopify UCP checkout, on a demo store with synthetic data. The browser exposed get_checkout, update_checkout, complete_checkout, and navigate_to_storefront. Our client used the first two and never called complete_checkout.
| Step | What happened | Result |
|---|---|---|
| Start checkout | Clean Incognito guest checkout with one catalog item; no contact, payment, or code entered. | $29.99 item |
| Check existing rewards | Shopify status lookup excluded the expired discount. | Old reward not reused |
| Confirm and issue | A person typed yes before a new reward was issued. | $10 reward; 300 points reserved |
| Apply the code | One update_checkout call supplied the code in checkout.discounts.codes. | Same code in Shopify's applied-discounts list; $19.99 before shipping |
| Review and pay | A human reviewed Shopify's page and used a test card. | $8 Standard shipping; $27.99 total |
| Verify settlement | The completed order's code matched the issued reward by hash. | One 300-point hold settled |
The final total was $29.99 − $10.00 + $8.00 = $27.99. We checked both the applied-discounts result and the completed order, rather than treating a returned code or a lower total alone as proof.
The synthetic loyalty account's balance moved from 1,350 to 1,050 points. Held points moved from 600 to 300: the new order settled one hold, while the abandoned reward's hold remained.
The loyalty account and checkout contact were separate synthetic identities in this fixture. That setup isolated reward settlement from earning on the new order; it did not test a real shopper's identity-linking journey.
Several recoverable checkout_error messages appeared. We recorded them without assigning causes we had not established.
What the browser path taught us
Check the destination's state before offering a reward. A loyalty record marked active can disagree with the corresponding Shopify discount. Checking Shopify caught that mismatch before we offered the old code again. A later checkout response is still needed to verify application.
Use the checkout page's own context. An initial inspection through an automation tool returned nothing for document.modelContext. The native developer console exposed the tools. The inspection context explained the difference; the empty result did not establish that WebMCP was absent.
Read the checkout again after an uncertain update. Our handoff allowed one coded attempt and stopped on uncertainty. Shopify documents update_checkout as replacing checkout state using PUT semantics. An update can also report a timeout while still taking effect. Read the current checkout before deciding whether another update is needed, and build any next request from that state.
Keep reward issuance and purchase approval separate. Human confirmation gated issuance. The raw reward code stayed out of printed output and saved evidence. A person then reviewed checkout and completed payment on Shopify's page.
The limits of this result
The completed test covers one demo store, one reward type, Chrome 155, and a founder-operated console. We did not test a named shopping agent applying the reward, autonomous payment, other stores, or Shop Pay. It provides no evidence of conversion lift or merchant revenue.
No live signed webhook replay was run, and we did not configure Web Bot Auth signing. Shopify recommends signing browser requests to identify the agent; this successful demo does not establish how other clients will be treated by bot detection.
The result establishes code application and the observed settlement for this fixture. UCP already has a loyalty extension, but this experiment used checkout discount fields. It did not validate a complete UCP loyalty-account integration or a general shopper authorization flow.
What we investigate next
Our next investigation is how a shopping agent can discover a buyer's existing rewards through an agent wallet, with the buyer's permission. A reward needs to be available while the shopper compares stores, as well as usable at checkout.
We are starting with Stripe Link's agent wallet to establish whether it offers a supported integration path for a loyalty provider. Wallet-based reward discovery has not been demonstrated by this checkout test. Any implementation will depend on what that investigation establishes.
Technical notes
- Chrome version: In our Chrome 155 run, string arguments failed before dispatch; object arguments worked. Shopify documents the transition from JSON strings to objects. Clients need to account for their browser version.
- Clipboard handoff: Before issuing a reward, we verified a harmless write/read/clear round trip. It required checkout-page focus and handling Chrome's clipboard permission prompt. The clipboard was cleared after the run.
- Checkout state: The adapter preserved the current optional
shop_pay_sign_upvalue. It did not choose a new signup preference. A different browser profile had a remembered shopper, so we used a clean Incognito session. - Console transfer: Multiline script entry produced syntax errors during setup. Serializing the helper into one expression resolved that transfer problem.
Frequently Asked Questions
Did a real shopper or merchant take part?
No. We used our demo store, synthetic loyalty data, and a Shopify test card.
Did an AI agent complete the purchase?
No. We operated the checkout tools from the browser's developer console. A human paid, and our client never called complete_checkout.
Did this test validate a complete UCP loyalty integration?
No. It verified applying an externally issued reward through checkout discount fields and settling the corresponding Stabile hold. It did not validate loyalty-account discovery or linking through UCP.
Can I try this on my store?
The test used custom tooling in a private demo environment. It is not a packaged checkout feature. A merchant implementation needs its own verification of reward rules, buyer authorization, checkout behavior, and settlement.
Get started
Interested in testing rewards through agent checkout?
Discuss your store's reward workflow and a suitable test.
Make sure your loyalty program can come along when an agent does the shopping. Stabile helps you publish your reward terms for AI shopping assistants, email customers the rewards they earn, and check your store's AI readiness for free. Free to install. Install from the Shopify App Store →
For the earlier result, read our server-side Checkout MCP test. For the broader problem, see where a reward code needs to work when an agent shops.
Sources
The test results come from our October 17 and 18, 2026 project records and observations of the demo checkout, issued reward, completed test order, and synthetic loyalty balance. They have not been independently verified outside this project. The cover is an illustration of the experiment, not a checkout screenshot.