Add Frak to a custom website
Section titled “Add Frak to a custom website”For a custom-built site, adding Frak takes two parts:
- Add the Frak components to your site. Load Frak, set one config object, and drop in the share button, the welcome banner, and the post-purchase card. Pick the setup that matches your stack below.
- Validate purchases from your backend. Confirm real orders with a signed webhook, so rewards only go out on genuine sales.
The components
Section titled “The components”All three components are framework-agnostic web components, so they work the same whether you write plain HTML, use a bundler, or build with React.
| Component | Where it goes | What it does |
|---|---|---|
<frak-button-share> | Product page, homepage | Lets customers share your store and earn rewards |
<frak-banner> | Top of the page | Welcomes referred visitors |
<frak-post-purchase> | Order confirmation page | Prompts a share right after checkout, and tracks the order |
1. Add Frak to your site
Section titled “1. Add Frak to your site”Load and configure Frak
Section titled “Load and configure Frak”Add this to the <head> of your pages. The config object is read by Frak when it loads, so set it before the script tag.
<head> <!-- 1. Configure Frak (domain defaults to the current host) --> <script> window.FrakSetup = { config: { metadata: { name: "Your Store", currency: "eur", }, }, }; </script>
<!-- 2. Avoid a flash of unstyled elements while the script loads --> <style> frak-button-share:not(:defined), frak-banner:not(:defined), frak-post-purchase:not(:defined) { display: none !important; } </style>
<!-- 3. Load the components (auto-registers them and boots the SDK) --> <script type="module" src="https://cdn.jsdelivr.net/npm/@frak-labs/components@latest" defer="defer" ></script></head>Add the components
Section titled “Add the components”Place the banner near the top of your <body>, and the share button wherever you want customers to share:
<body> <!-- Welcomes referred visitors --> <frak-banner></frak-banner>
<!-- Inherits your theme's .button styles via classname --> <frak-button-share classname="button"></frak-button-share></body>Track the purchase
Section titled “Track the purchase”On your order confirmation page, add the post-purchase card with your order details. When customer-id, order-id, and token are all present, the card also registers the order with Frak automatically:
<frak-post-purchase customer-id="cust_123" order-id="order_456" token="a-unique-order-token"></frak-post-purchase>If you do not want to show the card, register the order directly instead. The action becomes available once Frak is ready:
<script> window.addEventListener("frak:client", () => { window.FrakSetup.core.trackPurchaseStatus({ customerId: "cust_123", orderId: "order_456", token: "a-unique-order-token", }); });</script>Install
Section titled “Install”npm install @frak-labs/components @frak-labs/core-sdkConfigure Frak
Section titled “Configure Frak”Set the config in its own module so it runs first:
import type { FrakWalletSdkConfig } from "@frak-labs/core-sdk";
declare global { interface Window { FrakSetup: { config?: FrakWalletSdkConfig }; }}
window.FrakSetup = { config: { metadata: { name: "Your Store", currency: "eur", }, },};Register the components
Section titled “Register the components”Import your config module first, then import each component you use. Importing a component registers its custom element and boots the SDK from window.FrakSetup.config:
import "./frak-setup";import "@frak-labs/components/banner";import "@frak-labs/components/buttonShare";import "@frak-labs/components/postPurchase";Then drop the elements into your markup, exactly like the HTML tab:
<frak-banner></frak-banner><frak-button-share classname="button"></frak-button-share><frak-post-purchase customer-id="cust_123" order-id="order_456" token="a-unique-order-token"></frak-post-purchase>Track the purchase
Section titled “Track the purchase”The post-purchase card tracks the order automatically when given all three attributes. To track without rendering the card, call the action directly:
import { trackPurchaseStatus } from "@frak-labs/core-sdk/actions";
await trackPurchaseStatus({ customerId: "cust_123", orderId: "order_456", token: "a-unique-order-token",});The visual components are the same web components, used inside JSX. Install them and (optionally) @frak-labs/core-sdk for direct action calls:
npm install @frak-labs/components @frak-labs/core-sdkConfigure and register
Section titled “Configure and register”Set the config in its own module, then import it (and the components) before you render your app:
import type { FrakWalletSdkConfig } from "@frak-labs/core-sdk";
declare global { interface Window { FrakSetup: { config?: FrakWalletSdkConfig }; }}
window.FrakSetup = { config: { metadata: { name: "Your Store", currency: "eur", }, },};import "./frak-setup";import "@frak-labs/components/banner";import "@frak-labs/components/buttonShare";import "@frak-labs/components/postPurchase";
import { createRoot } from "react-dom/client";import { App } from "./App";
createRoot(document.getElementById("root")!).render(<App />);Use the components in JSX
Section titled “Use the components in JSX”export function App() { return ( <> <frak-banner /> <frak-button-share classname="button" />
{/* On your order confirmation route */} <frak-post-purchase customer-id="cust_123" order-id="order_456" token="a-unique-order-token" /> </> );}The post-purchase card tracks the order automatically. To track without the card, call trackPurchaseStatus from @frak-labs/core-sdk/actions after the order is placed.
2. Validate purchases from your backend
Section titled “2. Validate purchases from your backend”Tracking on the page tells Frak an order might be coming. Rewards only fire once your backend confirms the order is real with a signed webhook. This keeps rewards tied to genuine, paid sales.
-
The page registers the order. The post-purchase card (or
trackPurchaseStatus) sendscustomerId,orderId, andtokenso Frak starts listening for that order. -
Your backend confirms it. When the order is paid (or refunded, cancelled), your server sends a webhook to Frak with the same identifiers and an HMAC signature.
-
Frak triggers the reward. Once the signature checks out and the status is
confirmed, Frak sends thePurchaseCompletedinteraction, which can pay out rewards based on your active campaigns.
Your webhook URL and signing secret are in the business dashboard, under the Purchase Tracker section of your merchant. Sign the entire request body with HMAC SHA-256 and send it in the x-hmac-sha256 header.
import crypto from "node:crypto";
async function sendPurchaseWebhook(order: { id: string; customerId: string; status: "pending" | "confirmed" | "cancelled" | "refunded"; token: string; currency?: string; totalPrice?: string;}) { const body = JSON.stringify(order); const hmac = crypto .createHmac("sha256", process.env.FRAK_WEBHOOK_SECRET) .update(body) .digest("hex");
await fetch(process.env.FRAK_WEBHOOK_URL, { method: "POST", headers: { "Content-Type": "application/json", "x-hmac-sha256": hmac, // Use "true" while testing, "false" in production "x-test": "false", }, body, });}
await sendPurchaseWebhook({ id: "order_456", customerId: "cust_123", status: "confirmed", token: "a-unique-order-token", currency: "EUR", totalPrice: "99.99",});function sendPurchaseWebhook(array $order): void { $url = getenv('FRAK_WEBHOOK_URL'); $secret = getenv('FRAK_WEBHOOK_SECRET');
$body = json_encode($order); $hmac = hash_hmac('sha256', $body, $secret);
$ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_POSTFIELDS => $body, CURLOPT_HTTPHEADER => [ 'Content-Type: application/json', 'x-hmac-sha256: ' . $hmac, 'x-test: false', // "true" while testing ], ]); curl_exec($ch); curl_close($ch);}
sendPurchaseWebhook([ 'id' => 'order_456', 'customerId' => 'cust_123', 'status' => 'confirmed', 'token' => 'a-unique-order-token', 'currency' => 'EUR', 'totalPrice' => '99.99',]);See the Purchase webhook reference for the full payload (including line items) and the track purchase endpoint for the page-side call.