Referral Widget
Embed the Referral Widget, sign its short-lived token on your backend, and configure its design in the Console.
The Referral Widget is a button and a panel that you add to your product. It shows a signed-in customer their referral link, a copy button, and share buttons. When the customer has cash Rewards that RefRef pays out, it also shows their payout amounts and collects their PayPal address.
The Widget shows link sharing only. It does not show a referral history or a Reward list.
How it works
- Your backend enrolls the customer in a referral Program (
POST /v1/enrollments) and creates their code (POST /v1/referral-codes), or you enroll them in the Console. - Your backend signs a short-lived Widget token for the signed-in customer with the Project's client secret.
- The page loads the Widget script and calls
window.RefRef.initwith the token. - The Widget calls
POST /v1/widget/init. RefRef finds the customer named by the token, or creates it, and returns its link in the Program.
The Widget renders only for an enrolled customer who has a referral code. Widget initialization never enrolls a customer, creates a code, or records an Event.
1. Sign the token on your backend
Get the Client secret in the Console: open the Project, then Developers → Secrets (owners and admins only). The Sandbox and Live Projects have different secrets. Keep the secret on your server. If it leaks, rotate it: the old secret stops working at once.
The token is a JWT with these rules:
| Part | Value |
|---|---|
| Algorithm and header | HS256, with typ: "refref-widget+jwt" |
sub | Your ID of the customer: the same externalId that your backend sends |
participantKind | individual or group |
projectId and iss | The Project ID, in both claims |
aud | refref-widget |
scope | widget:read widget:payout for the full Widget, or widget:read to view only |
iat, exp | At most 15 minutes apart |
widget:read lets the Widget show the link and the payout amounts. widget:payout also lets the customer save their payout details. RefRef drops other claims.
This Node.js example uses the jose library:
import { SignJWT } from "jose";
export async function widgetToken(userId: string) {
const projectId = process.env.REFREF_PROJECT_ID!;
return new SignJWT({
projectId,
participantKind: "individual",
scope: "widget:read widget:payout",
})
.setProtectedHeader({ alg: "HS256", typ: "refref-widget+jwt" })
.setIssuer(projectId)
.setAudience("refref-widget")
.setSubject(userId)
.setIssuedAt()
.setExpirationTime("15m")
.sign(new TextEncoder().encode(process.env.REFREF_CLIENT_SECRET!));
}Serve the token from an authenticated route of your app, for example GET /refref/widget-token. Sign a token only for the customer of the current session.
For a company account, sign the token with participantKind: "group" and the company's ID as sub. Every person to whom you give that token sees the company's link.
2. Load the Widget
<script src="https://assets.refref.ai/widget.v1.js" defer></script>
<script>
const getToken = () =>
fetch("/refref/widget-token").then((response) => response.text());
window.RefRef = window.RefRef || [];
getToken().then((token) =>
window.RefRef.push([
"init",
{
projectId: "YOUR_PROJECT_ID",
apiUrl: "https://api.refref.ai",
token,
getToken,
},
]),
);
</script>The array form queues the call until the script loads. After the script loads, you can also call window.RefRef.init({ ... }) directly; it returns a promise.
| Option | Required | Meaning |
|---|---|---|
projectId | Yes | The Project ID. It must be the Project of the token. |
token | Yes | The signed Widget token |
getToken | No | A function that returns a new token. On a 401 answer, the Widget calls it once and tries again. |
programId | No | The referral Program to show. Required when the customer is enrolled in several referral Programs. |
apiUrl | No | The RefRef API, https://api.refref.ai |
demo | No | true shows example content and makes no request. Use it to preview the design. |
A Content Security Policy must allow https://assets.refref.ai in script-src and the API host in connect-src.
Control the panel
| Call | Effect |
|---|---|
window.RefRef.open() | Opens the panel |
window.RefRef.close() | Closes the panel |
window.RefRef.toggle() | Opens or closes the panel |
window.RefRef.isOpen | true when the panel is open |
window.RefRef.setConfig({…}) | Changes design fields on this page, for example triggerText |
window.RefRef.getConfig() | Returns the current design |
The Widget emits no events.
Design the Widget
Set the design for each Program on its Design tab in the Console. RefRef sends it to the Widget at init. The Design tab sets the colors through cssVariables.
| Field | Values | Default |
|---|---|---|
position | bottom-right, bottom-left, top-right, top-left | bottom-right |
triggerText | The button text | Refer & Earn |
icon | gift, heart, star, zap | gift |
title, subtitle | The panel heading and the text below it | Title: Invite your friends |
logoUrl | An image URL | None |
shareMessage | The text of a share; {productName} is replaced | Join me on {productName} and get a reward! |
enabledPlatforms | facebook, twitter (X), linkedin, whatsapp, email, instagram, telegram | All on except Instagram and Telegram |
cssVariables | CSS custom properties for the Widget's colors, radius, and font | The Widget theme |
The Widget renders in a shadow root, so your page's CSS does not reach it. Change its look with cssVariables. Instagram has no share URL: its button copies the message and the link.
What the customer sees
| Init status | When | The Widget shows |
|---|---|---|
enrolled | The customer has an open enrollment in an active referral Program | The button and panel |
not_enrolled | The customer has no open enrollment in the Program, or is new | Nothing |
not_applicable | programId names an affiliate or loyalty Program | Nothing |
The panel shows one referral link, https://r.refref.ai/<code> (or https://<your-domain>/<code> when the Project has an active custom link domain), with a copy button and the share buttons.
Payout details
A customer with a cash Reward in US dollars that RefRef pays out also sees a payout section: the amounts on hold, ready for payout, in progress, and paid. With a widget:payout token, the customer can enter their country and PayPal address and accept the payout terms. RefRef pays only a customer who saved these details. See Rewards and delivery.
Troubleshooting
| Symptom | Check |
|---|---|
| No button appears | The customer must be enrolled in an active referral Program and have a code. Check the init answer in the Network tab. |
401 AUTH_REQUIRED | Token signature, typ header, aud, iss, lifetime of at most 15 minutes, and the secret of the right Project |
403 FORBIDDEN | projectId in init differs from the token's Project, or the token lacks the scope |
400 INVALID_REQUEST | The customer has several open referral enrollments: pass programId |
| The wrong customer's link | sub and participantKind must match the IDs that your backend sends for that customer |
Never put the client secret or a Workspace API key in browser code. The browser gets only the short-lived Widget token.