Static HTML/JS
Static HTML/JS checkout for product pages
Add the public script once, authorize the storefront domain in WireGum Storefront, then place data attributes wherever the CMS renders a product page.
1. Authorize the domain
Add the live website, local, or staging origin in Storefront. Browser requests from other origins cannot fetch products or create Checkout Sessions for the workspace.
2. Install the script
<script
async
src="https://wiregum.com/api/storefront/widget"
data-wiregum-organization="workspace-slug"
></script>After checkout the customer returns to the storefront origin. Add optional data-wiregum-success-path and data-wiregum-cancel-path attributes to land on specific pages of the site instead.
<script
async
src="https://wiregum.com/api/storefront/widget"
data-wiregum-organization="workspace-slug"
data-wiregum-success-path="/thank-you"
data-wiregum-cancel-path="/cart"
></script>CMS templates that prefer emitting JSON can put the same settings in a data-wiregum-config element instead of script attributes. Attributes on the script tag win when both are present.
<script type="application/json" data-wiregum-config>
{
"organization": "workspace-slug",
"locale": "it",
"successPath": "/thank-you",
"cancelPath": "/cart"
}
</script>
<script async src="https://wiregum.com/api/storefront/widget"></script>3. Add a buy box
<div data-wiregum-product="wg_product_ref" lang="it"></div>Custom markup
<div data-wiregum-product="wg_product_ref" lang="it">
<div data-wiregum-price></div>
<div data-wiregum-variant-selector></div>
<input data-wiregum-quantity type="number" min="1" value="1">
<button data-wiregum-add-to-cart type="button">Add to cart</button>
</div>
<div data-wiregum-cart-count></div>
<div data-wiregum-country-selector></div>
<div data-wiregum-cart></div>Generated cart controls use data attributes only, so the CMS theme can style them with vanilla CSS, Tailwind classes on the parent, or framework-specific wrappers.
<div data-wiregum-cart>
<!-- WireGum renders data attributes only:
data-wiregum-cart-item
data-wiregum-cart-item-name
data-wiregum-cart-item-price
data-wiregum-cart-decrement
data-wiregum-cart-item-quantity
data-wiregum-cart-increment
data-wiregum-cart-remove
data-wiregum-cart-total
data-wiregum-checkout
-->
</div>Custom cart markup
An empty data-wiregum-cart element renders the default cart. When the element ships its own children, WireGum fills them instead of replacing them: put a single item template inside a data-wiregum-cart-items wrapper and it is cloned for every cart line, with names, quantities, prices, and the quantity controls wired up. The hidden attribute on the template avoids a flash before the first render, and the element marked data-wiregum-cart-empty is shown only while the cart is empty.
<div data-wiregum-cart>
<p data-wiregum-cart-empty>Your cart is empty.</p>
<ul data-wiregum-cart-items>
<!-- One item template: WireGum clones it for every cart line. -->
<li data-wiregum-cart-item hidden>
<span data-wiregum-cart-item-name></span>
<button data-wiregum-cart-decrement type="button">−</button>
<span data-wiregum-cart-item-quantity></span>
<button data-wiregum-cart-increment type="button">+</button>
<span data-wiregum-cart-item-subtotal></span>
<button data-wiregum-cart-remove type="button">Remove</button>
</li>
</ul>
<p>Total: <span data-wiregum-cart-total></span></p>
<div data-wiregum-country-selector></div>
<button data-wiregum-checkout type="button">Checkout</button>
</div>Product grid add-to-cart buttons
A grid can render one button per product before the site has internal product pages. Put data-wiregum-product on the card or directly on the button. WireGum fetches every product reference, binds each button, and adds the default or selected variant to the shared cart. Use the WireGum public ID, for example wg_..., when the integration should survive slug changes. Product slugs are still supported.
<section class="product-grid" lang="it">
<article data-wiregum-product="wg_12ab34cd56">
<h2>Linen tote</h2>
<div data-wiregum-price></div>
<button data-wiregum-add-to-cart type="button">Add to cart</button>
</article>
<article data-wiregum-product="wg_78ef90ab12">
<h2>Cotton cap</h2>
<div data-wiregum-price></div>
<button data-wiregum-add-to-cart type="button">Add to cart</button>
</article>
<button
data-wiregum-product="wg_34cd56ef78"
data-wiregum-add-to-cart
type="button"
>
Add scarf
</button>
</section>
<div data-wiregum-cart-count></div>
<div data-wiregum-country-selector></div>
<div data-wiregum-cart></div>For products with variants, keep a variant selector in the card or pass a fixed data-wiregum-variant public variant ID on the button. The shipping country selector should remain visible when shipping rates depend on country.
Loading states and errors
The widget reports its lifecycle on the root element as html[data-wiregum-status]: loading while products are fetched, ready once the page is hydrated, and unavailable when the workspace cannot be reached from this origin. Use it for CSS skeletons and fallback notes, no extra JavaScript needed.
/* One shimmer bar while the widget loads. */
html[data-wiregum-status="loading"] [data-wiregum-variant-selector]:empty {
min-height: 2.9rem;
background: #f3f1ef;
}
/* Shown only when this origin cannot reach the workspace. */
html[data-wiregum-status="unavailable"] .storefront-offline-note {
display: block;
}Errors never replace markup the site authored. Elements the widget owns, empty auto buy boxes, show the message inline; everything else keeps its content while data-wiregum-error is set on the product element and add-to-cart and checkout buttons are disabled with the reason as their title. Fallback prices and product content stay visible, so an unreachable workspace degrades to a read-only page instead of a broken one.
The same lifecycle is available as events for custom behavior.
window.addEventListener("wiregum:ready", () => {
// Products hydrated, cart rendered.
});
window.addEventListener("wiregum:unavailable", (event) => {
console.warn(event.detail.message);
});
window.addEventListener("wiregum:cart:updated", (event) => {
// event.detail is the current cart.
});API contract
Use the same public endpoints if a site wants to build its own UI. The request origin must still match an authorized live, local, or staging domain.
GET https://wiregum.com/api/storefront/products?organization=workspace-slug&products=wg_product_refStatic site generators fetching products at build time, and server-rendered pages, send no browser origin. Generate a read-only API key in Storefront and pass it as a bearer token. The key only reads products: checkout sessions still require a browser request from an authorized domain.
# Build pipelines and server-rendered pages have no browser origin:
# authenticate with the workspace API key from WireGum Storefront instead.
curl "https://wiregum.com/api/storefront/products?products=wg_product_ref" \
-H "Authorization: Bearer wg_pk_your_key"POST https://wiregum.com/api/storefront/checkout
Content-Type: application/json
{
"organizationSlug": "workspace-slug",
"locale": "it",
"shippingCountry": "IT",
"successPath": "/thank-you",
"cancelPath": "/cart",
"items": [
{ "variantId": "wg_variant_ref", "quantity": 1 }
]
}successPath and cancelPath are resolved against the storefront origin that created the checkout. Sites that need full control can send absolute successUrl and cancelUrl values instead, as long as they point to a domain authorized in WireGum Storefront. Stripe replaces a literal {CHECKOUT_SESSION_ID} placeholder in the success URL.
Stability and versioning
The current storefront contract is v0.1. The public widget exposes window.WireGum.version as 0.3.1.
window.WireGum methods, product payload fields used by the widget, and checkout request fields.Additive changes can ship on the same contract. Breaking changes should use a new major contract and keep the previous one available during a migration window.Use WireGum public product and variant IDs, not editable slugs or internal database IDs, when CMS integrations must remain stable over time.