Embeds: product cards, buy buttons and checkout links
Sell from any site with a product card, a buy button or a checkout link, with events your page can listen to.
Build snippets in Settings → Developers → Embeds: pick a product, a type and the look, preview it live, copy.
Want checkout inside your page, in your own layout and brand? See Elements, and try them in the playground.
Product card
An iframe with the cover, title, price, options and a buy button, sized to its content:
<div data-shopfast-embed data-shopfast-product="amalfi-golden-hour-presets"
data-shopfast-store="https://lumenfold.shopfa.st"
data-shopfast-layout="compact"
data-shopfast-cta="Get the presets"
data-shopfast-accent="#6230fa"></div>
<script src="https://lumenfold.shopfa.st/_sf/buy-button.js" async></script>
| Attribute | Values |
|---|---|
data-shopfast-product / data-shopfast-bundle |
The product or bundle handle |
data-shopfast-store |
Your store’s origin (defaults to where the script came from) |
data-shopfast-layout |
card (default), compact, row |
data-shopfast-cta |
Button label, up to 24 characters |
data-shopfast-accent |
#rgb or #rrggbb for the button |
data-shopfast-hide |
Comma list of description, rating, cover |
data-shopfast-width |
Max width in px (default 380) |
Buy button
A link the loader turns into a styled button that opens checkout in a popup (a new tab when popups are blocked, and a plain link without JavaScript):
<a data-shopfast-product="amalfi-golden-hour-presets" data-shopfast-store="https://lumenfold.shopfa.st"
data-shopfast-color="#6230fa">Buy now</a>
<script src="https://lumenfold.shopfa.st/_sf/buy-button.js" async></script>
Add data-shopfast-style="none" to keep your own styles, or data-shopfast-mode="tab" to open a tab instead of a popup.
Checkout link
No script at all: https://lumenfold.shopfa.st/cart?buy=amalfi-golden-hour-presets&qty=1 puts the product in the cart and
opens checkout. Add &variant=var_… for an option.
Checkout always happens on your store’s own origin, where its cookies are first-party, so it works in every browser and keeps buyers’ sessions safe.
Events
The loader re-dispatches what embeds post as DOM events on the embed element. They bubble, so one listener on
document catches every embed:
| Event | detail |
|---|---|
shopfast:ready |
{ height } once the card loaded |
shopfast:resize |
{ height } when the content height changes |
shopfast:checkout |
{ handle, variant } when the buyer starts checkout |
document.addEventListener('shopfast:checkout', (e) => {
analytics.track('Begin checkout', { product: e.detail.handle });
});
Messages from frames are only accepted from the origin the loader framed, and only from that frame.
Allowed sites
By default any site can frame your product cards. List your own origins in Allowed sites to stop others from framing them (the dashboard preview stays allowed). Buy buttons and checkout links are plain links and work anywhere. The embedded checkout is stricter: it opens only on sites in this list.
The same list decides where Elements open. With an empty list, live Elements open only on localhost, the docs playground and the dashboard.
Embedded checkout
The whole checkout, in a modal on your page: the buyer never leaves your site. It is the store’s real checkout (your checkout settings, method order and rules, Fraud Shield, ShopFast Pay limits and the same fees), rendered compact and framed only by your allowed sites.
<button type="button" data-shopfast-checkout="amalfi-golden-hour-presets"
data-shopfast-store="https://lumenfold.shopfa.st"
data-shopfast-theme="dark" data-shopfast-accent="#6230fa">Buy now</button>
<script src="https://lumenfold.shopfa.st/_sf/checkout.js" async></script>
| Attribute | Values |
|---|---|
data-shopfast-checkout |
The product handle (data-shopfast-product works too) |
data-shopfast-variant |
An option id (var_…), optional |
data-shopfast-qty |
Quantity, 1 to 100 |
data-shopfast-store |
Your store’s origin (defaults to where the script came from) |
data-shopfast-theme |
light or dark; leave it out to use your store’s look |
data-shopfast-accent |
#rrggbb for buttons and focus |
A buy button from buy-button.js opens it too with data-shopfast-mode="embed" when checkout.js is on the page.
From JavaScript
const checkout = window.ShopFastCheckout.open({
store: 'https://lumenfold.shopfa.st',
items: [{ product: 'ironveil-pro', variant: 'var_…', quantity: 1 }],
theme: 'dark',
onSuccess: ({ sessionId, orderNumber, totalMinor, currency }) => { showThanks(orderNumber); },
onClose: ({ reason }) => {},
onError: ({ reason }) => {},
});
// checkout.close() closes it from your code.
The same moments bubble as DOM events from the button (or document): shopfast:checkout:ready,
shopfast:checkout:success, shopfast:checkout:close and shopfast:checkout:error (not-allowed when your site is
not in the list). A checkout Fraud Shield refuses shows its message inside the frame. Amounts are in minor units.
How it pays
Card processors’ hosted pages cannot be framed, so for them the frame opens the payment in a secure popup and waits; it updates on its own when the payment confirms. Test payments (the sandbox and store test mode) are approved inside the frame. Either way the order, its receipt email and its delivery are exactly those of a normal checkout.
Security
- Only origins in Allowed sites (and the dashboard preview) may frame it. Each page sends
frame-ancestors <your site>, and an unlisted site gets a short “not available here” page instead of the form. - A framed page has no cookies, so the cart travels in signed form fields bound to your site’s origin; copied to another site, they stop working. Tokens expire after two hours.
- Messages go only to your site’s origin, and the loader accepts messages only from the store origin and from the frame it opened.
- Form posts are accepted only from the frame itself.