> ## Documentation Index
> Fetch the complete documentation index at: https://docs.asva-ai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# UCP on Shopify: Native Settings and Checkout Kit

> Enable UCP on your Shopify store — native UCP settings, Checkout Kit, Storefront API product mapping, and a custom manifest via Cloudflare Workers.

Shopify merchants have three paths to UCP: native Shopify UCP settings (fastest, if available on your plan), a custom manifest backed by Checkout Kit and the Storefront API (full control), or a headless Shopify setup where your own frontend domain hosts the manifest. This guide covers all three so you can choose based on your stack.

<Note>
  Native UCP availability varies by Shopify plan and region. If you don't see an **AI Commerce** or **Universal Commerce Protocol** option in your Shopify Admin, use Option 2 (Checkout Kit) below.
</Note>

## Option 1: Native Shopify UCP

If UCP is available on your plan, this is the fastest path to going live:

<Steps>
  <Step title="Open checkout settings">
    In your Shopify Admin, go to **Settings → Checkout**.
  </Step>

  <Step title="Enable UCP">
    Look for the **AI Commerce** or **Universal Commerce Protocol** section. Toggle UCP on and follow the setup wizard.
  </Step>

  <Step title="Verify endpoints">
    Shopify will automatically expose your product catalog and checkout endpoints. Confirm your store is working by running:

    ```bash theme={null}
    curl https://yourshop.com/.well-known/ucp
    ```

    Then run the [Readiness Score](https://asva-ai.com/tools/readiness) to verify full UCP compliance.
  </Step>
</Steps>

## Option 2: Custom manifest via Checkout Kit

Use this path if native UCP is unavailable or you need custom control over your catalog and checkout logic.

<Steps>
  <Step title="Generate your manifest">
    Use the [Manifest Generator](https://asva-ai.com/tools/manifest) or create the file manually:

    ```json /.well-known/ucp theme={null}
    {
      "version": "1.0",
      "capabilities": {
        "product_catalog": {
          "endpoint": "https://yourshop.myshopify.com/api/ucp/products"
        },
        "checkout": {
          "endpoint": "https://yourshop.myshopify.com/api/ucp/checkout"
        }
      }
    }
    ```
  </Step>

  <Step title="Host the manifest">
    Shopify does not allow arbitrary files at the domain root, so you need to serve `/.well-known/ucp` through a Shopify app route or a custom domain proxy.

    <Tabs>
      <Tab title="Via a Shopify app">
        Add a route handler to your Shopify app (Remix-based apps are common):

        ```javascript routes/well-known.ucp.js theme={null}
        export async function loader({ request }) {
          return new Response(JSON.stringify({
            version: "1.0",
            capabilities: {
              product_catalog: {
                endpoint: `${process.env.SHOP_URL}/api/ucp/products`
              },
              checkout: {
                endpoint: `${process.env.SHOP_URL}/api/ucp/checkout`
              }
            }
          }), {
            headers: { "Content-Type": "application/json" }
          })
        }
        ```
      </Tab>

      <Tab title="Via Cloudflare Workers">
        If your store uses a custom domain, intercept `/.well-known/ucp` requests at the edge with a Cloudflare Worker:

        ```javascript cloudflare-worker.js theme={null}
        const manifest = {
          version: "1.0",
          capabilities: {
            product_catalog: { endpoint: "https://yourshop.com/api/ucp/products" },
            checkout: { endpoint: "https://yourshop.com/api/ucp/checkout" }
          }
        }

        export default {
          async fetch(request) {
            const url = new URL(request.url)
            if (url.pathname === '/.well-known/ucp') {
              return new Response(JSON.stringify(manifest), {
                headers: { 'Content-Type': 'application/json' }
              })
            }
            return fetch(request)
          }
        }
        ```
      </Tab>
    </Tabs>
  </Step>

  <Step title="Build your catalog endpoint using the Storefront API">
    Query Shopify's Storefront API and transform the response to UCP format:

    ```javascript theme={null}
    // GET /api/ucp/products
    const { products } = await shopify.storefront.query(`
      query UCPProducts($first: Int!) {
        products(first: $first) {
          nodes {
            id
            title
            description
            priceRange { minVariantPrice { amount currencyCode } }
            variants(first: 100) {
              nodes {
                id
                title
                selectedOptions { name value }
                price { amount currencyCode }
                availableForSale
              }
            }
          }
        }
      }
    `, { variables: { first: 100 } })

    // Transform to UCP format
    return products.nodes.map(p => ({
      id: p.id,
      name: p.title,
      description: p.description,
      price: {
        amount: Math.round(parseFloat(p.priceRange.minVariantPrice.amount) * 100),
        currency: p.priceRange.minVariantPrice.currencyCode
      },
      availability: 'in_stock',
      variants: p.variants.nodes.map(v => ({
        id: v.id,
        attributes: Object.fromEntries(
          v.selectedOptions.map(o => [o.name.toLowerCase(), o.value])
        ),
        price: {
          amount: Math.round(parseFloat(v.price.amount) * 100),
          currency: v.price.currencyCode
        },
        availability: v.availableForSale ? 'in_stock' : 'out_of_stock'
      }))
    }))
    ```

    <Warning>
      Shopify's Storefront API returns prices as decimal strings (e.g. `"129.99"`). Multiply by 100 and round to an integer before returning them in UCP format — agents expect prices in the smallest currency unit (cents).
    </Warning>
  </Step>

  <Step title="Build your checkout endpoint using Shopify Checkout Kit">
    Use Shopify's `cartCreate` mutation to back your UCP checkout endpoint:

    ```javascript theme={null}
    // POST /api/ucp/checkout
    const checkout = await shopify.storefront.mutate(`
      mutation CartCreate($input: CartInput!) {
        cartCreate(input: $input) {
          cart {
            id
            checkoutUrl
            cost { totalAmount { amount currencyCode } }
            deliveryGroups {
              deliveryOptions {
                title
                estimatedCost { amount currencyCode }
              }
            }
          }
        }
      }
    `, { variables: { input: { lines: cartItems } } })
    ```

    Map the Shopify cart response to UCP checkout format, including the `checkout_id`, `subtotal`, `shipping_options`, and `expires_at`.
  </Step>

  <Step title="Validate your setup">
    Run the Asva readiness audit to confirm everything is correctly wired:

    ```bash theme={null}
    # Verify the manifest
    curl https://yourshop.com/.well-known/ucp

    # Run the full readiness audit
    curl -X POST https://asva-ai.com/api/audit \
      -H "Authorization: Bearer $ASVA_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"domain": "yourshop.com"}'
    ```

    Or use the browser tool: [asva-ai.com/tools/readiness](https://asva-ai.com/tools/readiness)
  </Step>
</Steps>

## Option 3: Headless Shopify

If you run a headless setup (Next.js + Shopify Hydrogen, or a similar combination), your own frontend domain hosts the `/.well-known/ucp` file. Follow the [UCP getting started guide](/ucp/getting-started) for endpoint setup, and use the Shopify Storefront API to back your catalog and checkout endpoints as shown in the Checkout Kit steps above.

## Common issues

<AccordionGroup>
  <Accordion title="Native UCP option not visible in Admin">
    Native UCP is rolling out progressively by plan and region. If it is not visible in **Settings → Checkout**, use the Checkout Kit path (Option 2) above. Native availability is expected to expand in future Shopify releases.
  </Accordion>

  <Accordion title="/.well-known/ucp returns 404 on Shopify domain">
    Shopify blocks unknown paths at the domain root. You must serve the manifest via a Shopify app route or a Cloudflare Worker — you cannot place a static file at `/.well-known/ucp` directly in Shopify's file system. See Step 2 above for both options.
  </Accordion>

  <Accordion title="Price showing as $1.29 instead of $129.00">
    Shopify returns prices as decimal strings (`"1.29"`). If you pass this directly as `amount`, the agent interprets it as 1.29 cents. Always multiply by 100 and round to an integer: `Math.round(parseFloat("129.99") * 100)` → `12999`.
  </Accordion>

  <Accordion title="Variant availability is always in_stock">
    The Storefront API field `availableForSale` reflects combined variant availability. Map it directly: `v.availableForSale ? 'in_stock' : 'out_of_stock'`. For real-time inventory counts, use the Admin API instead.
  </Accordion>
</AccordionGroup>

## Related

<CardGroup cols={2}>
  <Card title="UCP getting started" icon="rocket" href="/ucp/getting-started">
    Full quickstart for UCP on any stack.
  </Card>

  <Card title="Google Merchant Center" icon="google" href="/ucp/google-merchant-center">
    UCP implementation via Merchant Center for Google AI Mode.
  </Card>

  <Card title="Checkout and payments" icon="credit-card" href="/ucp/checkout-and-payments">
    Checkout flow, payment token handling, and error responses.
  </Card>

  <Card title="UCP capability discovery" icon="file-code" href="/ucp/well-known">
    Hosting and validating your /.well-known/ucp manifest.
  </Card>
</CardGroup>
