Embedded Portal
Add a partner referral dashboard to your app with hosted iframe rendering or custom React components.
The embedded portal is the partner-facing part of Refport. It lets signed-in users copy their referral link, view clicks and conversions, track earnings, and manage payouts without leaving your product.
This is a core Refport integration path. Install tracking first, start sending conversions, then embed the portal where partners already work inside your app.
Integration options
| Option | Best for | What you build |
|---|---|---|
| Hosted iframe | Fastest launch and low maintenance | A server route that creates tokens and a <RefportEmbed> component |
| Custom React UI | Native product experience | A server route that creates tokens and UI built with Refport hooks |
Both options use the same short-lived embed token.
How it works
- A signed-in user opens the referral area in your app.
- Your server verifies the user and calls
embedTokens.create(). - Refport creates or finds the partner enrollment for that user.
- Your app passes the public token to the iframe or React provider.
- The portal fetches partner-scoped data without exposing your private API key.
Setup
npm install refport @refport/react @tanstack/react-queryCreate an API route or server function that only runs after your app has authenticated the user.
import { Refport } from "refport";
const refport = new Refport({ apiKey: process.env.REFPORT_API_KEY! });
export async function GET(request: Request) {
const user = await getCurrentUser(request);
if (!user?.email) {
return Response.json({ error: "Unauthorized" }, { status: 401 });
}
const result = await refport.embedTokens.create({
tenantId: user.id,
partner: {
email: user.email,
name: user.name,
},
});
if (result.error) {
return Response.json(
{ error: result.error.message },
{ status: result.error.status }
);
}
return Response.json({
expires: result.data.expires,
token: result.data.publicToken,
});
}Generate tokens from the server only. The private Refport API key must never be available in browser code.
Use <RefportEmbed> when you want the fastest path.
import { RefportEmbed } from "@refport/react";
async function getEmbedToken(): Promise<string> {
const response = await fetch("/api/referrals/embed-token");
const data = await response.json();
return data.token;
}
export default async function ReferralsPage() {
const token = await getEmbedToken();
return <RefportEmbed token={token} theme="system" />;
}Hosted iframe
The hosted portal gives you a complete partner dashboard with minimal product work. Partners can view performance, copy their referral link, review payouts, and complete payout setup from the embedded experience.
<RefportEmbed
token={token}
theme="system"
cssVars={{
"--border-radius": "8px",
"--font-family": "Inter, sans-serif",
}}
/>Use the onError prop to recover from expired tokens.
<RefportEmbed
token={token}
onError={({ code }) => {
if (code === "TOKEN_EXPIRED") {
refreshEmbedToken();
}
}}
/>Custom React UI
Use RefportProvider and useRefportPartner() when the referral experience should look and behave like the rest of your product.
"use client";
import { RefportProvider, useRefportPartner } from "@refport/react";
export function ReferralPortal({ token }: { token: string }) {
return (
<RefportProvider token={token}>
<ReferralPortalContent />
</RefportProvider>
);
}
function ReferralPortalContent() {
const partner = useRefportPartner({ limit: 10 });
if (partner.isLoading) {
return <p>Loading...</p>;
}
if (partner.error) {
return <p>Could not load referral data.</p>;
}
const { earnings, link, payouts, stats } = partner.data;
return (
<section>
<h1>Your referrals</h1>
<input readOnly value={link.referralUrl} />
<dl>
<dt>Clicks</dt>
<dd>{stats.clicks}</dd>
<dt>Leads</dt>
<dd>{stats.leads}</dd>
<dt>Sales</dt>
<dd>{stats.sales}</dd>
<dt>Total earnings</dt>
<dd>
{earnings.total} {earnings.currency}
</dd>
</dl>
<ul>
{payouts.payouts.map((payout) => (
<li key={payout.id}>
{payout.amount} {payout.currency} - {payout.status}
</li>
))}
</ul>
</section>
);
}Portal dataset
useRefportPartner() returns the complete portal dataset in one request.
| Field | Description |
|---|---|
stats | Click, lead, sale, and earnings totals |
timeseries | Click, lead, and sale trends |
link | Referral code, referral URL, and program name |
earnings | Earnings breakdown and commission settings |
payouts | Payout history |
portalConfig | Portal branding and visibility configuration |
Granular hooks are available when a component only needs part of the dataset.
| Hook | Data |
|---|---|
useRefportAffiliateStats() | Click, lead, sale, and earnings totals |
useRefportAffiliateTimeseries() | Click, lead, and sale trends |
useRefportAffiliateLink() | Referral code, referral URL, and program name |
useRefportAffiliateEarnings() | Earnings breakdown and commission settings |
useRefportAffiliatePayouts() | Payout history |
useRefportPortalConfig() | Portal branding and visibility configuration |
Security model
- Create embed tokens on the server after your app authenticates the user.
- Scope each token to one partner or tenant.
- Generate a fresh token on page load or session refresh.
- Treat the public token as browser-safe but short lived.
- Keep
REFPORT_API_KEYin server-only environment variables.
Without React
If you are not using React, create the iframe URL yourself.
const params = new URLSearchParams({
dynamicHeight: "true",
theme: "system",
token: publicToken,
});
const iframeSrc = `https://app.refport.co/embed/referrals?${params}`;