Buy Now

Open checkout for a selected product or customized purchase while preserving the shopper’s cart.

Buy Now opens checkout for the selected item and quantity. Items and discount codes already in the shopper’s cart stay there. The shopper can enter a discount code in the new checkout. Buy Now does not skip contact verification, delivery details, shipping, payment, or final availability checks.

Add a product button#

Use the buy_now form tag after the shopper has chosen an available variant. The form tag provides the action URL and CSRF token. Show translated button and field labels from your theme’s locale files. Keep the button disabled until required options are selected.

vascula
{% form 'buy_now' %}
  <input type="hidden" name="product_id" value="{{ product.id }}">
  {% if product.selected_variant %}
    <input type="hidden" name="variant_id" value="{{ product.selected_variant.id }}">
  {% endif %}
  <label>
    {{ 'quantity' | t }}
    <input type="number" name="quantity" min="1" step="1" value="1" required>
  </label>
  <button type="submit"{% if product.type == 'variable' and product.selection_complete != true %} disabled{% endif %}>
    {{ 'buy_now' | t }}
  </button>
{% endform %}

To share the selection and quantity fields with Add to Cart, keep one cart_add form and give its second submit button name="purchase_intent" and value="buy_now". JavaScript form handlers must include the clicked submit button’s value. The Tringify storefront bridge handles this automatically.

vascula
<button type="submit" name="purchase_intent" value="buy_now">
  {{ 'buy_now' | t }}
</button>

Use the storefront bridge#

tringify.checkout.buyNow(input) submits the selection and opens the store’s checkout popup on success. Without a popup handler, it follows the checkout URL in the current tab. Use this method on the hosted storefront with its current visitor session.

javascript
const result = await window.tringify.checkout.buyNow({
  product_id: selectedProductId,
  variant_id: selectedVariantId,
  quantity: selectedQuantity,
  client_mutation_id: crypto.randomUUID()
});

if (!result.success) {
  showErrors(result.user_errors);
}

A successful JSON response contains success, checkout_url, user_errors, and refresh_required: false. Display each returned user error’s message rather than its code. Do not clear the cart, add the selected product to it first, or trigger the cart drawer. If you post directly, call tringify.checkout.open(checkout_url) after success.

Retries and checkout access#

Use one client_mutation_id for a purchase attempt. Retry an uncertain network result with the same key and unchanged selection. Generate a new key when the shopper changes the selection or deliberately starts another purchase. Reusing a key with different items, quantities, properties, or artifacts is rejected. The bridge retries a failed network request once with the same key. A checkout URL does not sign in another visitor and must not be treated as a shareable payment link.

An expired checkout asks the shopper to return to the store and choose their items again. It does not restore a Buy Now selection into the regular cart. Availability and prices are checked again when starting a new purchase. Shoppers who already paid should check their order status before trying again.

Buy Now from an app#

Any app surface can use Buy Now when its installed release grants checkout.buy_now to that surface. Call surface.command("checkout.buy_now", input) in response to the shopper choosing Buy Now. Send lines in the same product, variant, quantity, declared properties, and artifact attachment format as cart.add_lines. Products do not have to be customized; include properties and artifacts only when your integration needs them. Required product options, customization, availability, and artifact rules still apply.

javascript
// Create this attempt after the shopper selects the product and quantity.
// Keep it unchanged if the response is lost and the shopper retries.
const attempt = {
  client_mutation_id: crypto.randomUUID(),
  lines: [{
    product_id: selectedProductId,
    variant_id: selectedVariantId,
    quantity: selectedQuantity
  }]
};

async function submitPurchase() {
  const result = await surface.command("checkout.buy_now", attempt);
  if (!result.success) {
    showErrors(result.user_errors);
  }
  return result;
}

The host opens checkout after a successful command. Do not add these lines to the regular cart first, clear the shopper’s cart, or call checkout.begin: checkout.begin opens the existing cart. Custom Products is one example of an app using this action; other apps use the same contract.

client_mutation_id is optional and accepts a nonblank string of up to 128 characters. If omitted, the host creates a key for that command. To safely retry an uncertain result with another command, supply your own key and reuse it with exactly the same lines. Create a new attempt after the shopper changes a variant, quantity, property, or artifact, or deliberately starts another purchase. Disable the purchase button while its request is pending.

Hosted forms#

Buy Now is a Hosted Action. Hosted Vascula CTX provides the product selection used by the form. Do not expose private API credentials in theme code or checkout URLs.