Embeds

Put a product's order form, or any store page, on another website. The frame sizes itself, follows the site's theme and tells the site about each order.

An embed shows a product or a store page inside an <iframe> on any other website: a blog, a WordPress or Blogger site, a link-in-bio page. The shopper orders without leaving that site.

Helium serves every embed. It owns the frame (sizing, theme, links, framing rules, the order message); the store's template and the merchant own what is inside.

Add one to a site

Two lines, on any page:

<feeef-embed product-id="your-product" theme-mode="auto"></feeef-embed>
<script src="https://your-store.feeef.store/_h/embed.js" async></script>

embed.js defines the <feeef-embed> element: a frame that is always exactly as tall as its content, with no scroll bar inside. It is about 2 KB gzipped, has no dependencies, and works for elements added later (single-page sites, page builders). product-id takes the product's id or its slug; the store is the one that served the script.

Without the script, a plain frame works too; it keeps a fixed height and scrolls inside:

<iframe src="https://your-store.feeef.store/embed/products/your-product"
        style="width:100%;height:640px;border:0" allow="geolocation"></iframe>

What can be embedded

URLShows
/embed/products/<slug>The product's order form: its options, offers and add-ons, the customer fields, the summary and the order button, across the whole width, then a small "Protected by feeef" line
/embed/pages/<slug>A published store page (an offer, a product landing page, a banner)

No gallery, title or price by default: the site around the embed already shows the product. An unknown product or page, or a store that turned embeds off, shows the not-found page.

After an order, the thanks page opens inside the frame (/embed/thanks); the site's own page never changes.

Attributes

AttributeValuesDefault
product-ida product's id or slugshows that product's order form
pagea store page's path (summer-offer)shows that page instead
storethe store's host (your-store.feeef.store, or its own domain)the store that served embed.js; set it when one page shows products from several stores
srca full /embed/... URLinstead of the three above
theme-modelight, dark, autoauto: follows the site (its data-theme, a dark class, color-scheme, then the visitor's system) and keeps following when the site switches
variantthe name of a first-level option (Red)none; preselects that option
quantity1–99none; preselects the quantity
backgroundsurface, transparentsurface; transparent lets the site's background show through
heightpixels600; the height before the frame reports its own
labeltextthe page title; the frame's accessible name

Changing theme-mode or variant updates the frame in place; changing any other attribute loads the new embed. On a plain frame, theme, bg, variant and qty are query parameters.

Listen to orders

Every message from the frame is a DOM event on its container, so the site can count a sale in its own analytics or ad pixel:

js
document.addEventListener('feeef:order', (event) => {
  const { orderId, total, currency, items } = event.detail
  fbq('track', 'Purchase', { value: total, currency })
})
EventWhendetail
feeef:readyThe frame's page is ready (again after each page in the frame){ height, title }
feeef:resizeIts content height changed{ height }
feeef:orderAn order was saved{ orderId, total, currency, items: [{ productId, quantity, price }] }
feeef:navigateA link left the embed (it opens in a new tab){ url }
feeef:overlayA full-screen view (photos, a dialog) opened or closed; the frame covers the page meanwhile{ open }

Only the page that loaded embed.js receives order and navigate: the frame sends them to the origin that greeted it, never to *. Bot orders caught by the store's protection never send order.

JavaScript API

js
const embed = Feeef.embed(document.querySelector('#buy'), {
  url: 'https://your-store.feeef.store/embed/products/your-product',
  theme: 'auto',
  onReady({ height, title }) {},
  onOrder({ orderId, total, currency, items }) {},
  onResize(height) {},
  onNavigate(url) {},
  onOverlay(open) {},
})

embed.setTheme('dark')
embed.setVariant('Red')
embed.destroy()

Which sites may show your embeds

By default any site may. A store can turn embeds off or limit them to its own sites in configs.embed:

{ "configs": { "embed": { "enabled": true, "allowedHosts": ["blog.example.com", "*.myshop.dz"] } } }

Up to 20 hostnames; *. covers subdomains. With a list, browsers refuse to show the embed anywhere else (frame-ancestors). Every other page of a store (home, products, checkout) can only be framed by the store itself.

Orders from embeds

  • They go through the normal checkout, so Order protection treats them as orders from the store's own page.
  • Their source is embed, and metadata.attribution.embedHost names the site that showed the embed: merchants see which sites sell. UTM tags on the embed URL are kept like on any page.
  • The embed is the store's own order form, so the store's ad pixels (Meta, TikTok, Snapchat) see the visit, the lead and the purchase like on the store, and server-side conversions go out too, deduplicated with the browser events. Some browsers limit pixel cookies inside frames; the server-side conversions cover that. The site can also fire its own pixel from feeef:order.

Design the embed in a template

Embeds render in the embed layout: the template's app/layouts/embed.tsx when it ships one, otherwise its default layout with every slot left empty (its styles, fonts and theme stay; its header and footer go). Style embeds with html[data-embed]:

html[data-embed] .my-hero { display: none; }
html[data-embed][data-theme="dark"] .my-card { background: #111; }

The "Protected by feeef" line is the core block core/feeef-credit: any page can place it, and a template's own embed design can move it or leave it out.