<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Almin Zolotic</title>
    <description>The latest articles on DEV Community by Almin Zolotic (@zologic).</description>
    <link>https://dev.to/zologic</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3790384%2Fc55f6bcf-6195-4a20-a695-27480157be6e.jpg</url>
      <title>DEV Community: Almin Zolotic</title>
      <link>https://dev.to/zologic</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/zologic"/>
    <language>en</language>
    <item>
      <title>From Booking to Beyond: Making Autonomous Travel Servicing Work in Practice</title>
      <dc:creator>Almin Zolotic</dc:creator>
      <pubDate>Tue, 09 Jun 2026 22:10:28 +0000</pubDate>
      <link>https://dev.to/zologic/from-booking-to-beyond-making-autonomous-travel-servicing-work-in-practice-119h</link>
      <guid>https://dev.to/zologic/from-booking-to-beyond-making-autonomous-travel-servicing-work-in-practice-119h</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;This is part of an ongoing series on building &lt;a href="https://ucp.travel" rel="noopener noreferrer"&gt;ucp.travel&lt;/a&gt; — an agentic travel stack that lets AI agents search, book, change, and cancel flights autonomously. Built by Almin Zolotic at &lt;a href="https://zologic.nl" rel="noopener noreferrer"&gt;Zologic&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Last time I wrote about getting an AI agent to autonomously book a flight: search, revalidate, pay, confirm. That was the exciting part.&lt;/p&gt;

&lt;p&gt;This week was the less glamorous, but arguably more important, part: what happens &lt;em&gt;after&lt;/em&gt; the booking.&lt;/p&gt;

&lt;p&gt;Anyone who has built anything in travel knows the booking is only the beginning. The real complexity shows up afterward. The traveler wants to change their flight. The airline changes it for them. The traveler wants to cancel. Dates shift, prices reprice, confirmation windows expire. A real travel platform has to handle all of this without falling apart — and without making the traveler feel like they are operating blind.&lt;/p&gt;

&lt;p&gt;That is what we spent the week building.&lt;/p&gt;




&lt;h2&gt;
  
  
  The three moments that matter after a booking
&lt;/h2&gt;

&lt;p&gt;There are really three post-booking scenarios that define whether a travel platform feels like a product or a prototype.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Voluntary cancellation&lt;/strong&gt; — the traveler decides to cancel and needs to understand the consequence before committing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Airline-initiated change&lt;/strong&gt; — the carrier reschedules or changes the trip, and the platform has to reflect that clearly instead of pretending the booking is still unchanged.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Voluntary change&lt;/strong&gt; — the traveler wants a different flight, and the system has to guide them through a preview, a confirmation step, and any additional payment required, without ambiguity about what is final and what is not.&lt;/p&gt;

&lt;p&gt;All three are multi-step flows. None should happen in a single call. And none should complete without the traveler knowing exactly what they are confirming.&lt;/p&gt;




&lt;h2&gt;
  
  
  Making irreversible actions feel safe
&lt;/h2&gt;

&lt;p&gt;The principle we kept coming back to was simple: anything irreversible should be preceded by a preview.&lt;/p&gt;

&lt;p&gt;The traveler should see what will happen, have a chance to pause, and only then confirm. If the preview expires before they act, the system should catch that and ask them to start again — rather than proceeding with stale information.&lt;/p&gt;

&lt;p&gt;That sounds obvious, but implementing it correctly takes real discipline. There are a surprising number of places where a system can skip the preview, auto-confirm, or fail to communicate that a confirmation window has closed. We closed those gaps and added guards at multiple layers, so that if one check is bypassed, the next one still catches it.&lt;/p&gt;

&lt;p&gt;The same principle applies to how the system talks about fare conditions. A fare being labelled &lt;em&gt;refundable&lt;/em&gt; is a policy statement — not a guarantee that the system can execute a refund right now. We changed the platform to check live booking state before promising that change or cancellation is available. If a booking cannot be serviced through the current interface, the traveler now hears that clearly instead of getting a confusing error after the fact.&lt;/p&gt;




&lt;h2&gt;
  
  
  Airline-initiated changes were the hardest part
&lt;/h2&gt;

&lt;p&gt;The scenario that took the most care was airline-initiated change.&lt;/p&gt;

&lt;p&gt;When an airline changes a trip, the platform receives an event and has to decide what to do. The wrong answer is to handle it silently. Airline changes can involve new flight times, a different aircraft, or sometimes different routing — none of which the traveler has agreed to.&lt;/p&gt;

&lt;p&gt;The right answer is to surface the change clearly, show what was originally booked versus what is now being proposed, and ask the traveler to review before anything is accepted or rejected.&lt;/p&gt;

&lt;p&gt;We built that escalation path properly, made sure the platform re-fetches fresh booking state before presenting the change, and validated the full flow end to end against real provider behavior.&lt;/p&gt;




&lt;h2&gt;
  
  
  Settlement honesty matters too
&lt;/h2&gt;

&lt;p&gt;One smaller change that mattered a lot was how cancellation refunds are communicated.&lt;/p&gt;

&lt;p&gt;In many travel products, cancellation language implies the traveler will simply get money back to their card. In our model, the commercial reality is different — settlement happens through the platform's billing arrangement with operators.&lt;/p&gt;

&lt;p&gt;Those are not the same thing, and conflating them would be misleading.&lt;/p&gt;

&lt;p&gt;So the platform now communicates cancellation in terms of service status: the booking is cancelled, and any applicable credit or adjustment is handled through the billing arrangement. It no longer implies a direct traveler refund where that is not actually the right commercial interpretation.&lt;/p&gt;

&lt;p&gt;Small wording change. Matters a lot for trust.&lt;/p&gt;




&lt;h2&gt;
  
  
  How we know it actually works
&lt;/h2&gt;

&lt;p&gt;The thing I am most satisfied with this week is not just the feature list.&lt;/p&gt;

&lt;p&gt;It is that we did not stop at &lt;em&gt;"it works locally."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We exercised the full booking lifecycle — booking, changing, cancelling, and handling airline-driven changes — against live provider responses, step by step, until we had confirmed outcomes for every scenario.&lt;/p&gt;

&lt;p&gt;That shifted the project from &lt;em&gt;"we think this works"&lt;/em&gt; to &lt;em&gt;"we know these core flows work."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There is a meaningful difference between code that looks correct and a system that has been proven to behave correctly under real conditions. This week we crossed that line for the servicing layer.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is next
&lt;/h2&gt;

&lt;p&gt;The immediate next track is operator tooling: giving the people running travel programs visibility into booking settlement, billing data, and the ability to manage their travelers' bookings with confidence.&lt;/p&gt;

&lt;p&gt;The AI agent layer is now in a healthy place.&lt;/p&gt;

&lt;p&gt;Now the work is turning that foundation into a full product for the humans operating on top of it.&lt;/p&gt;

&lt;p&gt;More soon.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Almin Zolotic is the founder of &lt;a href="https://zologic.nl" rel="noopener noreferrer"&gt;Zologic&lt;/a&gt; and building &lt;a href="https://ucp.travel" rel="noopener noreferrer"&gt;ucp.travel&lt;/a&gt; — an agentic travel stack that lets AI agents search, book, change, and cancel flights autonomously. Follow the build here on dev.to.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>travel</category>
      <category>buildinpublic</category>
    </item>
    <item>
      <title>We Just Completed a Live AI-Agent Flight Booking End to End</title>
      <dc:creator>Almin Zolotic</dc:creator>
      <pubDate>Mon, 01 Jun 2026 14:25:44 +0000</pubDate>
      <link>https://dev.to/zologic/we-just-completed-a-live-ai-agent-flight-booking-end-to-end-3b2</link>
      <guid>https://dev.to/zologic/we-just-completed-a-live-ai-agent-flight-booking-end-to-end-3b2</guid>
      <description>&lt;p&gt;&lt;strong&gt;An AI agent received a natural language instruction, searched for flights, selected an offer, passed authorization checks, and created a confirmed booking — autonomously, without human input after initial setup.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Today that went from architecture spec to production reality.&lt;/p&gt;




&lt;h2&gt;
  
  
  What actually happened
&lt;/h2&gt;

&lt;p&gt;At 15:33 CET, on UCPPlayground, we ran the following prompt against our live stack:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Use search_flights for ZAG to AMS tomorrow. Then immediately call complete_checkout on the first direct offer. Do not explain first."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Two tool calls. Eight seconds.&lt;/p&gt;

&lt;p&gt;The agent searched. The agent booked. A confirmed booking reference came back. We opened the travel provider dashboard and the order was sitting there — confirmed, with a PNR, an e-ticket, passenger details, everything.&lt;/p&gt;

&lt;p&gt;No human touched the booking flow after the initial traveler setup.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why this is harder than it sounds
&lt;/h2&gt;

&lt;p&gt;Anyone can wrap a travel search API in an MCP tool and call it "AI travel booking." That part is easy.&lt;/p&gt;

&lt;p&gt;The hard part is everything that happens between &lt;em&gt;search&lt;/em&gt; and &lt;em&gt;confirmed booking&lt;/em&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Offers expire.&lt;/strong&gt; Flight fares are perishable inventory. An offer returned from search may be gone in 15–30 minutes. No LLM checks this unprompted — it will try to book an expired offer and get a rejection it doesn't know how to recover from.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prices change silently.&lt;/strong&gt; A fare can reprice between the moment the agent sees it and the moment it tries to book. Without a revalidation gate, the agent books at the new price without telling anyone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bookings can partially confirm.&lt;/strong&gt; A travel provider can return an async response — booking accepted, outcome pending. An agent that doesn't understand this state will retry, and retrying a booking call risks a double charge.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Identity and authorization matter.&lt;/strong&gt; Who is this booking for? What are they allowed to spend? What cabin class? Are they direct-only? Without a mandate layer, an agent has no constraints. It will spend whatever inventory is available.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Document requirements gate certain routes.&lt;/strong&gt; Some routes require passport details to be validated before an order is created. An agent that doesn't check this wastes a booking attempt and confuses the traveler.&lt;/p&gt;

&lt;p&gt;These aren't edge cases. Every one of them will happen in production. None of them are solved by the travel API or the LLM — they have to be solved by the layer in between.&lt;/p&gt;

&lt;p&gt;That's what we built.&lt;/p&gt;




&lt;h2&gt;
  
  
  The stack
&lt;/h2&gt;

&lt;p&gt;We built &lt;strong&gt;&lt;a href="https://ucp.travel" rel="noopener noreferrer"&gt;UCP Travel&lt;/a&gt;&lt;/strong&gt; — a travel transaction layer that sits between AI agents and travel inventory.&lt;/p&gt;

&lt;p&gt;It implements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;UCP&lt;/strong&gt; (Universal Commerce Protocol) — the open standard for agentic commerce, including the full checkout lifecycle&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP&lt;/strong&gt; (Model Context Protocol) — so any MCP-compatible agent can discover and call our tools&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AP2&lt;/strong&gt; (Agent Payments Protocol) — cryptographically signed traveler mandates that enforce spending limits, cabin class ceilings, and booking constraints before any transaction
The traveler sets up once: connects their AI assistant via OAuth, signs a mandate defining their booking constraints, stores their travel preferences. After that, every booking is autonomous within those constraints.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our capability declarations are public at &lt;code&gt;ucp.travel/.well-known/ucp&lt;/code&gt; and verified by &lt;a href="https://ucpchecker.com/status/ucp.travel" rel="noopener noreferrer"&gt;UCPChecker&lt;/a&gt; — currently the only verified implementation of &lt;code&gt;travel.ucp.mandate&lt;/code&gt; in the world.&lt;/p&gt;

&lt;p&gt;UCPPlayground now recognizes ucp.travel as the reference pattern for travel-as-shopping — the &lt;code&gt;travel.ucp.*&lt;/code&gt; namespace layered over &lt;code&gt;dev.ucp.shopping&lt;/code&gt; is the model the ecosystem is converging on.&lt;/p&gt;




&lt;h2&gt;
  
  
  The UCPPlayground integration
&lt;/h2&gt;

&lt;p&gt;The booking today happened through &lt;strong&gt;UCPPlayground&lt;/strong&gt; — a live testing environment for the UCP ecosystem built by Ben Fisher. It connects real AI models to real UCP endpoints and runs end-to-end agent sessions.&lt;/p&gt;

&lt;p&gt;Gemini 2.5 Flash connected to our MCP endpoint, discovered three tools (&lt;code&gt;search_flights&lt;/code&gt;, &lt;code&gt;complete_checkout&lt;/code&gt;, &lt;code&gt;get_booking&lt;/code&gt;), and completed the booking in 3 turns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Turn 1: search_flights(origin: ZAG, destination: AMS, departure_date: 2026-06-02, max_connections: 0)
Turn 2: complete_checkout(offer_id: off_..., checkout_id: chk_live_1)
Turn 3: [confirmed — PNR returned]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Outcome: &lt;code&gt;purchase_completed&lt;/code&gt;. PNR confirmed in the provider dashboard.&lt;/p&gt;




&lt;h2&gt;
  
  
  What "traveler setup once" actually means
&lt;/h2&gt;

&lt;p&gt;The autonomous booking only works because we solved the identity problem first.&lt;/p&gt;

&lt;p&gt;During onboarding, a traveler:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Creates a profile with travel documents and preferences&lt;/li&gt;
&lt;li&gt;Signs an AP2 Intent Mandate — their authorized booking constraints, cryptographically signed&lt;/li&gt;
&lt;li&gt;Links their AI assistant via OAuth 2.0 Authorization Code flow
From that point, every MCP tool call the agent makes carries a bearer token that resolves server-side to the traveler's identity, mandate, and payment profile. The agent never sees raw credentials, card numbers, or passport data. It just calls tools and gets results.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is the architecture that makes autonomous booking trustworthy — not just technically possible.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's live now
&lt;/h2&gt;

&lt;p&gt;The multi-tenant operator platform is running. Operators onboard, configure traveler mandates, and connect AI assistants today. Flight booking is live.&lt;/p&gt;

&lt;p&gt;Expanding next:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stay (hotel) booking alongside flights&lt;/li&gt;
&lt;li&gt;Post-booking servicing — changes, cancellations, ancillaries&lt;/li&gt;
&lt;li&gt;Complete audit trail UI for operators and compliance teams
If you're building an AI travel assistant, a travel management platform, or anything that needs to turn travel intent into confirmed bookings — we'd like to talk.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://ucp.travel" rel="noopener noreferrer"&gt;ucp.travel&lt;/a&gt;&lt;/strong&gt; · &lt;a href="mailto:contact@zologic.nl"&gt;contact@zologic.nl&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built by Zologic — &lt;a href="https://zologic.nl" rel="noopener noreferrer"&gt;zologic.nl&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;UCP spec: &lt;a href="https://ucp.dev" rel="noopener noreferrer"&gt;ucp.dev&lt;/a&gt; · MCP spec: &lt;a href="https://modelcontextprotocol.io" rel="noopener noreferrer"&gt;modelcontextprotocol.io&lt;/a&gt; · AP2: &lt;a href="https://ap2-protocol.org" rel="noopener noreferrer"&gt;ap2-protocol.org&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>travel</category>
      <category>mcp</category>
      <category>ucp</category>
    </item>
    <item>
      <title>30 Days of AI Agents Buying From a Real WooCommerce Store. Here's What the Data Says.</title>
      <dc:creator>Almin Zolotic</dc:creator>
      <pubDate>Tue, 26 May 2026 15:32:55 +0000</pubDate>
      <link>https://dev.to/zologic/30-days-of-ai-agents-buying-from-a-real-woocommerce-store-heres-what-the-data-says-ma0</link>
      <guid>https://dev.to/zologic/30-days-of-ai-agents-buying-from-a-real-woocommerce-store-heres-what-the-data-says-ma0</guid>
      <description>&lt;p&gt;Last week &lt;a class="mentioned-user" href="https://dev.to/benjifisher"&gt;@benjifisher&lt;/a&gt; published a sharp piece on agentic commerce's messy middle — the trust, verification, and liability layer between "found it" and "bought it." His conclusion: the middle is mostly unbuilt.&lt;/p&gt;

&lt;p&gt;We have 30 days of production data that says otherwise. Not a demo. Not a sandbox. A live Dutch perfume store with 40,000 SKUs, real pricing, real tax, real wallet debits. Here is what actually happened.&lt;/p&gt;

&lt;h2&gt;
  
  
  The numbers
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;€1,269&lt;/strong&gt; in AI-driven revenue — last 30 days&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;39 completed orders&lt;/strong&gt; via AI agents&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;€32.54&lt;/strong&gt; average order value per AI transaction&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;76.5% session conversion&lt;/strong&gt; — 39 of 51 agent sessions resulted in a completed order&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;1.5 average calls per session&lt;/strong&gt; — the spec benchmark is 4 (list → create → update → complete)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last number is the one I want to focus on.&lt;/p&gt;

&lt;h2&gt;
  
  
  1.5 calls per session means agents are skipping steps
&lt;/h2&gt;

&lt;p&gt;The UCP spec optimised benchmark is 4 tool calls for a complete purchase: list products, create checkout, update checkout, complete checkout. Our agents are averaging 1.5. &lt;/p&gt;

&lt;p&gt;That is not agents failing — it is agents that have already done discovery in a prior session arriving with intent and going straight to checkout. The &lt;code&gt;/agents.md&lt;/code&gt; instruction layer we shipped two weeks ago is working: agents are reading the operating manual on first visit and not re-reading it on every subsequent transaction.&lt;/p&gt;

&lt;p&gt;The messy middle does not look messy when the protocol is clean and the instructions are explicit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who is actually buying
&lt;/h2&gt;

&lt;p&gt;Eight distinct agents hit the store in 30 days. Here is what the agent table shows:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Agent&lt;/th&gt;
&lt;th&gt;Sessions&lt;/th&gt;
&lt;th&gt;Avg Calls&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;UCP Directory Verifier&lt;/td&gt;
&lt;td&gt;19&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Discovery only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Unknown Agent&lt;/td&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;2.2&lt;/td&gt;
&lt;td&gt;Transacting efficiently&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UCP Checker&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;1.4&lt;/td&gt;
&lt;td&gt;Validation + light transacting&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UCPReady MCP&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;1.2&lt;/td&gt;
&lt;td&gt;Internal testing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UCP Playground&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;+1 above benchmark&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Clean&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ucptools.dev&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;At target&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Generic Bot&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;At target&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The most interesting row is Unknown Agent — 13 sessions, 2.2 avg calls, at or below target. An agent we cannot identify by name is transacting against the store efficiently and repeatedly. It found the &lt;code&gt;/.well-known/ucp&lt;/code&gt; manifest, parsed the capability declarations, and is completing purchases without any integration work on our side.&lt;/p&gt;

&lt;p&gt;That is the protocol working exactly as designed.&lt;/p&gt;

&lt;p&gt;UCP Playground is the only agent above benchmark at 5 calls — that is Ben's testing environment running full end-to-end validation sessions including the identity linking flow. Expected noise, not a problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the messy middle actually looked like
&lt;/h2&gt;

&lt;p&gt;Building to this point was not clean. The first fully autonomous purchase — WooCommerce order #82251 on March 25 — took 24 hours of debugging across two people. The failures were specific:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Idempotency key formatting.&lt;/strong&gt; Claude kept sending &lt;code&gt;meta&lt;/code&gt; as a stringified JSON object instead of a proper nested object. Fixed at the orchestrator level by auto-injecting the key shape.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wallet instrument ID vs handler name.&lt;/strong&gt; The store's validator accepted &lt;code&gt;com.terrawallet.store_credit&lt;/code&gt; (the handler name) but rejected &lt;code&gt;terrawallet-1&lt;/code&gt; (the instrument ID). Two different identifiers, one lookup path, one silent failure mode.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stale OAuth sessions.&lt;/strong&gt; Merchant-side token revocation was not being detected. Agents were holding expired Bearer tokens and getting 401s with no clear recovery path. Fixed by adding token validation on connect and auto-clearing on 401.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MCP endpoint override.&lt;/strong&gt; Our Shopify storefront probe was overriding the manifest endpoint. OAuth tokens were stored against &lt;code&gt;/api/mcp&lt;/code&gt; but MCP calls were going to &lt;code&gt;/wp-json/ucpready/v1/mcp&lt;/code&gt;. One endpoint mismatch, zero successful completions until found.&lt;/p&gt;

&lt;p&gt;Each of these was a real failure that blocked real purchases. The protocol did not hide them — the session data captured every one. Observability is what made them fixable.&lt;/p&gt;

&lt;h2&gt;
  
  
  What 76.5% conversion means in context
&lt;/h2&gt;

&lt;p&gt;Human checkout conversion on e-commerce averages 2-4%. Mobile is lower. Even high-performing stores rarely exceed 5% on cold traffic.&lt;/p&gt;

&lt;p&gt;76.5% is not comparable to human checkout conversion — agent sessions are intentional by definition, not browsing. But it does tell you something about friction. An agent that reaches &lt;code&gt;create_checkout&lt;/code&gt; on a well-implemented UCP endpoint completes the purchase 76.5% of the time. The failures are mostly discovery sessions (UCP Directory Verifier, UCP Checker) that never intended to purchase.&lt;/p&gt;

&lt;p&gt;Strip out the pure discovery sessions and the completion rate is higher.&lt;/p&gt;

&lt;h2&gt;
  
  
  The small retailer readiness tax — revisited
&lt;/h2&gt;

&lt;p&gt;Paul do Forno at Deloitte posted last week that smaller retailers face a "hidden agentic readiness tax" — perfect catalog data as table stakes, deep system access creating data leakage risk.&lt;/p&gt;

&lt;p&gt;The data above is from a small Dutch retailer. Not a platform. Not an enterprise. A WooCommerce store. The tax is real — it took months of development to get here — but the output is 39 AI-driven orders and €1,269 in revenue in 30 days that would not have existed otherwise.&lt;/p&gt;

&lt;p&gt;The readiness tax is a one-time cost. The revenue is recurring.&lt;/p&gt;

&lt;h2&gt;
  
  
  What comes next
&lt;/h2&gt;

&lt;p&gt;The 13 Unknown Agent sessions are the most interesting data point we have right now. An unidentified agent found this store, parsed the protocol, and is transacting repeatedly. We do not know where it came from. That is the network effect of an open protocol — you do not have to be listed anywhere specific. You publish a conformant &lt;code&gt;/.well-known/ucp&lt;/code&gt; manifest and agents find you.&lt;/p&gt;

&lt;p&gt;The next milestone is identifying that agent and understanding its mandate scope. If it is running AP2 autonomous purchasing without an explicit buyer confirmation step, the audit trail is the only thing standing between "it worked" and "it bought the wrong thing." That is the observability layer Ben is right about — not a theoretical need, a live operational requirement.&lt;/p&gt;

&lt;p&gt;The middle is not unbuilt. It is early, it is messy to get right, and it generates real revenue when you do.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;UCPReady is the WooCommerce plugin behind this data. The AI Agent Analytics dashboard is a Pro feature. houseofparfum.nl is the live reference store — the manifest is at houseofparfum.nl/.well-known/ucp.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you want to see where your WooCommerce store stands: ucpchecker.com&lt;/em&gt;&lt;/p&gt;

</description>
      <category>woocommerce</category>
      <category>ai</category>
      <category>mcp</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Shopify Just Gave AI Agents an Operating Manual. We Built One for WooCommerce.</title>
      <dc:creator>Almin Zolotic</dc:creator>
      <pubDate>Tue, 26 May 2026 15:28:38 +0000</pubDate>
      <link>https://dev.to/zologic/shopify-just-gave-ai-agents-an-operating-manual-we-built-one-for-woocommerce-25m</link>
      <guid>https://dev.to/zologic/shopify-just-gave-ai-agents-an-operating-manual-we-built-one-for-woocommerce-25m</guid>
      <description>&lt;p&gt;When Shopify shipped &lt;code&gt;@shopify/ucp-cli&lt;/code&gt; last week, most of the coverage focused on the obvious part: AI agents can now browse and buy from Shopify stores using the Universal Commerce Protocol.&lt;/p&gt;

&lt;p&gt;What got less attention was the file bundled inside the package — &lt;code&gt;SKILL.md&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That file is not protocol. It's instructions. It tells AI agents &lt;em&gt;how to behave&lt;/em&gt; when shopping on Shopify: start with discovery, sequence cart before checkout, render totals in the order the merchant provides them, treat escalation as a normal lifecycle step not an error. It encodes operational knowledge that the UCP spec alone doesn't cover.&lt;/p&gt;

&lt;p&gt;Shopify proved something important: &lt;strong&gt;protocol + agent instructions is stronger than protocol alone.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We build UCPReady — a WooCommerce plugin that implements the full UCP stack. And until last week, WooCommerce merchants running it had the protocol layer but not the instruction layer. No file telling agents how to work with their store. No guidance surface beyond &lt;code&gt;/.well-known/ucp&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We shipped that this week.&lt;/p&gt;




&lt;h2&gt;
  
  
  The gap Shopify exposed
&lt;/h2&gt;

&lt;p&gt;UCP standardizes the transport and schema. Every conformant store — Shopify, WooCommerce, BigCommerce, custom — exposes the same protocol surface. That's the point.&lt;/p&gt;

&lt;p&gt;But Benji Fisher at UCP Checker wrote a sharp breakdown of what Shopify's CLI actually does, and one line stuck:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It can buy from any UCP-compliant store on any platform. It can only &lt;em&gt;find&lt;/em&gt; Shopify stores.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The discovery layer defaults to &lt;code&gt;catalog.shopify.com&lt;/code&gt;. The transaction layer is pure, open UCP. Shopify owns the index; the protocol is shared.&lt;/p&gt;

&lt;p&gt;That asymmetry matters. But there's a second asymmetry that's just as real: Shopify agents arrive at a store already knowing how to behave. Non-Shopify agents arrive and have to figure it out from the profile alone.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;SKILL.md&lt;/code&gt; bundled in a CLI is one way to solve that. But it only works for agents that installed that specific CLI. The more durable fix is publishing the operating manual on the merchant's own domain — discoverable by any agent, from any platform, the moment it finds the store.&lt;/p&gt;




&lt;h2&gt;
  
  
  What we shipped: the Agent Guidance Layer
&lt;/h2&gt;

&lt;p&gt;UCPReady now auto-generates two public documents on every merchant site:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;/agents.md&lt;/code&gt;&lt;/strong&gt; — human and agent readable Markdown. Tells any agent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start with &lt;code&gt;/.well-known/ucp&lt;/code&gt;, use the advertised endpoint, never assume &lt;code&gt;/api/ucp/mcp&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;What capabilities this specific merchant supports (cart, checkout, orders, returns, identity linking, embedded checkout)&lt;/li&gt;
&lt;li&gt;How to sequence checkout operations&lt;/li&gt;
&lt;li&gt;What payment handlers are available&lt;/li&gt;
&lt;li&gt;When to stop and escalate to the buyer&lt;/li&gt;
&lt;li&gt;Whether return flows include retention/keep-offer decisions (KeepCard integration)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;/llms-full.txt&lt;/code&gt;&lt;/strong&gt; — compact, machine-oriented. Covers protocol version, supported transports (REST, MCP, Embedded), capability inventory, and explicit safe probing guidance.&lt;/p&gt;

&lt;p&gt;Both are generated dynamically from live merchant capabilities. If cart is disabled, the cart section doesn't appear. If KeepCard isn't active, no keep-offer guidance is included. Nothing is hardcoded; nothing claims unsupported behavior.&lt;/p&gt;

&lt;p&gt;Here's what it looks like for a real production store — House of Parfum, currently #1 on ucpchecker.com with a perfect 100/100 score:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# House of Parfum

This merchant uses UCPReady and publishes UCP-compatible shopping
endpoints for AI agents.

## Merchant Profile

- **Store:** House of Parfum
- **Description:** Van iconische parfums tot luxe skincare
- **Discovery:** https://houseofparfum.nl/.well-known/ucp
- **Shop:** https://houseofparfum.nl/shop/

## Start Here

- Discover this merchant from https://houseofparfum.nl/.well-known/ucp
- Use the service endpoint advertised in the profile.
- Do not assume /api/ucp/mcp.
- MCP endpoint: https://houseofparfum.nl/wp-json/ucpready/v1/mcp
- REST endpoint: https://houseofparfum.nl/wp-json/ucpready/v1

## Supported Capabilities

- Catalog browsing and product lookup
- Cart creation and update
- Checkout creation, update, and completion
- Order lookup
- Return flows
- Identity linking
- Embedded checkout

## Checkout Guidance

- Create checkout first, then update it with buyer, fulfillment,
  and payment data as needed.
- Read payment handlers from the live checkout response.
- If checkout reaches a completed state, use the final order as
  the source of truth for totals and discounts.
- Treat coupon failures as recoverable checkout issues, not as
  silent success.

## Returns Guidance

- This merchant supports return tooling.
- Return flows may include optional retention / keep-offer decisions
  when enabled by merchant integrations.
- Ask the buyer before accepting or declining any keep-offer outcome.

## Payment Handlers

- dev.ucp.delegate_payment
- com.terrawallet.store_credit

## Escalate to the Buyer When

- variant or quantity selection is ambiguous
- identity linking is required
- coupon validation fails
- the merchant response requires approval or additional buyer action
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can hit it live: &lt;a href="https://houseofparfum.nl/agents.md" rel="noopener noreferrer"&gt;houseofparfum.nl/agents.md&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Why this matters more than it might look
&lt;/h2&gt;

&lt;p&gt;When Google announced Universal Cart at I/O 2026, the commerce director described UCP as "a common language that lets agents reach businesses securely and seamlessly." Universal Cart, AI Mode checkout, YouTube Shopping — they all run on it.&lt;/p&gt;

&lt;p&gt;The stores that benefit are the ones agents can actually work with reliably. A broken or ambiguous implementation gets abandoned. A store with a valid manifest, correct capability declarations, and clear operating guidance gets completed transactions.&lt;/p&gt;

&lt;p&gt;Shopify's approach is to bundle instructions in a CLI. That works for Shopify's ecosystem. Our approach is to publish instructions on the merchant's own domain, discoverable by any agent from any platform.&lt;/p&gt;

&lt;p&gt;The instruction layer is not optional anymore. It's part of what makes a store agent-ready.&lt;/p&gt;

&lt;p&gt;That's the WooCommerce answer to what Shopify bundled in their CLI — platform-level agent guidance, open and accessible, not locked to a single discovery surface.&lt;/p&gt;

&lt;p&gt;If you're running WooCommerce and want to see where your store stands: &lt;a href="https://ucpchecker.com" rel="noopener noreferrer"&gt;ucpchecker.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;UCPReady is at &lt;a href="https://zologic.nl/ucpready" rel="noopener noreferrer"&gt;zologic.nl/ucpready&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>woocommerce</category>
      <category>cli</category>
    </item>
    <item>
      <title>Shopify Just Gave AI Agents an Operating Manual. We Built One for WooCommerce.</title>
      <dc:creator>Almin Zolotic</dc:creator>
      <pubDate>Thu, 21 May 2026 22:45:41 +0000</pubDate>
      <link>https://dev.to/zologic/shopify-just-gave-ai-agents-an-operating-manual-we-built-one-for-woocommerce-1p4p</link>
      <guid>https://dev.to/zologic/shopify-just-gave-ai-agents-an-operating-manual-we-built-one-for-woocommerce-1p4p</guid>
      <description>&lt;p&gt;When Shopify shipped &lt;code&gt;@shopify/ucp-cli&lt;/code&gt; last week, most of the coverage focused on the obvious part: AI agents can now browse and buy from Shopify stores using the Universal Commerce Protocol.&lt;/p&gt;

&lt;p&gt;What got less attention was the file bundled inside the package — &lt;code&gt;SKILL.md&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That file is not protocol. It's instructions. It tells AI agents &lt;em&gt;how to behave&lt;/em&gt; when shopping on Shopify: start with discovery, sequence cart before checkout, render totals in the order the merchant provides them, treat escalation as a normal lifecycle step not an error. It encodes operational knowledge that the UCP spec alone doesn't cover.&lt;/p&gt;

&lt;p&gt;Shopify proved something important: &lt;strong&gt;protocol + agent instructions is stronger than protocol alone.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We build UCPReady — a WooCommerce plugin that implements the full UCP stack. And until last week, WooCommerce merchants running it had the protocol layer but not the instruction layer. No file telling agents how to work with their store. No guidance surface beyond &lt;code&gt;/.well-known/ucp&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We shipped that this week.&lt;/p&gt;




&lt;h2&gt;
  
  
  The gap Shopify exposed
&lt;/h2&gt;

&lt;p&gt;UCP standardizes the transport and schema. Every conformant store — Shopify, WooCommerce, BigCommerce, custom — exposes the same protocol surface. That's the point.&lt;/p&gt;

&lt;p&gt;But Benji Fisher at UCP Checker wrote a sharp breakdown of what Shopify's CLI actually does, and one line stuck:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It can buy from any UCP-compliant store on any platform. It can only &lt;em&gt;find&lt;/em&gt; Shopify stores.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The discovery layer defaults to &lt;code&gt;catalog.shopify.com&lt;/code&gt;. The transaction layer is pure, open UCP. Shopify owns the index; the protocol is shared.&lt;/p&gt;

&lt;p&gt;That asymmetry matters. But there's a second asymmetry that's just as real: Shopify agents arrive at a store already knowing how to behave. Non-Shopify agents arrive and have to figure it out from the profile alone.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;SKILL.md&lt;/code&gt; bundled in a CLI is one way to solve that. But it only works for agents that installed that specific CLI. The more durable fix is publishing the operating manual on the merchant's own domain — discoverable by any agent, from any platform, the moment it finds the store.&lt;/p&gt;




&lt;h2&gt;
  
  
  What we shipped: the Agent Guidance Layer
&lt;/h2&gt;

&lt;p&gt;UCPReady now auto-generates two public documents on every merchant site:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;/agents.md&lt;/code&gt;&lt;/strong&gt; — human and agent readable Markdown. Tells any agent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start with &lt;code&gt;/.well-known/ucp&lt;/code&gt;, use the advertised endpoint, never assume &lt;code&gt;/api/ucp/mcp&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;What capabilities this specific merchant supports (cart, checkout, orders, returns, identity linking, embedded checkout)&lt;/li&gt;
&lt;li&gt;How to sequence checkout operations&lt;/li&gt;
&lt;li&gt;What payment handlers are available&lt;/li&gt;
&lt;li&gt;When to stop and escalate to the buyer&lt;/li&gt;
&lt;li&gt;Whether return flows include retention/keep-offer decisions (&lt;a href="https://keepcard.io" rel="noopener noreferrer"&gt;KeepCard integration&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;/llms-full.txt&lt;/code&gt;&lt;/strong&gt; — compact, machine-oriented. Covers protocol version, supported transports (REST, MCP, Embedded), capability inventory, and explicit safe probing guidance.&lt;/p&gt;

&lt;p&gt;Both are generated dynamically from live merchant capabilities. If cart is disabled, the cart section doesn't appear. If &lt;a href="https://keepcard.io" rel="noopener noreferrer"&gt;KeepCard &lt;/a&gt;isn't active, no keep-offer guidance is included. Nothing is hardcoded; nothing claims unsupported behavior.&lt;/p&gt;

&lt;p&gt;Here's what it looks like for a real production store — House of Parfum, currently #1 on ucpchecker.com with a perfect 100/100 score:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# House of Parfum&lt;/span&gt;

This merchant uses UCPReady and publishes UCP-compatible shopping
endpoints for AI agents.

&lt;span class="gu"&gt;## Merchant Profile&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; &lt;span class="gs"&gt;**Store:**&lt;/span&gt; House of Parfum
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Description:**&lt;/span&gt; Van iconische parfums tot luxe skincare
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Discovery:**&lt;/span&gt; https://houseofparfum.nl/.well-known/ucp
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Shop:**&lt;/span&gt; https://houseofparfum.nl/shop/

&lt;span class="gu"&gt;## Start Here&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; Discover this merchant from https://houseofparfum.nl/.well-known/ucp
&lt;span class="p"&gt;-&lt;/span&gt; Use the service endpoint advertised in the profile.
&lt;span class="p"&gt;-&lt;/span&gt; Do not assume /api/ucp/mcp.
&lt;span class="p"&gt;-&lt;/span&gt; MCP endpoint: https://houseofparfum.nl/wp-json/ucpready/v1/mcp
&lt;span class="p"&gt;-&lt;/span&gt; REST endpoint: https://houseofparfum.nl/wp-json/ucpready/v1

&lt;span class="gu"&gt;## Supported Capabilities&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; Catalog browsing and product lookup
&lt;span class="p"&gt;-&lt;/span&gt; Cart creation and update
&lt;span class="p"&gt;-&lt;/span&gt; Checkout creation, update, and completion
&lt;span class="p"&gt;-&lt;/span&gt; Order lookup
&lt;span class="p"&gt;-&lt;/span&gt; Return flows
&lt;span class="p"&gt;-&lt;/span&gt; Identity linking
&lt;span class="p"&gt;-&lt;/span&gt; Embedded checkout

&lt;span class="gu"&gt;## Checkout Guidance&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; Create checkout first, then update it with buyer, fulfillment,
  and payment data as needed.
&lt;span class="p"&gt;-&lt;/span&gt; Read payment handlers from the live checkout response.
&lt;span class="p"&gt;-&lt;/span&gt; If checkout reaches a completed state, use the final order as
  the source of truth for totals and discounts.
&lt;span class="p"&gt;-&lt;/span&gt; Treat coupon failures as recoverable checkout issues, not as
  silent success.

&lt;span class="gu"&gt;## Returns Guidance&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; This merchant supports return tooling.
&lt;span class="p"&gt;-&lt;/span&gt; Return flows may include optional retention / keep-offer decisions
  when enabled by merchant integrations.
&lt;span class="p"&gt;-&lt;/span&gt; Ask the buyer before accepting or declining any keep-offer outcome.

&lt;span class="gu"&gt;## Payment Handlers&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; dev.ucp.delegate_payment
&lt;span class="p"&gt;-&lt;/span&gt; com.terrawallet.store_credit

&lt;span class="gu"&gt;## Escalate to the Buyer When&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; variant or quantity selection is ambiguous
&lt;span class="p"&gt;-&lt;/span&gt; identity linking is required
&lt;span class="p"&gt;-&lt;/span&gt; coupon validation fails
&lt;span class="p"&gt;-&lt;/span&gt; the merchant response requires approval or additional buyer action
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can hit it live: &lt;a href="https://houseofparfum.nl/agents.md" rel="noopener noreferrer"&gt;houseofparfum.nl/agents.md&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Why this matters more than it might look
&lt;/h2&gt;

&lt;p&gt;When Google announced Universal Cart at I/O 2026, the commerce director described UCP as "a common language that lets agents reach businesses securely and seamlessly." Universal Cart, AI Mode checkout, YouTube Shopping — they all run on it.&lt;/p&gt;

&lt;p&gt;The stores that benefit are the ones agents can actually work with reliably. A broken or ambiguous implementation gets abandoned. A store with a valid manifest, correct capability declarations, and clear operating guidance gets completed transactions.&lt;/p&gt;

&lt;p&gt;Shopify's approach is to bundle instructions in a CLI. That works for Shopify's ecosystem. Our approach is to publish instructions on the merchant's own domain, discoverable by any agent from any platform.&lt;/p&gt;

&lt;p&gt;The instruction layer is not optional anymore. It's part of what makes a store agent-ready.&lt;/p&gt;

&lt;p&gt;That's the WooCommerce answer to what Shopify bundled in their CLI — platform-level agent guidance, open and accessible, not locked to a single discovery surface.&lt;/p&gt;

&lt;p&gt;If you're running WooCommerce and want to see where your store stands: &lt;a href="https://ucpchecker.com" rel="noopener noreferrer"&gt;ucpchecker.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;UCPReady is at &lt;a href="https://zologic.nl/ucpready" rel="noopener noreferrer"&gt;zologic.nl/ucpready&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>woocommerce</category>
      <category>cli</category>
    </item>
    <item>
      <title>I Replaced a Returns Portal with Five MCP Tools. Here's What Actually Happened.</title>
      <dc:creator>Almin Zolotic</dc:creator>
      <pubDate>Thu, 30 Apr 2026 20:06:06 +0000</pubDate>
      <link>https://dev.to/zologic/i-replaced-a-returns-portal-with-five-mcp-tools-heres-what-actually-happened-43ii</link>
      <guid>https://dev.to/zologic/i-replaced-a-returns-portal-with-five-mcp-tools-heres-what-actually-happened-43ii</guid>
      <description>&lt;p&gt;A live WooCommerce journey where a model searched products, completed a purchase, and handled a return with keep-offer logic — through UCPReady and KeepCard.io on the Universal Commerce Protocol.&lt;/p&gt;

&lt;p&gt;Most "AI commerce" demos are still just chat layered on top of old flows.&lt;/p&gt;

&lt;p&gt;Tonight we did something different.&lt;/p&gt;

&lt;p&gt;We ran a live WooCommerce journey where a model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;searched products&lt;/li&gt;
&lt;li&gt;helped complete a purchase&lt;/li&gt;
&lt;li&gt;and then handled a return with keep-offer logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not on a mock store. Not with human agents behind the curtain. Not with Claude-specific business logic buried in the backend. And not by building "AI features" into the store itself.&lt;/p&gt;

&lt;p&gt;This ran through &lt;strong&gt;UCPReady&lt;/strong&gt; and &lt;strong&gt;KeepCard.io&lt;/strong&gt; — two products I built — using protocol-native rails so the model could interact with the store as an agent.&lt;/p&gt;




&lt;h2&gt;
  
  
  The transcript in one line
&lt;/h2&gt;

&lt;p&gt;This was the actual lifecycle:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Customer asked for a face cleanser&lt;/li&gt;
&lt;li&gt;Model searched the live WooCommerce catalog&lt;/li&gt;
&lt;li&gt;Customer bought two products&lt;/li&gt;
&lt;li&gt;Checkout ran through UCPReady&lt;/li&gt;
&lt;li&gt;Payment used wallet rails plus browser authorization&lt;/li&gt;
&lt;li&gt;Order completed&lt;/li&gt;
&lt;li&gt;Customer changed their mind about one item&lt;/li&gt;
&lt;li&gt;KeepCard.io verified the order, surfaced the line items, collected the reason, and presented a keep offer&lt;/li&gt;
&lt;li&gt;Customer accepted the offer&lt;/li&gt;
&lt;li&gt;A real discount code was generated&lt;/li&gt;
&lt;li&gt;A real confirmation email was sent&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That is the entire commerce loop in one conversational journey.&lt;/p&gt;




&lt;h2&gt;
  
  
  What actually happened
&lt;/h2&gt;

&lt;p&gt;The session started like a normal shopping flow. The model searched a live WooCommerce store, found products, built a checkout, selected fulfillment, selected payment, and moved through the purchase flow using UCPReady.&lt;/p&gt;

&lt;p&gt;Then, in the same broader system, we tested returns through KeepCard.io.&lt;/p&gt;

&lt;p&gt;The return flow did this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Looked up the order by order number and email&lt;/li&gt;
&lt;li&gt;Checked eligibility&lt;/li&gt;
&lt;li&gt;Collected the return reason&lt;/li&gt;
&lt;li&gt;Evaluated keep-offer logic&lt;/li&gt;
&lt;li&gt;Presented the customer with a keep offer &lt;strong&gt;in chat&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Accepted the offer&lt;/li&gt;
&lt;li&gt;Generated a real discount code&lt;/li&gt;
&lt;li&gt;Sent the confirmation email&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We saw the discount code issued. We saw the email arrive. We saw the KeepCard dashboard record the return session as &lt;strong&gt;Kept&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That is not "AI-assisted support." That is a real agentic commerce lifecycle.&lt;/p&gt;




&lt;h2&gt;
  
  
  A real example from tonight
&lt;/h2&gt;

&lt;p&gt;The customer started with:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I want to buy something to clean my face&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The model searched the live catalog and found:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rilastil Aqua Face Cleanser 200ml — €16.95&lt;/li&gt;
&lt;li&gt;Shiseido Men Face Cleanser 125ml — €18.95&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The customer then said:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;buy me 2 of Rilastil Aqua Face Cleanser 200ml and 1 Shiseido Men Face Cleanser 125ml&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The system created checkout, configured fulfillment and wallet payment, and moved the buyer into the final authorization step.&lt;/p&gt;

&lt;p&gt;After the order completed, the customer came back with:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Oh no, I made a mistake — I want to return the item&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The return flow asked for the order number, verified eligibility, and surfaced the exact purchased items:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rilastil Aqua Face Cleanser 200ml (Quantity: 2)&lt;/li&gt;
&lt;li&gt;Shiseido Men Face Cleanser 125ml (Quantity: 1)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The customer selected only the Shiseido item. Then gave the reason:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Other — I made a mistake&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Instead of routing to a standard return portal, the system evaluated the return and offered a keep option:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can keep the Shiseido Men Face Cleanser and receive €1.00 off your next order as a discount code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The customer replied:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Accept&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The result:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keep offer accepted ✓&lt;/li&gt;
&lt;li&gt;Discount code &lt;strong&gt;KEEP-3V9FNM&lt;/strong&gt; generated in WooCommerce ✓&lt;/li&gt;
&lt;li&gt;Confirmation email delivered via KeepCard's email stack ✓&lt;/li&gt;
&lt;li&gt;No return shipment needed ✓&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is exactly the kind of post-purchase flow that usually lives inside rigid portals, manual support queues, or custom integrations tied to one model vendor. Tonight it happened conversationally on top of a live WooCommerce stack.&lt;/p&gt;




&lt;h2&gt;
  
  
  The architecture: what UCPReady and KeepCard.io actually are
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;UCPReady&lt;/strong&gt; is a WooCommerce plugin that implements the &lt;a href="https://ucp.dev" rel="noopener noreferrer"&gt;Universal Commerce Protocol (UCP)&lt;/a&gt; — an open protocol for exposing store capabilities through structured, machine-operable interfaces. It turns a WooCommerce store into a UCP-compliant endpoint that AI agents can discover and transact with autonomously.&lt;/p&gt;

&lt;p&gt;The MCP endpoint on houseofparfum.nl exposes these tools:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;— shopping —
ucp_list_products       ucp_get_product
create_checkout         get_checkout
update_checkout         complete_checkout
cancel_checkout         create_cart
get_cart                update_cart
cancel_cart             convert_cart
ucp_get_order           ucp_list_orders

— returns (KeepCard) —
keepcard_check_return_eligibility
keepcard_select_return_items
keepcard_submit_return_reason
keepcard_accept_keep_offer
keepcard_decline_keep_offer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;KeepCard.io&lt;/strong&gt; is a standalone returns intelligence platform. It connects to WooCommerce via REST API and Shopify via app installation. It owns the decision engine — return eligibility, keep-offer thresholds, fraud signals, monthly caps, discount code generation, and email delivery. None of that logic lives in the LLM.&lt;/p&gt;

&lt;p&gt;The UCPReady companion plugin for KeepCard exposes five MCP tools that let any agent drive the return flow conversationally, while KeepCard handles all the business logic and side effects server-side.&lt;/p&gt;




&lt;h2&gt;
  
  
  The important part: no AI in the business logic
&lt;/h2&gt;

&lt;p&gt;This is the part worth repeating.&lt;/p&gt;

&lt;p&gt;There is no hidden LLM orchestration inside the return engine. There is no model deciding business logic in the backend. There is no "if Claude says X, do Y" architecture.&lt;/p&gt;

&lt;p&gt;The business logic is deterministic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Return eligibility&lt;/li&gt;
&lt;li&gt;Order verification&lt;/li&gt;
&lt;li&gt;Keep-offer thresholds&lt;/li&gt;
&lt;li&gt;Duplicate protection&lt;/li&gt;
&lt;li&gt;Policy routing&lt;/li&gt;
&lt;li&gt;Store credit and discount issuance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The model is only the interface layer.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That makes the system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Model-agnostic — Claude, GPT-5, Gemini, Grok all work&lt;/li&gt;
&lt;li&gt;Easier to audit — no prompt-based rules buried in a system prompt&lt;/li&gt;
&lt;li&gt;Easier to harden — business rules are code, not inference&lt;/li&gt;
&lt;li&gt;More future-proof — swap the model, the commerce layer stays the same&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The same session ran successfully with both Claude Sonnet 4.5 and GPT-5. Neither needed store-specific prompting. The protocol carries the context.&lt;/p&gt;




&lt;h2&gt;
  
  
  How the return flow chains through UCPReady
&lt;/h2&gt;

&lt;p&gt;The integration works server-to-server. When the agent calls &lt;code&gt;keepcard_check_return_eligibility&lt;/code&gt;, UCPReady makes an HTTP POST to the KeepCard &lt;code&gt;/api/mcp/init&lt;/code&gt; endpoint with the store slug, order ID, and email. KeepCard resolves the order directly against WooCommerce or Shopify using its own stored credentials — UCPReady never touches the order data.&lt;/p&gt;

&lt;p&gt;The full call chain looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Agent → UCPReady MCP endpoint (WooCommerce)
      → KeepCard /api/mcp/* (cloud service)
      → WooCommerce or Shopify API (order verification)
      → KeepCard decision engine (keep-offer logic)
      → WooCommerce API (discount code creation)
      → KeepCard email stack (confirmation)
      → back through the chain to the agent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The LLM sees clean structured responses at each step:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;keepcard_check_return_eligibility&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;response&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"eligible"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"session_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"needs_item_selection"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"customer_message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"I found order #85774. You have 30 day(s) left to return it. Which item(s) would you like to return?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"order"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"display_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"85774"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"currency"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"EUR"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"days_remaining"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;keepcard_accept_keep_offer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;response&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"outcome"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"kept"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"discount_code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"KEEP-3V9FNM"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"currency"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"EUR"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email_sent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"customer_message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Done! Your discount code is KEEP-3V9FNM — worth 1.00 EUR off your next order. A confirmation has been sent to your email."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;customer_message&lt;/code&gt; field means the agent surfaces KeepCard's language directly — it does not have to infer what to say from raw API data.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why this is different from what's already out there
&lt;/h2&gt;

&lt;p&gt;Most of what is marketed today as "AI returns" falls into one of these buckets:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;What it actually is&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Chatbot on a returns portal&lt;/td&gt;
&lt;td&gt;AI layer on top of an existing flow, still ends in a form&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Custom automation project&lt;/td&gt;
&lt;td&gt;Tied to one model vendor, one store, one integration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Shopify-first AI returns&lt;/td&gt;
&lt;td&gt;Good tooling, but WooCommerce is a different ecosystem&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Refund infrastructure for devs&lt;/td&gt;
&lt;td&gt;Powerful but requires significant custom work&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Those are real products. But they are still mostly AI applications sitting on top of commerce systems.&lt;/p&gt;

&lt;p&gt;What we are building is different: &lt;strong&gt;the commerce system itself becomes operable by agents.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;UCPReady exposes structured commerce capabilities through UCP and MCP. KeepCard.io exposes post-purchase capabilities through the same kind of machine-operable interface. The store does not wait for us to write Claude-specific code, GPT-specific prompts, or Gemini-specific workflows.&lt;/p&gt;

&lt;p&gt;The model is replaceable. The protocol is the product.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why WooCommerce specifically matters
&lt;/h2&gt;

&lt;p&gt;A lot of public examples in this space are Shopify-first. That makes sense — Shopify has a louder app ecosystem and more visible AI tooling.&lt;/p&gt;

&lt;p&gt;But what happened tonight was on WooCommerce.&lt;/p&gt;

&lt;p&gt;WooCommerce powers a large share of the world's online stores. It has almost no public examples of protocol-driven, frontier-model, post-purchase flows. The combination of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;WooCommerce-native&lt;/li&gt;
&lt;li&gt;Protocol-native (UCP)&lt;/li&gt;
&lt;li&gt;Model-agnostic&lt;/li&gt;
&lt;li&gt;Agent-executable&lt;/li&gt;
&lt;li&gt;Post-purchase keep-offer logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;...is the category we are helping define. I have not seen a strong public proof of this combination before tonight.&lt;/p&gt;




&lt;h2&gt;
  
  
  What broke (because honesty matters)
&lt;/h2&gt;

&lt;p&gt;Tonight was not a perfect demo, and that is exactly why it was valuable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. The keep-offer accept step was occasionally slow.&lt;/strong&gt; The final &lt;code&gt;keepcard_accept_keep_offer&lt;/code&gt; step sometimes exceeded the runner timeout budget. The business action still completed — coupon created, email sent, session marked kept — but the agent runner could report failure because the round trip took too long. This is a bridge latency problem, not a logic problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Duplicate finalization needed hardening.&lt;/strong&gt; When the first accept completed but the runtime retried, we needed the system to treat the retry as a successful terminal state rather than an error. Repeated accept should return: already processed, discount code, final state. That is what resilient agent commerce looks like.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Mixed shopping and returns in one session exposed session contamination.&lt;/strong&gt; In one test, we ran search → purchase → return inside a single session. That exposed a session-orchestration issue: return tools were receiving stale search arguments from the earlier shopping flow. Not a KeepCard logic problem. A session-context boundary problem. The kind you only discover once the stack is real enough to chain these experiences together.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where we go next
&lt;/h2&gt;

&lt;p&gt;The hardest question has been answered: can a model search, buy, and then resolve a return with keep-offer logic on a live WooCommerce store through protocol-native rails?&lt;/p&gt;

&lt;p&gt;Yes. Tonight, it did.&lt;/p&gt;

&lt;p&gt;The remaining work is hardening, not architecture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reduce latency on the post-purchase bridge&lt;/li&gt;
&lt;li&gt;Keep terminal actions idempotent across retries&lt;/li&gt;
&lt;li&gt;Isolate session state between shopping and returns flows&lt;/li&gt;
&lt;li&gt;Test identity linking across multi-session journeys&lt;/li&gt;
&lt;li&gt;Validate the same lifecycle across more stores&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When the remaining problems are latency budgets, idempotency, and session context boundaries — you are no longer asking whether the concept works. You are refining a working system.&lt;/p&gt;




&lt;h2&gt;
  
  
  The bigger idea
&lt;/h2&gt;

&lt;p&gt;The goal is not "AI can help with returns."&lt;/p&gt;

&lt;p&gt;The goal is: &lt;strong&gt;stores should become operable by agents through standard protocols.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Search is one capability. Checkout is one capability. Payment is one capability. Returns are one capability. Keep-offers are one capability. Once those are exposed properly through open protocol rails, the model becomes interchangeable.&lt;/p&gt;

&lt;p&gt;That is when agentic commerce stops being a gimmick and starts becoming infrastructure.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;UCPReady: &lt;a href="https://zologic.nl/ucpready" rel="noopener noreferrer"&gt;zologic.nl/ucpready&lt;/a&gt; — WooCommerce UCP implementation&lt;/em&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;KeepCard.io: &lt;a href="https://keepcard.io" rel="noopener noreferrer"&gt;keepcard.io&lt;/a&gt; — Returns intelligence platform&lt;/em&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;Session recording: &lt;a href="https://ucpplayground.com/s/01KQFVJJK6HZF2Z58MVMZQ3WXP" rel="noopener noreferrer"&gt;ucpplayground.com/s/01KQFVJJK6HZF2Z58MVMZQ3WXP&lt;/a&gt;&lt;/em&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;Universal Commerce Protocol: &lt;a href="https://ucp.dev" rel="noopener noreferrer"&gt;ucp.dev&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>woocommerce</category>
      <category>mcp</category>
      <category>webdev</category>
    </item>
    <item>
      <title>60 seconds to see if your webstore supports the latests UCP protocol. Give it a run!</title>
      <dc:creator>Almin Zolotic</dc:creator>
      <pubDate>Thu, 30 Apr 2026 12:03:40 +0000</pubDate>
      <link>https://dev.to/zologic/60-seconds-to-see-if-your-webstore-supports-the-latests-ucp-protocol-give-it-a-run-364j</link>
      <guid>https://dev.to/zologic/60-seconds-to-see-if-your-webstore-supports-the-latests-ucp-protocol-give-it-a-run-364j</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/benjifisher/is-my-store-ucp-ready-how-to-check-in-60-seconds-4fco" class="crayons-story__hidden-navigation-link"&gt;Is My Store UCP Ready? How to Check in 60 Seconds&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/benjifisher" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3787687%2F0c8176d8-b238-43f2-b0af-71689e955123.jpg" alt="benjifisher profile" class="crayons-avatar__image" width="400" height="400"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/benjifisher" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Benji Fisher
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Benji Fisher
                
              
              &lt;div id="story-author-preview-content-3591133" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/benjifisher" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3787687%2F0c8176d8-b238-43f2-b0af-71689e955123.jpg" class="crayons-avatar__image" alt="" width="400" height="400"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Benji Fisher&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/benjifisher/is-my-store-ucp-ready-how-to-check-in-60-seconds-4fco" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Apr 30&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/benjifisher/is-my-store-ucp-ready-how-to-check-in-60-seconds-4fco" id="article-link-3591133"&gt;
          Is My Store UCP Ready? How to Check in 60 Seconds
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ecommerce"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ecommerce&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/tutorial"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;tutorial&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ucp"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ucp&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/benjifisher/is-my-store-ucp-ready-how-to-check-in-60-seconds-4fco" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;2&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/benjifisher/is-my-store-ucp-ready-how-to-check-in-60-seconds-4fco#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              1&lt;span class="hidden s:inline"&gt;&amp;nbsp;comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            5 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>The 0.2% flawless rate from your April report is wild. Most stores have a manifest. Almost none actually work end-to-end. It's a conformance problem, not an infrastructure problem — and that's exactly what this score makes visible.
Love what you built here</title>
      <dc:creator>Almin Zolotic</dc:creator>
      <pubDate>Wed, 29 Apr 2026 11:29:46 +0000</pubDate>
      <link>https://dev.to/zologic/the-02-flawless-rate-from-your-april-report-is-wild-most-stores-have-a-manifest-almost-none-4ngi</link>
      <guid>https://dev.to/zologic/the-02-flawless-rate-from-your-april-report-is-wild-most-stores-have-a-manifest-almost-none-4ngi</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/benjifisher/introducing-the-ucp-score-a-0-100-agent-readiness-grade-for-every-ucp-store-1851" class="crayons-story__hidden-navigation-link"&gt;Introducing the UCP Score: A 0–100 Agent-Readiness Grade for Every UCP Store&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/benjifisher" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3787687%2F0c8176d8-b238-43f2-b0af-71689e955123.jpg" alt="benjifisher profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/benjifisher" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Benji Fisher
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Benji Fisher
                
              
              &lt;div id="story-author-preview-content-3585672" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/benjifisher" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3787687%2F0c8176d8-b238-43f2-b0af-71689e955123.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Benji Fisher&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/benjifisher/introducing-the-ucp-score-a-0-100-agent-readiness-grade-for-every-ucp-store-1851" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Apr 29&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/benjifisher/introducing-the-ucp-score-a-0-100-agent-readiness-grade-for-every-ucp-store-1851" id="article-link-3585672"&gt;
          Introducing the UCP Score: A 0–100 Agent-Readiness Grade for Every UCP Store
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ecommerce"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ecommerce&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/product"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;product&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ucp"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ucp&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/benjifisher/introducing-the-ucp-score-a-0-100-agent-readiness-grade-for-every-ucp-store-1851" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;5&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/benjifisher/introducing-the-ucp-score-a-0-100-agent-readiness-grade-for-every-ucp-store-1851#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              2&lt;span class="hidden s:inline"&gt;&amp;nbsp;comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            8 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>AP2 Mandates Are Live on UCPReady — Here's What That Actually Means for Autonomous Payment</title>
      <dc:creator>Almin Zolotic</dc:creator>
      <pubDate>Fri, 24 Apr 2026 19:42:29 +0000</pubDate>
      <link>https://dev.to/zologic/ap2-mandates-are-live-on-ucpready-heres-what-that-actually-means-for-autonomous-payment-1bba</link>
      <guid>https://dev.to/zologic/ap2-mandates-are-live-on-ucpready-heres-what-that-actually-means-for-autonomous-payment-1bba</guid>
      <description>&lt;p&gt;Zero merchants in &lt;a href="https://dev.to/benjifisher/agentic-commerce-optimization-what-4491-merchants-reveal-about-ucp-readiness-3fk"&gt;Ben Fisher's 4,024-merchant UCP dataset&lt;/a&gt; support native payment. I've been building toward closing that gap since March. Today it's done — at least on the business side.&lt;/p&gt;

&lt;p&gt;This post is about AP2 Mandates: what they are, why they're the only spec-compliant path to autonomous card payment on UCP, and what it took to implement them correctly on WooCommerce.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why every UCP checkout still ends with a browser redirect
&lt;/h2&gt;

&lt;p&gt;When an AI agent completes a UCP checkout today, it gets a &lt;code&gt;continue_url&lt;/code&gt;. The buyer clicks a link, lands on the WooCommerce checkout page, fills in their card, and pays. The agent handled discovery and session setup. The human handled payment.&lt;/p&gt;

&lt;p&gt;That handoff exists because the spec requires it — unless one specific extension is active.&lt;/p&gt;

&lt;p&gt;From the UCP checkout specification:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The checkout has to be finalized manually by the user through a trusted UI &lt;strong&gt;unless the AP2 Mandates extension is supported&lt;/strong&gt;."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That "unless" is the entire autonomous payment story in UCP. Not Stripe tokens. Not saved cards. Not wallet APIs. &lt;strong&gt;AP2 Mandates.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What AP2 Mandates actually are
&lt;/h2&gt;

&lt;p&gt;AP2 is a cryptographic authorization framework. When it's negotiated between a business and a platform, the checkout session is "security locked" — neither party can revert to an unprotected flow.&lt;/p&gt;

&lt;p&gt;The flow has two sides:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Business side:&lt;/strong&gt; Every checkout response must include &lt;code&gt;ap2.merchant_authorization&lt;/code&gt; — a JWS detached signature proving the checkout terms (price, line items, totals) are authentic and haven't been tampered with. The signature is ES256, JCS-canonicalized per RFC 8785, with the payload excluded from the JWS body (RFC 7515 Appendix F detached content format).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Platform side:&lt;/strong&gt; When the user confirms the purchase, the platform generates a cryptographically signed mandate — an SD-JWT credential proving the user explicitly authorized this specific transaction. It submits that mandate at &lt;code&gt;complete_checkout&lt;/code&gt;. The business verifies it. If valid, payment proceeds without a browser redirect.&lt;/p&gt;

&lt;p&gt;The checkout mandate contains the full checkout response including the business's &lt;code&gt;merchant_authorization&lt;/code&gt;. So the platform's signature covers the business's signature. It's a nested cryptographic binding: the business proves the terms, the platform proves the user consented to those exact terms.&lt;/p&gt;




&lt;h2&gt;
  
  
  What implementing this actually required
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Getting the signing right
&lt;/h3&gt;

&lt;p&gt;The spec says ES256 with detached JWS. In PHP, &lt;code&gt;openssl_sign()&lt;/code&gt; on a P-256 key produces a DER-encoded ECDSA signature. JWS ES256 requires raw &lt;code&gt;r||s&lt;/code&gt; — 64 bytes for P-256. Those are not the same format.&lt;/p&gt;

&lt;p&gt;Every JWS library you'd use on the platform side (jose, python-jose, jsonwebtoken) expects raw r||s. A DER signature will fail verification silently or throw a malformed signature error. The fix is a DER-to-raw-rs converter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// openssl_sign() → DER. JWS ES256 → raw r||s. Not the same.&lt;/span&gt;
&lt;span class="nb"&gt;openssl_sign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$signing_input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$signature_der&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$private_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;OPENSSL_ALGO_SHA256&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;substr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$der_inner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$r_offset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$r_len&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;substr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$der_inner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$s_offset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$s_len&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$signature_raw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str_pad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;ltrim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\x00&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\x00&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;STR_PAD_LEFT&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
               &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nb"&gt;str_pad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;ltrim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\x00&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\x00&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;STR_PAD_LEFT&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The JCS canonicalization (RFC 8785) is the other non-obvious requirement. Before signing, the checkout payload is canonicalized — keys sorted recursively, Unicode normalized, numbers in IEEE 754 format. This ensures the signature is reproducible across systems that may re-serialize JSON differently.&lt;/p&gt;

&lt;h3&gt;
  
  
  Enforcing the mandate at complete_checkout
&lt;/h3&gt;

&lt;p&gt;The spec is explicit: if AP2 was negotiated, &lt;code&gt;complete_checkout&lt;/code&gt; MUST reject requests without &lt;code&gt;ap2.checkout_mandate&lt;/code&gt;. This is the security boundary. Without it, AP2 is advertised but provides no protection — a platform could skip the mandate entirely and the checkout would succeed.&lt;/p&gt;

&lt;p&gt;The enforcement block runs before order creation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$ap2_ext&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;is_ap2_configured&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$mandate_jwt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$body&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'ap2'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'checkout_mandate'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="k"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$mandate_jwt&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Return mandate_required error — session stays ready_for_complete&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;mandate_error_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'mandate_required'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$session&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nv"&gt;$mandate_error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$ap2_ext&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;verify_checkout_mandate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$mandate_jwt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nv"&gt;$mandate_error&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;mandate_error_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$mandate_error&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'code'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nv"&gt;$session&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Verifying the mandate
&lt;/h3&gt;

&lt;p&gt;When a mandate is present, the full verification chain runs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Parse the SD-JWT structure (&lt;code&gt;header.payload.signature~disclosures~keybinding&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Check expiry (&lt;code&gt;exp&lt;/code&gt; claim)&lt;/li&gt;
&lt;li&gt;Extract the embedded checkout from mandate claims&lt;/li&gt;
&lt;li&gt;Re-verify &lt;code&gt;merchant_authorization&lt;/code&gt; — confirm the platform wrapped our own signature, not a different checkout&lt;/li&gt;
&lt;li&gt;Verify checkout ID matches the current session&lt;/li&gt;
&lt;li&gt;Verify totals match — no bait-and-switch between what the user saw and what gets charged&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Platform key verification
&lt;/h3&gt;

&lt;p&gt;The final step: verifying the SD-JWT outer signature using the platform's public key. This is what proves the mandate is genuinely from the platform and not forged.&lt;/p&gt;

&lt;p&gt;The flow: decode the JWS header → extract &lt;code&gt;alg&lt;/code&gt; and &lt;code&gt;kid&lt;/code&gt; → fetch the platform's UCP profile from the &lt;code&gt;UCP-Agent&lt;/code&gt; header → pull &lt;code&gt;signing_keys&lt;/code&gt; → find the JWK matching &lt;code&gt;kid&lt;/code&gt; → build an OpenSSL public key from the JWK &lt;code&gt;x&lt;/code&gt;/&lt;code&gt;y&lt;/code&gt; coordinates → verify.&lt;/p&gt;

&lt;p&gt;Building an EC public key from JWK coordinates without a library means constructing the SubjectPublicKeyInfo DER by hand in PHP — OID encoding, SEQUENCE wrapping, BIT STRING for the uncompressed EC point. It's ~80 lines but removes a runtime dependency and works on any WordPress host.&lt;/p&gt;

&lt;p&gt;The platform profile is fetched over HTTPS and cached with WP transients, respecting &lt;code&gt;Cache-Control max-age&lt;/code&gt; with a 60-second floor. Verification result is logged with kid, algorithm, and session ID for auditability.&lt;/p&gt;




&lt;h2&gt;
  
  
  The capability name that broke everything
&lt;/h2&gt;

&lt;p&gt;Before any of this verification mattered, there was a simpler bug: the capability was advertised as &lt;code&gt;dev.ucp.shopping.ap2_mandates&lt;/code&gt; — plural. The spec uses &lt;code&gt;dev.ucp.shopping.ap2_mandate&lt;/code&gt; — singular.&lt;/p&gt;

&lt;p&gt;Capability negotiation is a string equality check. The intersection algorithm finds no match between &lt;code&gt;ap2_mandates&lt;/code&gt; and &lt;code&gt;ap2_mandate&lt;/code&gt;. AP2 is never activated. Every checkout session falls back to delegate payment. No error, no warning — it silently never negotiates.&lt;/p&gt;

&lt;p&gt;One character. Every implementation should validate capability names against the spec registry rather than trusting their own strings.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's live now
&lt;/h2&gt;

&lt;p&gt;When &lt;code&gt;dev.ucp.shopping.ap2_mandate&lt;/code&gt; is enabled in UCPReady and a compatible platform connects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every checkout response includes &lt;code&gt;ap2.merchant_authorization&lt;/code&gt; (JWS ES256, detached, JCS payload)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;complete_checkout&lt;/code&gt; rejects requests without &lt;code&gt;ap2.checkout_mandate&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Verification runs: SD-JWT parse → expiry → embedded checkout extraction → merchant_authorization re-verification → ID and totals match → platform key verification&lt;/li&gt;
&lt;li&gt;If all checks pass, payment proceeds — no browser redirect&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The one remaining piece is ecosystem readiness: a platform that supports AP2 mandate submission and forwards the access token that proves identity linking. &lt;a href="https://ucpplayground.com" rel="noopener noreferrer"&gt;Ben Fisher's UCPPlayground&lt;/a&gt; is the logical first test. Once that's connected, UCPReady will produce the first confirmed AP2-mandate-verified autonomous purchase on WooCommerce.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why this matters beyond WooCommerce
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to/benjifisher/the-state-of-agentic-commerce-april-2026-l93"&gt;Ben's dataset of 4,024 merchants&lt;/a&gt; shows zero native payment support. Part of that is the SPT/ACS story — Stripe's Shared Payment Token is US-only right now and requires Stripe to host the checkout flow. That's a different architecture than UCP.&lt;/p&gt;

&lt;p&gt;On UCP, AP2 Mandates is the spec's answer. It's protocol-agnostic — the mandate can cover any payment method handled by any PSP. The platform proves user consent cryptographically. The business verifies that proof and charges via their existing payment gateway. No card data crosses protocol boundaries. PSD2 SCA compliance comes from the mandate being platform-issued and buyer-authenticated at mandate creation time.&lt;/p&gt;

&lt;p&gt;This is what autonomous agent commerce looks like when the merchant controls the checkout instead of delegating it to Stripe's infrastructure.&lt;/p&gt;




&lt;p&gt;UCPReady is available at &lt;strong&gt;&lt;a href="https://zologic.nl/ucpready" rel="noopener noreferrer"&gt;zologic.nl/ucpready&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you're building a platform that supports UCP and want to test AP2 mandate submission against a live endpoint, reach out. houseofparfum.nl is running UCPReady 1.8.23 with AP2 ready to activate.&lt;/p&gt;

</description>
      <category>woocommerce</category>
      <category>ucp</category>
      <category>agenticcommerce</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How We Took a New SaaS From Search Confusion to a Clean Google Entity Before Launch</title>
      <dc:creator>Almin Zolotic</dc:creator>
      <pubDate>Thu, 23 Apr 2026 16:06:30 +0000</pubDate>
      <link>https://dev.to/zologic/how-we-took-a-new-saas-from-search-confusion-to-a-clean-google-entity-before-launch-2o6e</link>
      <guid>https://dev.to/zologic/how-we-took-a-new-saas-from-search-confusion-to-a-clean-google-entity-before-launch-2o6e</guid>
      <description>&lt;p&gt;We’re launching &lt;strong&gt;KeepCard&lt;/strong&gt; on Product Hunt tomorrow.&lt;/p&gt;

&lt;p&gt;Before launch, we ran into a problem that a lot of early-stage products probably hit and don’t notice right away:&lt;/p&gt;

&lt;p&gt;Google was getting confused about &lt;strong&gt;what KeepCard actually is&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of understanding KeepCard as a B2B ecommerce product, it was blending our brand with unrelated products that had a similar name. The page itself was fine to a human, but search engines need more than “looks good” to understand a brand entity correctly.&lt;/p&gt;

&lt;p&gt;So we spent time fixing the foundation.&lt;/p&gt;

&lt;h2&gt;
  
  
  What KeepCard is
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;KeepCard&lt;/strong&gt; is a pre-return recovery platform for Shopify and WooCommerce merchants.&lt;/p&gt;

&lt;p&gt;It sits in front of the normal return flow. A customer scans a QR card, verifies the order, selects a reason, and preference-based returns can receive a controlled keep offer before reverse logistics starts.&lt;/p&gt;

&lt;p&gt;That’s very different from a generic “card app” or consumer wallet product.&lt;/p&gt;

&lt;p&gt;And that difference needs to be obvious everywhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  The real SEO problem wasn’t rankings first. It was identity.
&lt;/h2&gt;

&lt;p&gt;A lot of launch-stage SEO advice focuses on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;titles&lt;/li&gt;
&lt;li&gt;meta descriptions&lt;/li&gt;
&lt;li&gt;page speed&lt;/li&gt;
&lt;li&gt;keyword placement&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those matter, but our first issue was more basic:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Google wasn’t fully confident about the entity behind the name.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If your brand name overlaps with existing apps, products, or companies, then good markup alone may not be enough. Search engines look at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;page titles and descriptions&lt;/li&gt;
&lt;li&gt;structured data&lt;/li&gt;
&lt;li&gt;crawlable supporting pages&lt;/li&gt;
&lt;li&gt;social cards&lt;/li&gt;
&lt;li&gt;external mentions&lt;/li&gt;
&lt;li&gt;linked profiles&lt;/li&gt;
&lt;li&gt;consistency of naming across the web&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So we approached this like an entity cleanup project, not just an on-page SEO task.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we changed
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. We made the homepage name more explicit
&lt;/h3&gt;

&lt;p&gt;Instead of only saying &lt;code&gt;KeepCard&lt;/code&gt;, we started using:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;KeepCard for Shopify and WooCommerce&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That sounds small, but it gives search engines a much stronger disambiguation signal.&lt;/p&gt;

&lt;p&gt;We updated:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;title tags&lt;/li&gt;
&lt;li&gt;Open Graph tags&lt;/li&gt;
&lt;li&gt;Twitter cards&lt;/li&gt;
&lt;li&gt;meta descriptions&lt;/li&gt;
&lt;li&gt;application naming&lt;/li&gt;
&lt;li&gt;structured data labels&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal was simple: every important machine-readable surface should say the same thing.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. We strengthened structured data
&lt;/h3&gt;

&lt;p&gt;We expanded the homepage schema to describe KeepCard as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an &lt;code&gt;Organization&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;a &lt;code&gt;WebSite&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;a &lt;code&gt;SoftwareApplication&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;a &lt;code&gt;Service&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And we added supporting context like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;alternate names&lt;/li&gt;
&lt;li&gt;audience&lt;/li&gt;
&lt;li&gt;publisher&lt;/li&gt;
&lt;li&gt;brand relationship&lt;/li&gt;
&lt;li&gt;service type&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The point wasn’t “more schema because schema is good.”&lt;/p&gt;

&lt;p&gt;The point was to help Google understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;who we are&lt;/li&gt;
&lt;li&gt;what we offer&lt;/li&gt;
&lt;li&gt;who it is for&lt;/li&gt;
&lt;li&gt;what category we belong to&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. We de-indexed the wrong surfaces
&lt;/h2&gt;

&lt;p&gt;Our merchant app lives on a separate subdomain.&lt;/p&gt;

&lt;p&gt;That app is useful to users, but not useful as a landing surface for search engines. In fact, it can create confusion if it exposes thin or generic titles.&lt;/p&gt;

&lt;p&gt;So we added &lt;code&gt;noindex&lt;/code&gt; signals there and kept the public marketing site as the canonical search target.&lt;/p&gt;

&lt;p&gt;This is underrated:&lt;/p&gt;

&lt;p&gt;Sometimes SEO improves not by publishing more pages, but by making sure crawlers ignore the wrong ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. We improved technical quality because trust compounds
&lt;/h2&gt;

&lt;p&gt;We also cleaned up the technical side:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;fixed render-blocking font issues&lt;/li&gt;
&lt;li&gt;reduced layout shift&lt;/li&gt;
&lt;li&gt;improved heading structure&lt;/li&gt;
&lt;li&gt;added proper landmarks&lt;/li&gt;
&lt;li&gt;cleaned up CSP problems&lt;/li&gt;
&lt;li&gt;improved performance on mobile&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We ended up with a clean Lighthouse result:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;100 Performance&lt;/li&gt;
&lt;li&gt;100 Accessibility&lt;/li&gt;
&lt;li&gt;100 Best Practices&lt;/li&gt;
&lt;li&gt;100 SEO&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That score alone doesn’t guarantee rankings.&lt;/p&gt;

&lt;p&gt;But it removes a lot of unnecessary ambiguity and friction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I’m posting this before Product Hunt
&lt;/h2&gt;

&lt;p&gt;Because launch traffic is noisy.&lt;/p&gt;

&lt;p&gt;If people mention your brand tomorrow across:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Product Hunt&lt;/li&gt;
&lt;li&gt;X&lt;/li&gt;
&lt;li&gt;DEV&lt;/li&gt;
&lt;li&gt;LinkedIn&lt;/li&gt;
&lt;li&gt;indie communities&lt;/li&gt;
&lt;li&gt;blog roundups&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;you want those mentions reinforcing one clear identity.&lt;/p&gt;

&lt;p&gt;Not scattering weak, inconsistent versions of your brand across the web.&lt;/p&gt;

&lt;p&gt;That means the best time to fix entity confusion is &lt;strong&gt;before&lt;/strong&gt; the wave of citations starts.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we’re doing now to build branded citations and backlinks
&lt;/h2&gt;

&lt;p&gt;The next phase is consistency.&lt;/p&gt;

&lt;p&gt;We want every mention of KeepCard to reinforce the same identity:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;KeepCard is a pre-return recovery platform for Shopify and WooCommerce merchants.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So we’re pushing that exact framing across:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Product Hunt&lt;/li&gt;
&lt;li&gt;DEV&lt;/li&gt;
&lt;li&gt;founder social profiles&lt;/li&gt;
&lt;li&gt;launch posts&lt;/li&gt;
&lt;li&gt;directories&lt;/li&gt;
&lt;li&gt;documentation&lt;/li&gt;
&lt;li&gt;email signatures&lt;/li&gt;
&lt;li&gt;future guest posts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not for keyword stuffing.&lt;/p&gt;

&lt;p&gt;For entity clarity.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I’d recommend to other founders
&lt;/h2&gt;

&lt;p&gt;If you’re launching a new product, especially with a brand name that could be confused with something else:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Stress-test your name in search
&lt;/h3&gt;

&lt;p&gt;Search your exact brand and see what Google thinks it is.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Make your machine-readable surfaces consistent
&lt;/h3&gt;

&lt;p&gt;Titles, meta descriptions, OG tags, schema, canonicals, and app naming should tell the same story.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Keep crawlers focused
&lt;/h3&gt;

&lt;p&gt;Index the pages that explain your business best. De-index weak or confusing app surfaces.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Use the same one-sentence description everywhere
&lt;/h3&gt;

&lt;p&gt;You need a stable phrase people can repeat when they mention your company.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Treat backlinks as entity confirmation, not just authority
&lt;/h3&gt;

&lt;p&gt;A backlink helps more when the surrounding text clearly says what your company is.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thought
&lt;/h2&gt;

&lt;p&gt;The biggest SEO win for a new SaaS is often not “ranking harder.”&lt;/p&gt;

&lt;p&gt;It’s making it easy for Google to stop guessing.&lt;/p&gt;

&lt;p&gt;That’s what we focused on for KeepCard before launch.&lt;/p&gt;

&lt;p&gt;If you’re working on search clarity, launch prep, or technical SEO for an early product, I’d love to compare notes.&lt;/p&gt;

&lt;p&gt;We launch tomorrow on Product Hunt.&lt;/p&gt;

&lt;p&gt;You can see the product here: &lt;a href="https://keepcard.io" rel="noopener noreferrer"&gt;https://keepcard.io&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>saas</category>
      <category>seo</category>
      <category>startup</category>
    </item>
    <item>
      <title>WooCommerce Now Has More UCP capabilities than Shopify. Here's the breakdown.</title>
      <dc:creator>Almin Zolotic</dc:creator>
      <pubDate>Tue, 14 Apr 2026 17:39:29 +0000</pubDate>
      <link>https://dev.to/zologic/woocommerce-now-has-more-ucp-capabilities-than-shopify-heres-the-breakdown-4fe2</link>
      <guid>https://dev.to/zologic/woocommerce-now-has-more-ucp-capabilities-than-shopify-heres-the-breakdown-4fe2</guid>
      <description>&lt;p&gt;UCPChecker just launched store-to-store comparisons. I ran my WooCommerce store against Reebok (Shopify). The results surprised me.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ucpchecker.com/compare/houseofparfum.nl/vs/reebok.com" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5yn1u77x6tozzqec30rd.png" alt="houseofparfum.nl vs reebok.com UCP comparison" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Numbers
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;WooCommerce&lt;/th&gt;
&lt;th&gt;Shopify&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Capabilities&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Transports&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Latency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;558ms&lt;/td&gt;
&lt;td&gt;225ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Status&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Verified&lt;/td&gt;
&lt;td&gt;Verified&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Shopify is faster. WooCommerce exposes more.&lt;/p&gt;

&lt;h2&gt;
  
  
  What WooCommerce Has That Shopify Doesn't
&lt;/h2&gt;

&lt;p&gt;Six capabilities are unique to the WooCommerce store:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Identity Linking&lt;/strong&gt; — OAuth 2.0 buyer authentication&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Buyer Consent&lt;/strong&gt; — GDPR/CCPA preference handling&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Embedded Checkout&lt;/strong&gt; — iframe protocol for payment delegation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Catalog Search&lt;/strong&gt; — structured product discovery&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Catalog Lookup&lt;/strong&gt; — individual product fetch&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Products&lt;/strong&gt; — base product capability&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The big one is &lt;strong&gt;Identity Linking&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;When a buyer connects their store account to an AI platform, the agent can access their saved addresses, wallet balance, and (eventually) saved payment methods. This is what enables fully autonomous checkout — the agent doesn't need a credit card if it can use the buyer's stored value.&lt;/p&gt;

&lt;p&gt;Shopify's UCP implementation stops at checkout initiation. The agent can browse, build a cart, and start checkout — but payment requires a browser redirect. The human finishes the transaction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;The UCP spec defines the &lt;em&gt;maximum&lt;/em&gt; surface an agent can interact with. Stores declare which capabilities they support. Agents query the manifest and adapt their behavior.&lt;/p&gt;

&lt;p&gt;A store with 5 capabilities gives agents 5 ways to help. A store with 11 capabilities gives agents 11 ways to help. More surface area = more useful agent interactions = more conversions.&lt;/p&gt;

&lt;p&gt;Right now, Shopify owns the UCP install base — &lt;a href="https://ucpchecker.com/directory" rel="noopener noreferrer"&gt;UCPChecker's directory&lt;/a&gt; shows thousands of Shopify stores with manifests, versus a handful of WooCommerce stores. But install base isn't the same as capability depth.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Latency Trade-off
&lt;/h2&gt;

&lt;p&gt;Shopify: 225ms. WooCommerce: 558ms.&lt;/p&gt;

&lt;p&gt;This is expected. Shopify is a $100B+ platform with global CDN infrastructure. WooCommerce is self-hosted PHP on whatever server the merchant chose.&lt;/p&gt;

&lt;p&gt;558ms for a 40k SKU WooCommerce store is actually solid. And latency matters less than you'd think for agent commerce — agents batch multiple tool calls, so the total session time matters more than individual response times.&lt;/p&gt;

&lt;p&gt;A typical checkout session on either platform takes 5-15 seconds total. Whether each call is 200ms or 500ms doesn't change the user experience much.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Shopify Could Add
&lt;/h2&gt;

&lt;p&gt;The five capabilities Shopify ships are the core: checkout, fulfillment, discount, order management, cart. These cover the happy path for agent shopping.&lt;/p&gt;

&lt;p&gt;To match WooCommerce's depth, Shopify would need to add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Identity linking&lt;/strong&gt; — OAuth flow for buyer authentication&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Embedded checkout&lt;/strong&gt; — ECP protocol for iframe payment&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structured catalog capabilities&lt;/strong&gt; — search and lookup as declared capabilities&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Shopify has the resources to ship these. The question is prioritization. Right now, they've optimized for breadth (every Shopify store has UCP) over depth (limited capability set).&lt;/p&gt;

&lt;h2&gt;
  
  
  What WooCommerce Needs
&lt;/h2&gt;

&lt;p&gt;WooCommerce's advantage is flexibility — you can add any capability the spec supports. The disadvantage is adoption — merchants have to install a plugin and configure it.&lt;/p&gt;

&lt;p&gt;Right now, the WooCommerce UCP ecosystem is small. &lt;a href="https://zologic.nl/ucpready" rel="noopener noreferrer"&gt;UCPReady&lt;/a&gt; is the main option. For WooCommerce to compete on install base, either:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;UCPReady adoption grows organically&lt;/li&gt;
&lt;li&gt;Other plugins emerge (competition is healthy)&lt;/li&gt;
&lt;li&gt;WooCommerce core ships native UCP support&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Option 3 is unlikely near-term — WooCommerce core moves slowly and UCP is still early. But options 1 and 2 are happening.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;Shopify made UCP ubiquitous. WooCommerce made it deep.&lt;/p&gt;

&lt;p&gt;If you're a merchant choosing between platforms, the question is: do you want to be in the largest agent-accessible network (Shopify), or do you want the most capable agent integration (WooCommerce)?&lt;/p&gt;

&lt;p&gt;If you're an agent developer, the answer is simpler: build for both. The &lt;a href="https://ucp.dev" rel="noopener noreferrer"&gt;UCP spec&lt;/a&gt; is platform-agnostic. The same agent code that shops Shopify can shop WooCommerce — it just gets more capabilities on the latter.&lt;/p&gt;

&lt;p&gt;Run your own comparison: &lt;a href="https://ucpchecker.com/compare" rel="noopener noreferrer"&gt;ucpchecker.com/compare&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Building UCP for WooCommerce? I'm &lt;a href="https://dev.to/zologic"&gt;@zologic&lt;/a&gt; — drop a comment or DM.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>ecommerce</category>
      <category>shopify</category>
      <category>woocommerce</category>
    </item>
    <item>
      <title>Building the Only UCP Plugin for WooCommerce — Outside the Walled Garden</title>
      <dc:creator>Almin Zolotic</dc:creator>
      <pubDate>Thu, 09 Apr 2026 17:50:45 +0000</pubDate>
      <link>https://dev.to/zologic/building-the-only-ucp-plugin-for-woocommerce-outside-the-walled-garden-4adk</link>
      <guid>https://dev.to/zologic/building-the-only-ucp-plugin-for-woocommerce-outside-the-walled-garden-4adk</guid>
      <description>&lt;p&gt;When protocol compliance conflicts with platform policy, independence stops being a limitation and becomes a feature that enables full execution.&lt;/p&gt;

&lt;p&gt;Two months ago, AI purchasing landed on Shopify, and within hours a WooCommerce store completed a fully autonomous transaction without any human interaction.&lt;/p&gt;

&lt;p&gt;That store was running UCPReady, a plugin that turns WooCommerce into a Universal Commerce Protocol endpoint for AI agents to transact directly.&lt;/p&gt;

&lt;p&gt;Today, UCPReady is the only WooCommerce plugin with full UCP 2026-04-08 compliance, running in production and processing real autonomous orders.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Makes It Different
&lt;/h2&gt;

&lt;p&gt;UCPReady is not a partial implementation or a demo layer, but a complete protocol-native system designed for real autonomous commerce flows.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full Universal Commerce Protocol 2026-04-08 compliance across all required surfaces and behaviors
&lt;/li&gt;
&lt;li&gt;Support for REST, MCP, and Embedded Checkout transports without fallback compromises
&lt;/li&gt;
&lt;li&gt;Autonomous AI purchasing with no human confirmation step required at checkout
&lt;/li&gt;
&lt;li&gt;Schema Quality rating of A (99) verified through independent validation tools
&lt;/li&gt;
&lt;li&gt;Spec updates shipped within 24 hours from release to production deployment
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is production commerce running on an open protocol rather than a controlled integration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why It’s Not in the Marketplace
&lt;/h2&gt;

&lt;p&gt;Open protocols sometimes introduce requirements that do not align with existing marketplace rules designed for traditional plugin behavior.&lt;/p&gt;

&lt;p&gt;UCP requires that checkout execution completes fully when invoked, including payment processing, instead of redirecting to manual confirmation flows.&lt;/p&gt;

&lt;p&gt;Marketplace policies, reasonably, enforce strict controls around autonomous payment execution for security and user protection reasons.&lt;/p&gt;

&lt;p&gt;That creates a structural mismatch between protocol requirements and platform rules rather than a simple review outcome.&lt;/p&gt;

&lt;p&gt;The decision becomes whether to adapt the protocol to fit the platform or preserve the protocol and distribute independently.&lt;/p&gt;

&lt;p&gt;UCPReady chose to preserve the protocol as designed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Difference in Approach
&lt;/h2&gt;

&lt;p&gt;WooCommerce is building AI capabilities focused on merchants managing their stores through internal tools and administrative workflows.&lt;/p&gt;

&lt;p&gt;UCPReady focuses on the opposite side of the interaction, where AI agents act on behalf of users to discover and purchase products.&lt;/p&gt;

&lt;p&gt;These approaches are not competing implementations, but they operate at completely different layers of the commerce stack.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Independence Works Better
&lt;/h2&gt;

&lt;p&gt;Operating outside the marketplace enables faster iteration cycles that match the pace of protocol evolution without external approval delays.&lt;/p&gt;

&lt;p&gt;Full compliance can be maintained without introducing exceptions, fallbacks, or behavior changes that fragment the protocol surface.&lt;/p&gt;

&lt;p&gt;Support becomes direct and immediate, without reliance on layered support systems or delayed release cycles.&lt;/p&gt;

&lt;p&gt;Merchants get a transparent product with clear capabilities instead of features shaped by policy constraints.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Trade-off
&lt;/h2&gt;

&lt;p&gt;You do not get marketplace distribution, automatic updates, or official platform endorsement through the standard channels.&lt;/p&gt;

&lt;p&gt;You do get full protocol compliance, rapid updates, direct support, and a system designed for autonomous AI commerce from the ground up.&lt;/p&gt;

&lt;p&gt;This is a trade between convenience and capability rather than a limitation of the implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Standards vs Platform Deals
&lt;/h2&gt;

&lt;p&gt;Platform integrations are fast to deploy but inherently limited by agreements, approvals, and ecosystem boundaries.&lt;/p&gt;

&lt;p&gt;Open protocols are slower to standardize but enable interoperability across platforms, agents, and implementations without restriction.&lt;/p&gt;

&lt;p&gt;UCPReady is built on the assumption that standards will outlast individual platform deals.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Means
&lt;/h2&gt;

&lt;p&gt;If you want your WooCommerce store to be accessible to AI agents for real autonomous purchasing, this capability exists today.&lt;/p&gt;

&lt;p&gt;It does not require waiting for platform updates, partnerships, or future roadmap features to become available.&lt;/p&gt;

&lt;p&gt;It requires adopting a protocol-first approach that operates outside traditional distribution models.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Note
&lt;/h2&gt;

&lt;p&gt;Some innovations do not fit inside existing systems because those systems were designed for a different generation of use cases.&lt;/p&gt;

&lt;p&gt;Autonomous AI commerce is one of those cases, and open protocols are where that shift is currently happening.&lt;/p&gt;

&lt;p&gt;UCPReady exists outside the marketplace because that is currently the only place it can fully exist without compromise.&lt;/p&gt;




&lt;p&gt;🔗 &lt;a href="https://zologic.nl/ucpready" rel="noopener noreferrer"&gt;Try UCPReady&lt;/a&gt;&lt;br&gt;&lt;br&gt;
💼 &lt;a href="https://www.linkedin.com/in/almin-zolotic/" rel="noopener noreferrer"&gt;Almin Zolotic on LinkedIn&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>opensource</category>
      <category>php</category>
    </item>
  </channel>
</rss>
