Skip to content

For a custom-built site, adding Frak takes two parts:

  1. 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.
  2. Validate purchases from your backend. Confirm real orders with a signed webhook, so rewards only go out on genuine sales.

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.

ComponentWhere it goesWhat it does
<frak-button-share>Product page, homepageLets customers share your store and earn rewards
<frak-banner>Top of the pageWelcomes referred visitors
<frak-post-purchase>Order confirmation pagePrompts a share right after checkout, and tracks the order

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.

index.html
<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>

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>

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>

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.

  1. The page registers the order. The post-purchase card (or trackPurchaseStatus) sends customerId, orderId, and token so Frak starts listening for that order.

  2. 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.

  3. Frak triggers the reward. Once the signature checks out and the status is confirmed, Frak sends the PurchaseCompleted interaction, 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",
});

See the Purchase webhook reference for the full payload (including line items) and the track purchase endpoint for the page-side call.