Skip to main content

Referrals

Referral links let players invite friends into your game.

You can attach an entryPayload to carry attribution or customization into the invited player’s first session, and then track which invites converted (joined your game).

Conversions are grouped by reference, a stable campaign key you define (for example unlock_party_mode_v1 or tiktok_campaign_feb).

note

Attribution happens the first time a player enters your game. A player who has previously entered your game is not counted as a conversion if they later open a referral link.

Call shareReferralLink to open the platform share dialog for a referral link to your game.

note

shareReferralLink only opens the share dialog. It does not guarantee the player completes the share.

Opens the platform share dialog with your provided title/text and a link to your game.

JestSDK.referrals.shareReferralLink({
// A stable campaign key you choose to label invites (for example a feature or campaign name).
reference: string;

// Optional metadata that is passed to the invited player when they enter the game
entryPayload?: Record<string, unknown>;

// Optional title/text for the share dialog (platform dependent)
shareTitle?: string;
shareText?: string;

// Optional onboarding game slug to route invited players through first
onboardingSlug?: string;
}): Promise<{
// True if the player dismissed the share dialog.
canceled: boolean;
}>;

The entryPayload is embedded into the shared link. When an invited player enters your game through that link, you can read the payload via JestSDK.getEntryPayload().

Here’s an example:

const { canceled } = await JestSDK.referrals.shareReferralLink({
reference: "unlock_party_mode_v1", // Unlock Party Mode after enough successful invites
entryPayload: {
feature: "party_mode",
// Optional: include referrer-specific context for the invited player to read on entry
// (for example, a chosen pet name, loadout, or a short invite code).
referrer: { name: "Ava", petName: "Pickles" },
},
shareTitle: "Come play this with me",
shareText: "Join my game. I want to unlock Party Mode with you.",
});

if (canceled) {
// The user dismissed the share dialog.
}

Error handling

shareReferralLink can throw an INVALID_ARGUMENTS error if the provided options do not match the required schema.

List referral conversions (listReferrals)

Call listReferrals to retrieve referral conversions for the current player, grouped by reference.

Conversions include only invited players who complete registration.

JestSDK.referrals.listReferrals

JestSDK.referrals.listReferrals(): Promise<{
referrals: {
[reference: string]: { playerId: string; joinedAt: string }[];
};
referralsSigned: string;
}>;
const { referrals, referralsSigned } = await JestSDK.referrals.listReferrals();

const partyModeConversions = referrals["unlock_party_mode_v1"] ?? [];
console.log("Party Mode conversions:", partyModeConversions.length);

// Recommended: send `referralsSigned` to your backend and verify it before granting rewards.

If you grant rewards for referrals, verify referralsSigned on your backend instead of trusting client-reported conversions. This is the same pattern used for JestSDK.getPlayerSigned() and signed purchase payloads in the Payments module.

referralsSigned is an HS256 JWS signed with your game’s shared secret. The payload has this shape:

type ReferralsSignedPayload = {
referrals: Record<string, Array<{ playerId: string; joinedAt: string }>>;
aud: string; // game id
sub: string; // referrer player id
};
// npm i jose
import { jwtVerify } from "jose";

export async function verifyReferralsSigned(token: string, gameId: string) {
const secretBase64 = process.env.JWS_SECRET!;
const secret = Buffer.from(secretBase64, "base64");

const { payload } = await jwtVerify(token, secret, {
algorithms: ["HS256"],
audience: gameId,
});

return payload as {
referrals: Record<string, Array<{ playerId: string; joinedAt: string }>>;
aud: string;
sub: string;
};
}

Example: Unlock a feature after 3 invites

Suppose you want to unlock a feature (for example, “Party Mode”) after a player gets 3 successful invites.

Use a dedicated reference for this feature gate, for example:

  • reference: "unlock_party_mode_v1"

There are two common ways to implement this:

  • Client-only (not server verified): simplest, good for low-stakes UX (cosmetics, UI hints). This can be spoofed by a modified client.
  • Server verified: recommended for anything that affects entitlements, currency, or competitive balance. The server verifies referralsSigned before unlocking.

Non-server verified (client-only)

const { referrals } = await JestSDK.referrals.listReferrals();
const inviteCount = (referrals["unlock_party_mode_v1"] ?? []).length;

if (inviteCount >= 3) {
unlockPartyModeLocally();
} else {
showInviteProgress({ inviteCount, required: 3 });
}

Client: send referralsSigned to your backend (and authenticate the player using your normal mechanism).

const { referralsSigned } = await JestSDK.referrals.listReferrals();

await fetch("/api/referrals/unlock-party-mode", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
referralsSigned,
}),
});

Server: verify the JWS, count conversions for the reference, then unlock the feature in persistent state.

import { jwtVerify } from "jose";

export async function unlockPartyModeHandler(req: {
body: { referralsSigned: string };
}) {
const secretBase64 = process.env.JWS_SECRET!;
const secret = Buffer.from(secretBase64, "base64");
const gameId = process.env.GAME_ID!;

const { payload } = await jwtVerify(req.body.referralsSigned, secret, {
algorithms: ["HS256"],
audience: gameId,
});

const referrals = payload.referrals as Record<
string,
Array<{ playerId: string; joinedAt: string }>
>;

const reference = "unlock_party_mode_v1"; // hardcode server-side; do not trust client input
const inviteCount = (referrals?.[reference] ?? []).length;

if (inviteCount < 3) {
return { unlocked: false, inviteCount };
}

// Persist the entitlement (idempotent write recommended).
await grantPartyModeToPlayer({ playerId: payload.sub as string });

return { unlocked: true, inviteCount };
}

Testing referrals

To run a full referral loop against an uploaded build, use two sandbox users — one as the referrer, one as the invitee. See Test referrals for the step-by-step recipe.