Is your storefront agentic?

Add-to-cart button for AI agents: a real button in a form

An agent-ready add-to-cart control is a native button with visible text, such as Add to cart, inside a form that posts to the cart. AI agents find actions through the accessibility tree, where a clickable div has no role, and a plain form post works even before JavaScript loads.

Updated · By the Medusa team

Category
Operability (20% of score)
Impact
High
Scanner check
Add-to-cart is a real, named button in a form

Why it matters for AI agents

Add-to-cart is the single most important action on a product page, and it is where many agents get stuck. Browser agents such as Claude in Chrome and ChatGPT’s agent rely on the accessibility tree, the browser’s structured list of elements with their roles, names and states (Claude browser use tool, OpenAI publisher FAQ). Lighthouse’s agentic audits state that agents “rely on the accessibility tree as their primary data model” (Lighthouse).

In that tree, <button>Add to cart</button> appears as button "Add to cart". A <div onclick="addToCart()"> appears as plain text, or not at all. WCAG’s Name, Role, Value criterion and the first rule of Using ARIA say the same thing: use the native element.

Wrapping the button in a <form> with an action adds a second path. Agents and tools that work from fetched HTML, without running scripts, can see exactly where the add-to-cart request goes and what it needs, such as a variant ID and quantity.

What the scanner checks

The scanner inspects the server HTML of up to three sampled product pages, without running JavaScript. It looks for add-to-cart candidates by text or accessible name (“Add to cart/bag/basket”, “Buy now”, “Add to order”, “Pre-order now”) and by attributes like name, id, class or data-testid (for example add-to-cart, addtocart, product-form__submit). The best result across the sampled pages counts.

Result When
Pass A native <button> or <input type="submit"> with an accessible name, inside a <form> that has an action attribute
Partial A named native button exists, but it is not inside a <form>, or the form has no action (JavaScript-only)
Fail Add-to-cart is a <div>, <span>, link or role="button" element, or no add-to-cart control is in the server HTML
Inconclusive No product page could be loaded

How to fix it

  1. Render add-to-cart as a native submit button with visible text.
  2. Wrap it in a form that posts to your cart route, with the selected variant and quantity as inputs.
  3. Enhance with JavaScript (an AJAX cart drawer, for example) by intercepting the form’s submit event, not by replacing the form.
<form method="post" action="/cart/add">
  <input type="hidden" name="id" value="44012345678901" />
  <label for="qty">Quantity</label>
  <input id="qty" type="number" name="quantity" value="1" min="1" />
  <button type="submit">Add to cart</button>
</form>

For a sold-out product:

<button type="submit" disabled>Sold out</button>

Put variant selectors inside the same form, so the selected size or color is submitted with the request. Verify with curl -s <product URL> | grep -i '<form' and confirm the form and button appear in the raw HTML.

Common mistakes

  • Icon-only buttons (a bag icon with no text or aria-label). The button has a role but no name; see accessible names.
  • Rendering the button client-side only, so the server HTML contains an empty placeholder.
  • Removing the button when out of stock, which makes the page look broken rather than unavailable.

How to fix it on Medusa

Medusa’s DTC starter renders add-to-cart as a named <button> with an onClick handler and no <form>, which scores partial. To pass:

  1. Wrap the button in <form action={addToCartAction}> with hidden inputs for the variant ID and quantity, and make the button type="submit".
  2. Make addToCartAction a server action that calls the starter’s existing addToCart data function, which adds the line item through the Store API (Next.js forms and server actions).
  3. Put the option selectors in the same form (see variant controls).

The Medusa agent-readiness guide walks through this alongside the starter’s other gaps.

Sources

Frequently asked questions

Why can't AI agents click my add-to-cart button?
Browser agents read the accessibility tree, which lists elements by role and name. A clickable div or span has no button role, so the agent may not recognize it as an action, and screenshot agents may not find it reliably either.
Does add-to-cart need to work without JavaScript?
It is the most robust option. A form that posts to the cart works for any client, including agents that fetch HTML or act before scripts finish loading. You can still enhance it with JavaScript.
What should the add-to-cart button show when a product is sold out?
Keep the button in the page, add the disabled attribute and change its text to Sold out, so agents can tell the product exists but is unavailable.

Run your store on a platform built for agentic commerce

Medusa is open-source, headless commerce with a full Store API agents can call and storefronts you control end to end.

Deploy on Medusa Cloud

Open-source commerce with a full Store API, hosted and scaled for you. Your storefront, your data model.

Storefront skills for coding agents

Teach Claude Code, Cursor or Codex to build storefronts with the patterns these checks look for.

npx skills add medusajs/medusa-agent-skills
View the skill on GitHub