Skip to content

Loyalty when AI agents shop

More and more orders are placed by an AI agent on the shopper’s behalf: ChatGPT, Gemini, Copilot or the Shop app finds the product, fills the cart and checks out. Nobody sees your theme, the Charm widget or a discount field. This page explains what still works, what does not, and how agents can read a member’s loyalty status through the Universal Commerce Protocol (UCP).

Charm’s tier and membership perks run as an automatic Shopify discount (a Discount Function) tied to the customer, not to a code. Whenever the checkout knows who the buyer is, they apply, whether a person or an agent is at the keyboard:

PerkIn an AI-agent checkout
Tier or membership percentage or fixed discountApplies when the buyer is identified
Member pricing on products or collectionsApplies when the buyer is identified
Free shipping for a tier or membershipApplies when the buyer is identified
Points for the order, tier progress, cashbackAwarded after the order, as always
Store creditSpent by Shopify for a signed-in buyer

Fixed amounts and minimum order values are converted to the currency the agent checks out in, so a 10 EUR tier discount is worth the same in a CZK or USD checkout.

Identified means the checkout carries the Shopify customer: the shopper signed in, or the agent platform linked their Shopify identity (Shopify’s buyer-linked checkout does this and applies automatic discounts). A guest checkout with only an email address gets no member perks, exactly as on your own storefront.

  • Discount codes from points redemptions, birthdays, milestones and tier gifts are bound to the customer but must still be entered. An agent can apply a code the shopper gives it; it cannot discover one on its own.
  • Members-only products are hidden by your theme. An agent does not see the theme, so the product is not blocked in an agent checkout.
  • Referral and affiliate links attribute through the storefront. In an agent checkout, the friend’s or affiliate’s code attributes the order instead.

The Universal Commerce Protocol (Google and Shopify) is how AI agents talk to stores about catalog, cart and checkout. Its loyalty extension, dev.ucp.common.loyalty, lets a store tell the agent which membership and tier the buyer holds, what the benefits are and how many points the cart will earn, so the agent can say “you’re Gold, this order earns 240 points” before the buyer commits.

Charm returns exactly that object:

Terminal window
curl -X POST "https://charm.appfleece.app/api/v1/customers/7712345/ucp-loyalty" \
-H "Authorization: Bearer chrm_live_..." \
-H "Content-Type: application/json" \
-d '{ "line_items": [{ "product_id": "8123456789", "price": 60, "quantity": 2 }] }'
{
"loyalty": {
"com.myshopify.your-store.loyalty": {
"id": "mbr_3f9a61c0d2e4b7a8",
"name": "Rewards Club",
"display_id": "****2345",
"tiers": [
{
"id": "gold",
"name": "Gold",
"benefits": [
{ "id": "points_multiplier", "description": "2× points on every order" },
{ "id": "benefit_free_shipping", "description": "Free shipping" }
]
}
],
"rewards": [
{
"currency": { "name": "points", "code": "PTS", "decimal_places": 0 },
"earning_forecast": {
"amount": 240,
"breakdown": [
{ "id": "base", "amount": 120, "description": "1 points per EUR spent" },
{ "id": "tier_multiplier", "amount": 120, "description": "Gold bonus (2× points)", "benefit_id": "points_multiplier" }
]
}
}
],
"provisional": false
}
},
"messages": [
{ "type": "info", "code": "membership_benefit_eligible", "path": "$.loyalty['com.myshopify.your-store.loyalty']", "content": "Gold: 2× points apply to this order." }
]
}
UCP fieldWhat Charm puts there
map keycom.myshopify.<your-handle>.loyalty, the claim id an agent sends in context.eligibility
idAn opaque member id, stable per customer, never the Shopify id
display_idThe last four digits of the customer id, masked
tiersThe tier the member holds, with its benefits as display text
rewards[].currencyYour points name
rewards[].earning_forecastPoints the cart would earn; the breakdown rows add up to the total
provisionalfalse: Charm answers only for a customer the caller identified

The balance is deliberately absent: UCP models spendable value as a payment method or a future redemption capability, not as loyalty data.

A buyer who is not a member gets an empty loyalty map and an eligibility_invalid message, as the specification asks.

All three accept a customer session token, so a shopper-facing app can call them for its own customer. None of them calls Shopify, and nothing is written.

Shopify answers UCP requests for stores on its agentic channels. Today Shopify does not yet offer apps a documented way to contribute the loyalty extension; we are working with Shopify on it, and the object above is ready to pass through the day it opens. If you run your own UCP server (headless or custom commerce), return this object unchanged in your catalog, cart and checkout responses.