Website embed
Show your products on any website with two lines of HTML — mockups, color and size pickers, your retail or points price — and hand the customer's pick to your own checkout or points redemption.
The embed shows your active products on your own website: mockups, the options of the enabled variants, and the price your customers pay — your retail price or its points price. It never shows our wholesale price and carries no branding of ours. There is no checkout on our side: when a customer picks a variant, your page receives an event and your checkout (or points redemption) takes over.
1. Create a publishable key
In Developers → Embed, create a publishable key and list the websites that will use it — exact origins such as https://shop.example.com (add https://www.shop.example.com separately; http:// only for localhost). Publishable keys (pk_live_…, pk_test_…) are safe to put in your HTML: they only read your active products, only from those websites, and the API refuses them for everything else. Orders always use a secret key (sk_…) on your server.
2. Add the embed
<!-- One product -->
<div data-swaglists-product="prod_01k8x2c4v6b8n0m2q4w6e8r0t2"></div>
<!-- Or a grid of all your active products (optionally only those with a tag) -->
<div data-swaglists-products data-tag="rewards"></div>
<script src="https://swaglists.com/embed.js" data-key="pk_live_…" async></script>Load the script once per page; it renders every matching element, including ones added later (single-page apps). /embed.js is the current version; pin /embed/v1.js if you prefer. In the grid, a click shows the product in place — or set data-product-url="/products/{id}" to link to your own product pages instead.
3. Receive the customer's pick
document.addEventListener("swaglists:select", async (e) => {
const { product_variant_id, sku, quantity, retail_price, retail_points } = e.detail;
// Add to your cart, or deduct retail_points from the customer's balance, then let your
// server create the order with your secret key: POST /v1/orders
// { items: [{ product_variant_id, quantity }], recipient: { … } }
});The event bubbles from the embed element. e.detail contains product_id, product_variant_id, sku, title, variant_title, options, quantity, retail_price (cents), retail_points, currency and image_url. Instead of listening, you can name a global function: data-on-select="addToCart". swaglists:ready fires when a product rendered, swaglists:error when it could not load (the reason is also logged in the browser console).
Always re-check the price on your server from GET /product_variants before charging — anything in a browser can be changed by the customer.
Styling
Set any of these on the embed element (or once on the script tag):
| Attribute | Default | |
|---|---|---|
data-price |
auto |
auto (points when your account shows points prices), money, points, both |
data-points-label |
points |
e.g. pts or your program's name |
data-button-label |
Add to cart |
e.g. Redeem |
data-sold-out-label, data-from-label, data-back-label, data-more-label |
other labels | |
data-accent, data-accent-text |
#111827, #ffffff |
button and selection colors |
data-text-color, data-muted-color, data-background, data-surface, data-border-color |
colors | |
data-font |
inherit |
your site's font by default |
data-radius |
10px |
corner radius |
data-card-width |
220px |
grid card width |
data-quantity |
true |
false hides the quantity field; data-max-quantity (default 10) |
data-description |
true |
false hides the description |
The embed renders in a shadow root, so your page's CSS doesn't change it and its CSS doesn't leak into your page. window.SwaglistsEmbed.refresh() re-renders every embed (for example after a product.prices_changed webhook told your site that prices moved).
Content Security Policy
If your site sends a CSP, allow https://swaglists.com in script-src, connect-src and img-src.
Errors
The embed endpoints answer { "error": { "code", "message" } }: invalid_key (401, unknown or revoked key), origin_not_allowed (403, add the website under Developers → Embed), account_inactive (403), not_found (404, the product is a draft, archived or not yours) and rate_limited (429).