CDN integration
Section titled “CDN integration”No bundler, no build step: one script tag gives you the Frak web components and the full SDK on window.
Prerequisites
Section titled “Prerequisites”- A merchant account on the Frak business dashboard with your domain registered. The main domain is registered at sign-up; add subdomains under Allowed Domains.
- Any HTML page you can add a script tag to.
If you have not done that yet, start with the Get started guide.
Which bundle
Section titled “Which bundle”| Bundle | URL | What it is |
|---|---|---|
| Components | https://cdn.jsdelivr.net/npm/@frak-labs/components@latest | ESM. Registers the <frak-*> elements, boots the SDK, and exposes the SDK on window.FrakSetup.core. This is the one you want. |
| Core only | https://cdn.jsdelivr.net/npm/@frak-labs/core-sdk@latest/cdn/bundle.js | IIFE exposing window.FrakSDK. No UI, no auto-boot. Only for a page that drives the SDK entirely by hand. |
The rest of this page uses the components bundle.
1. Set the config, then load the script
Section titled “1. Set the config, then load the script”The loader reads window.FrakSetup.config when it boots, so the config object must exist before the script tag runs.
<head> <!-- 1. Configure Frak --> <script> window.FrakSetup = { config: { metadata: { name: "Your Store", currency: "eur", }, }, }; </script>
<!-- 2. Load the components (registers the elements and boots the SDK) --> <script type="module" src="https://cdn.jsdelivr.net/npm/@frak-labs/components@latest" defer="defer" ></script></head>type="module" is required: the components bundle is ESM.
Config options
Section titled “Config options”| Field | Default | Meaning |
|---|---|---|
env | "prod" | The environment to run against: "prod", "dev", or { wallet, backend }. |
metadata.name | none | Your application name, shown in modals and SSO. |
metadata.merchantId | resolved from your domain | Your merchant ID (UUID) from the dashboard. |
metadata.currency | "eur" | "eur", "usd", or "gbp". |
metadata.lang | browser language | "en" or "fr". |
metadata.logoUrl | none | Logo used by some components. |
metadata.homepageLink | none | Fallback link used by some components. |
domain | window.location.host | Override only if the page host differs from your registered domain. |
customizations.css | none | URL of a stylesheet applied to the modals and components. |
customizations.i18n | none | Inline translation overrides, per locale or flat. |
waitForBackendConfig | true | Wait for the backend configuration before rendering components. |
attribution | none | Default UTM, via, and ref values appended to sharing URLs. |
preload | ["sharing"] | Views preloaded inside the listener iframe. Pass [] to disable. |
See Configuration and FrakSetup for the full reference.
2. Drop in the components
Section titled “2. Drop in the components”The loader watches the DOM, so an element added at any time registers itself:
<body> <frak-banner></frak-banner> <frak-button-share classname="button"></frak-button-share></body>Every element and attribute is documented in the components reference.
3. Call the SDK from your own code
Section titled “3. Call the SDK from your own code”Once booted, the SDK publishes two things:
window.FrakSetup.client, the client instancewindow.FrakSetup.core, every SDK function and action
The client is created asynchronously, so wait for the frak:client event before using it:
<script> function waitForClient() { if (window.FrakSetup?.client) return Promise.resolve(window.FrakSetup.client); return new Promise((resolve) => { window.addEventListener( "frak:client", () => resolve(window.FrakSetup.client), { once: true } ); }); }
(async () => { const client = await waitForClient();
// Watch the wallet status await window.FrakSetup.core.watchWalletStatus(client, (status) => { console.log(status.key === "connected" ? status.wallet : "not connected"); });
// Open a modal await window.FrakSetup.core.displayModal(client, { steps: { login: {}, final: { action: { key: "sharing" } }, }, }); })();</script>Track a purchase
Section titled “Track a purchase”trackPurchaseStatus is the exception: it takes no client, so you can call it as soon as the SDK is loaded.
<script> window.addEventListener("frak:client", () => { window.FrakSetup.core.trackPurchaseStatus({ customerId: "cust_123", orderId: "order_456", token: "a-unique-order-token", }); });</script>Rewards are only released once your backend confirms the order with a signed webhook. See Validate purchases from your backend.
Events
Section titled “Events”| Event | Target | Detail | Fired when |
|---|---|---|---|
frak:client | window | none | The client is ready, window.FrakSetup.client is set |
frak:config | window | the resolved config | The backend configuration is resolved or refreshed |
frak:referral-success | window | none | An inbound referral was processed successfully |
The share query parameter
Section titled “The share query parameter”The loader also handles ?frakAction=share on page load, with optional link, products, and placement parameters. It opens the sharing flow and then strips those parameters from the URL. That is how a link out of an email or a QR code can open the share sheet directly.
Advanced: the core-only bundle
Section titled “Advanced: the core-only bundle”If you do not want the components at all, load the core bundle and create the client yourself:
<script src="https://cdn.jsdelivr.net/npm/@frak-labs/core-sdk@latest/cdn/bundle.js"></script><script> let clientPromise;
function getClient() { // Call setupClient once. Each call recreates the listener iframe. clientPromise ??= FrakSDK.setupClient({ config: { metadata: { name: "Your Store" } }, }); return clientPromise; }
(async () => { const client = await getClient(); if (!client) return; await FrakSDK.watchWalletStatus(client, console.log); })();</script>window.FrakSDK carries the same functions and actions as window.FrakSetup.core. It exists only for this bundle: the components bundle is ESM and exposes no global.