SellubDevelopersStorefront embedding

Storefront embedding

Status: Plan / RFC. The sellub-embed package and proxy-fidelity integration are tracked at PLATFORM-STATUS.md.

This document describes the plan for embedding Sellub marketplace surfaces (product listings, checkout, seller dashboard) into 3rd-party host sites such as Proxy Fidelity loyalty pages.

Use case: Proxy Fidelity

Proxy Fidelity is a loyalty/identity platform whose merchants want to:

  1. Show their catalog as part of the loyalty page (browse + redeem).
  2. Let members check out with loyalty discounts applied — without leaving the loyalty experience.
  3. Offer the merchant a light dashboard view (orders, inventory) inside the Proxy Fidelity merchant console.

Three embedding modes

ModeWhat’s embeddedTrust model
A. Headless SDKNone — host queries Sellub API directlyHost owns UI; uses API key
B. iframe widgetsSellub-rendered widgets via <iframe>Sandboxed; postMessage bridge
C. Web component<sellub-checkout> custom elementLoaded from CDN; styled by host

Recommended path: B for checkout (PCI / payment isolation) and A for catalog browsing (best UX, host CSS).

Mode A — Headless via @duabalabs/sellub-client

Host site uses the existing SDK to query Sellub directly.

import { createShopClient } from "@duabalabs/sellub-client";
 
const sellub = createShopClient({
  endpoint: "https://api.sellub.com/shop-api",
  channelToken: PROXY_CHANNEL_TOKEN, // per-merchant Vendure channel
});
 
// Query products
const { products } = await sellub.query(`
  query {
    products(options: { take: 24 }) {
      items { id name slug featuredAsset { preview } variants { priceWithTax } }
    }
  }
`);

Required SDK additions

To make this fully usable for the Proxy Fidelity catalog, sellub-client needs:

  • sellub.delivery.estimates({ destinationCity }) → wraps the deliveryEstimates query (now multi-source aware).
  • sellub.delivery.sources({ sellerId? }) → optional helper for “carrier picker” widgets.
  • Better-typed searchProducts, addToCart, transitionToState helpers (today only query / mutate raw escape hatches plus a few cart ops).

These are tracked under the D7 storefront workstream.

Mode B — <iframe> checkout widget

The host site renders its own catalog (Mode A) but delegates payment to a Sellub-hosted checkout iframe at https://checkout.sellub.com/embed.

<iframe
  src="https://checkout.sellub.com/embed?cart=<cartId>&theme=light"
  width="100%"
  height="640"
  allow="payment *"
></iframe>
 
<script>
  window.addEventListener("message", (e) => {
    if (e.origin !== "https://checkout.sellub.com") return;
    if (e.data.type === "sellub:checkout:complete") {
      window.location.href = "/loyalty/order-success";
    }
  });
</script>

postMessage events emitted by the iframe:

EventPayload
sellub:checkout:ready
sellub:checkout:resize{ height }
sellub:checkout:cart_updated{ totalWithTax, currency }
sellub:checkout:complete{ orderCode }
sellub:checkout:error{ message, code }

Why iframe for checkout?

  • PCI scope isolation — Paystack widget stays inside Sellub’s origin.
  • Channel auth — iframe carries Sellub session cookie scoped to the channel without leaking it to host.
  • Cart consistency — host can’t tamper with line totals.

Mode C — Web component (future)

<script src="https://cdn.sellub.com/embed/v1.js" async></script>
 
<sellub-product-grid channel="proxy_fidelity_acme" take="24"></sellub-product-grid>
<sellub-checkout cart-id="abc123"></sellub-checkout>

This wraps Modes A/B with a CSS-isolated shadow DOM. Lower priority — only needed when host sites can’t run the iframe approach.

Auth & multi-tenancy

Each embedding host gets:

  • A dedicated Vendure channel (proxy_fidelity_<merchant>)
  • A channel token for read queries (safe to expose in client JS)
  • An API key (server-side only) for write operations

Proxy Fidelity’s own auth (loyalty member login) is mapped to a Sellub Customer record using the existing @duabalabs/sellub-types external auth bridge (planned).

Delivery in embedded checkout

The iframe checkout already supports the multi-source delivery system shipped in the latest sellub-server release:

  • One option per (seller, carrier) combination.
  • “via Ghana Post / DHL / your in-house courier” subtitle on each option.
  • ETA per option.

Host sites do not need to know about delivery sources — they’re rendered automatically inside the iframe.

Roadmap

PhaseDeliverableStatus
1Mode A SDK delivery helpers🔴 STUB (packages/sellub-client/src/shop-client.ts)
2Mode B iframe origin (checkout.sellub.com/embed)🔴 STUB (apps/sellub/sellub-storefront)
3postMessage protocol🔴 RFC (this doc)
4Proxy Fidelity adapter package🔴 not started
5Web component wrapper🔴 not started

Track: PLATFORM-STATUS.md under “Embeddable surfaces”.