Product contexts include {{ query:products }}, {{ query:product }}, resources/views/single-product.php, and product-aware WooCommerce overrides.
Smallest Add-To-Cart Form#
{{ query:products limit="4" }} <article> <h2>{{ title }}</h2> <div>{{ price_html }}</div> {{ cart:add }} <button type="submit">Add to cart</button> {{ /cart:add }} </article>{{ /query:products }}TemplateX compiles {{ cart:add }} to a WooCommerce add-to-cart form for the current product. The generated form includes the product ID and a default quantity of 1.
Use It On Single Products#
Single product templates are already product contexts:
<main> {{ notices }} <h1>{{ title }}</h1> <div>{{ price_html }}</div> {{ if purchasable }} {{ cart:add class="product-purchase" }} <button type="submit">Add to cart</button> {{ /cart:add }} {{ /if }}</main>{{ notices }} is a value tag. It prints WooCommerce notices and does not have a closing tag.
Open The Mini-Cart#
Add open_cart when a successful add-to-cart action should open the first available mini-cart drawer:
{{ cart:add class="product-purchase" open_cart }} <button type="submit">Add to cart</button>{{ /cart:add }}Bare option names are shorthand for true, so open_cart and open_cart="true" are equivalent.
Keep Variation URLs Shareable#
Add variation_url when selected variation options should update the current URL:
{{ cart:add variation_url }} {{ variation:pills for="size" active_class="bg-black text-white" }} {{ label }} {{ /variation:pills }} <button type="submit">Add to cart</button>{{ /cart:add }}TemplateX writes WooCommerce-style query parameters such as ?variation_id=123&attribute_pa_size=large. Opening that URL again selects the matching variation before the visitor adds it to the cart.
Variable Products#
For variable products, place variation controls inside {{ cart:add }}:
{{ cart:add }} <p>Size</p> {{ variation:pills for="size" class="border px-4 py-2" active_class="bg-black text-white" unavailable_class="opacity-40 cursor-not-allowed" }} {{ label }} {{ /variation:pills }} <p>Color</p> {{ variation:select for="color" class="border px-3 py-2" placeholder="Choose color" }} <button type="submit">Add to cart</button>{{ /cart:add }}TemplateX handles the WooCommerce input names, submitted values, required selection, selected variation ID, active state, price updates, and optional variation URLs.
Out-of-stock or otherwise unavailable pill and radio choices are non-clickable by default. Use unavailable_class to style that state.
For product cards with more variation detail, see Product Loop With Variations.
Stock And Purchase Checks#
You can decide when to show a form:
{{ query:products limit="4" }} <article> <h2>{{ title }}</h2> <div>{{ price_html }}</div> {{ if in_stock && purchasable }} {{ cart:add }} <button type="submit">Add to cart</button> {{ /cart:add }} {{ else }} <span>Unavailable</span> {{ /if }} </article>{{ /query:products }}WooCommerce still performs the final validation. The conditional only controls what your template shows.
Runtime Behavior#
With JavaScript enabled, the generated add-to-cart form submits through WooCommerce's AJAX add-to-cart endpoint and refreshes cart count, cart item content, and cart values such as {{ total }}.
On success, TemplateX dispatches a bubbling cart:added event from the form after cart content has refreshed:
document.addEventListener('cart:added', function (event) { console.log(event.detail);});If WooCommerce rejects the request because stock, purchasability, or variation validation changed after the page rendered, TemplateX dispatches a bubbling cart:error event instead. When WooCommerce returns a product URL, TemplateX follows that URL so the native WooCommerce notice can render near the product.
Without JavaScript, the form still submits as a normal WooCommerce add-to-cart request.
Avoid These Patterns#
- Do not use
{{ cart:add }}outside a product context. - Do not put
{{ cart:add }}inside another form. - Do not put variation controls outside
{{ cart:add }}. - Do not use a plain link when the action changes cart state. Use a real button inside
{{ cart:add }}.