Cart, totals and promotions
Render server-owned line items before totals, payments and promotion conditions.
Line items, quantities and removal
Render actual cart lines for products and accessories. Properties or selling plans can produce separate lines for the same variant, so preserve line identity rather than matching product names.
Data and dependencies
- cart.items, quantity, final_line_price and url_to_remove.
- Use the current line key for asynchronous line updates.
Interaction logic
- Reconcile totals and lines after each update.
- Handle zero quantity, removal and an empty cart separately.
Example code · snippets/ww-cart-lines.liquid
{% form 'cart', cart %}
<ul>
{% for item in cart.items %}
<li>
<a href="{{ item.url | escape }}">{{ item.product.title | escape }} — {{ item.variant.title | escape }}</a>
<label for="Quantity-{{ section.id }}-{{ forloop.index }}">Quantity</label>
<input id="Quantity-{{ section.id }}-{{ forloop.index }}" type="number" name="updates[]" value="{{ item.quantity }}" min="0" step="1">
<span>{{ item.final_line_price | money_with_currency }}</span>
<a href="{{ item.url_to_remove | escape }}">Remove this line</a>
</li>
{% endfor %}
</ul>
<p>{{ cart.total_price | money_with_currency }}</p>
<button type="submit" name="update">Update cart</button>
<button type="submit" name="checkout"{% if cart.empty? %} disabled{% endif %}>Checkout</button>
{% endform %}
Acceptance checks
- Test two lines sharing a variant but different properties.
- Check insufficient inventory, quantity correction and keyboard submission.
The fragment targets a full cart page. A drawer needs focus management and feedback; server totals remain authoritative.
Official documentation
Implementation references
WESWOO guides
Totals, payment types and reassurance
Distinguish discounted item totals, shipping/tax calculations and the final checkout result. Payment icons reflect configured types; validate eligibility for the target market at checkout.
Data and dependencies
- cart.total_price with money_with_currency.
- shop.enabled_payment_types and policy pages.
Interaction logic
- Refresh authoritative totals after cart changes.
- Keep reassurance linked to the same policy record.
Example code · snippets/ww-cart-summary.liquid
<dl>
<dt>Items after applied discounts</dt>
<dd>{{ cart.total_price | money_with_currency }}</dd>
</dl>
<p>Shipping, taxes and final eligibility are confirmed at checkout.</p>
{% if shop.shipping_policy != blank %}
<a href="{{ shop.shipping_policy.url | escape }}">Shipping conditions</a>
{% endif %}
{% if shop.refund_policy != blank %}
<a href="{{ shop.refund_policy.url | escape }}">Return conditions</a>
{% endif %}
<ul aria-label="Supported payment types">
{% for type in shop.enabled_payment_types %}
<li>{{ type | payment_type_svg_tag }}</li>
{% endfor %}
</ul>
Acceptance checks
- Compare product, cart and checkout amounts/currencies.
- Check payment, shipping and returns for the target market.
An icon does not establish eligibility for every shopper or that all taxes have been calculated.
Official documentation
WESWOO guides
Promotion cards, copy controls and expiry
Show eligible products, thresholds, currency and validity before the copy button. A successful copy changes feedback only; confirm application through the actual cart or checkout.
Data and dependencies
- Approved code, dates and combination conditions.
- A read-only input, button and role=status feedback.
Interaction logic
- Allow manual selection if clipboard access fails.
- Remove misleading claims when expired or ineligible.
Example code · assets/ww-copy-code.js
export function bindDiscountCopy(button, input, status) {
button.addEventListener('click', async () => {
const value = input.value.trim();
if (!value) return;
try {
await navigator.clipboard.writeText(value);
status.textContent = 'Code copied. Check its conditions at checkout.';
} catch {
input.focus();
input.select();
status.textContent = 'Select and copy the code.';
}
});
}
// Use a read-only text input, a type=button control and a role=status element.
// Copying a code does not apply or validate a discount.
Acceptance checks
- Check clipboard failure, empty codes and repeated activation.
- Validate checkout with eligible and ineligible products.
Copying does not apply a discount. Client-side display values do not establish the final price.
Read it, integrate it, verify it
- Choose a module and confirm the data contract.
- Connect the fragment to the current theme or framework.
- Check real variants, markets and recovery states.
Examples target Shopify Online Store 2.0 themes. Headless has separate data and version boundaries. Integrate fragments with actual fields, theme components and locale files.
Architecture references
Original educational examples with Shopify documentation and pinned upstream references. Follow the applicable license when adopting repository code.
References checked 2026-11-12