Universal Commerce Protocol (UCP) for PHP and Magento

· Magento 2, Development

Table of contents

On October 15, 2026, Google started rolling out Universal Cart in US Search and the Gemini app: one cart that holds products from several retailers, watches their price and stock, and either lets the shopper pay with Google Pay or hands the items over to the merchant's own cart. Both routes run on the Universal Commerce Protocol (UCP). If you build or maintain Magento, Laravel or custom PHP shops, UCP is the piece worth understanding now, before a client asks why their products can't be added to that cart. Here is what UCP is, what a store has to expose, and how I would approach it on a PHP stack.

What the Universal Commerce Protocol is

UCP describes itself as a common language for platforms, agents and businesses. It is an open specification, co-developed by companies including Google, Shopify and Stripe, with the spec and code on GitHub. The idea: instead of every AI assistant scraping product pages or every platform writing a custom integration per retailer, a store publishes a machine-readable profile and a small set of standard endpoints, and any compatible agent can use them.

The specification is split into capabilities, each named in reverse-domain form:

  • dev.ucp.shopping.checkout: checkout sessions with pricing, tax and fulfilment.
  • dev.ucp.shopping.cart: a multi-item cart.
  • dev.ucp.shopping.order: post-purchase status updates via webhooks.
  • dev.ucp.common.identity_linking: OAuth 2.0 account linking, so a shopper can use their existing store account.
  • Extensions such as dev.ucp.shopping.fulfillment and dev.ucp.shopping.discount, which build on checkout and cart.

Transports are REST and JSON-RPC, and the site says MCP, Agent2Agent (A2A) and the Agent Payments Protocol (AP2) are supported. For a PHP developer, the REST binding is the natural starting point.

What Google's Universal Cart asks of merchants

Google's Merchant Center hub, opened on October 6, lets eligible US merchants choose between three options: cart transfer to their own site, native checkout on Google, and identity linking. According to PPC Land's report on the launch, cart transfer requires UCP version 2026-04-08 or later, a UCP profile at /.well-known/ucp and the cart capability. Access is gradual: merchants apply and Google selects who gets onboarded. The merchant stays the seller of record and keeps handling confirmations and support.

Two other points matter for anyone running a shop:

  • Feeds still drive everything. Price-drop and back-in-stock alerts come from the Shopping Graph, which relies heavily on Merchant Center feeds. A feed that lags behind the real stock means wrong alerts.
  • It is US-only for now. Canada and Australia were pushed to 2027, and the UK has no date. For European stores, this is preparation, not an emergency.

Shopify merchants got this almost for free: since September 18 they have been matched to Merchant Center and enabled by default. Magento and custom PHP shops have to do the integration themselves, which is exactly where developers come in.

Step 1: the discovery profile

Everything starts with a JSON document at /.well-known/ucp. The specification overview requires a top-level ucp object with version, services and payment_handlers, plus optional capabilities, and a keys array (a JWK Set) for signing. Versions are dates in YYYY-MM-DD form. A trimmed example:

{
  "ucp": {
    "version": "2026-08-25",
    "services": {
      "dev.ucp.shopping": [
        {
          "version": "2026-08-25",
          "transport": "rest",
          "endpoint": "https://shop.example.com/ucp/v1"
        }
      ]
    },
    "capabilities": {
      "dev.ucp.shopping.cart": [{ "version": "2026-08-25" }],
      "dev.ucp.shopping.checkout": [{ "version": "2026-08-25" }]
    },
    "payment_handlers": {}
  },
  "keys": []
}

In Laravel this is a single route returning a config-driven array. In Magento, I would not put it in a CMS page: a small module with a frontend router (or a controller under a custom route plus an nginx rewrite for /.well-known/ucp) keeps it versioned with the code. Serve it with Content-Type: application/json, and make sure Varnish or your CDN does not cache an error page there.

// routes/web.php (Laravel)
Route::get('/.well-known/ucp', fn () => response()->json(config('ucp.profile')));

Step 2: capability negotiation

The part that surprised me is how negotiation works. The calling platform sends the URI of its own profile with every request, in the UCP-Agent HTTP header. The store then computes the intersection: it keeps each capability both sides list, picks the highest date version they share, drops capabilities with no common version, and removes extensions whose parent capability fell out. Responses must echo ucp.version and the active ucp.capabilities.

In practice, that means:

  • Fetch and cache the platform profile (with a sensible TTL and a timeout, it is a remote call in your request path).
  • Write the intersection as a pure function with unit tests. It is a few dozen lines, and it is the place where version bugs will hide.
  • Log the negotiated versions per request. When Google moves to a newer version, you want to see it in your logs, not in a support ticket.

Mapping UCP onto Magento and Laravel

The cart and checkout capabilities map fairly well onto what a Magento store already has. Magento's REST and GraphQL APIs already create guest carts, add items, estimate shipping and set addresses; a UCP layer is mostly a translation layer on top of the quote. My checklist for a first version:

  1. Start with cart transfer. It is the smallest scope: build a cart from the agent's items and hand the shopper a URL that restores it. Native checkout brings payment tokens and separate terms; leave it for later.
  2. Use stable product identifiers. The IDs in your Merchant Center feed must match what your UCP endpoints accept. If your feed uses SKUs and your API expects entity IDs, fix that first.
  3. Respect real stock. MSI salable quantity, not the raw stock column, should decide what goes in the cart.
  4. Keep totals honest. Tax and shipping returned to the agent must match what the shopper will see on your checkout, or you will get abandoned carts and complaints.
  5. Protect the endpoints. Rate limiting, request size limits and signature checks with the published keys, like any public API.

For Laravel or custom shops, the same structure applies: a profile route, a negotiation service, and controllers that wrap your existing cart and order services. Don't duplicate business rules in the UCP layer; call the same code your own checkout uses.

Conclusion

UCP is young, versioned by date, and for now only Google's US Universal Cart makes it a real requirement. But it is an open standard backed by the big platforms, and it solves a problem every store will have as more shopping starts in an AI assistant. If you maintain a Magento or PHP shop, two things are worth doing this quarter: clean up the Merchant Center feed so price and stock are always right, and prototype the /.well-known/ucp profile with cart transfer behind a feature flag. When the cart reaches Europe, you will be ready instead of starting from scratch.