Реферальный дашборд — это полнофункциональное представление партнёра с partners.revroute.ru (ссылка, кнопки шеринга, статистика, история комиссий, баланс выплат), отрендеренное прямо в вашей странице.
Предусловия
- Workspace API-ключ с правом
partners.read - Программа создана в вашем workspace
- Пользователь уже зачислен в эту программу как партнёр (вручную, через форму заявки или через API)
@dub/embed-reactустановлен — см. Установку
Выпуск токена
curl -X POST https://api.revroute.ru/tokens/embed/referrals \
-H "Authorization: Bearer $REVROUTE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"partnerId": "pn_5MhYz",
"programId": "prog_CYCu7IMAapjkRpTnr8F1azjN"
}'| Поле | Обязательно | Описание |
|---|---|---|
partnerId | одно из двух | ID партнёра в RevRoute (pn_...) |
tenantId | одно из двух | Внешний ID партнёра в вашей системе (если мапили при зачислении) |
programId | да | Дашборд какой программы рендерить |
Ответ:
{
"publicToken": "dub_embed_eyJhbGc...",
"expires": "2026-05-15T13:34:56.789Z"
}Токен валиден ~1 час и scoped к одному партнёру. Выпускайте заново на каждую загрузку страницы — никогда не кэшируйте между пользователями.
Монтирование компонента
import { DubEmbed } from "@dub/embed-react";
<DubEmbed
data="referrals"
token={publicToken}
style={{ width: "100%", height: "720px", border: 0, borderRadius: 12 }}
/>| Prop | Тип | Обязателен | Описание |
|---|---|---|---|
token | string | да | publicToken от эндпоинта токенов |
data | "referrals" | да | Какой embed рендерить |
options | object | нет | Темизация и локаль, см. Темизацию |
style | CSSProperties | нет | Inline-стили для обёрточного <div> |
className | string | нет | Класс для обёрточного <div> |
Все остальные HTML-пропсы (id, data-*, aria-* и т.д.) пробрасываются на обёрточный <div>.
Что видит партнёр
Компонент показывает вкладки:
- Обзор — реферальная ссылка, кнопки скопировать/поделиться, статистика кликов и конверсий, топ-страны
- Заработок — pending и оплаченные комиссии, фильтры по статусу и дате
- Выплаты — подтверждённые выплаты, текущий баланс, ожидаемая следующая выплата
- Материалы — лендинги и креативы, загруженные в программу
Партнёр копирует уникальную ссылку, генерирует UTM-варианты, шарит через deep-links, смотрит историю конверсий — не покидая ваш продукт.
Авто-зачисление новых партнёров
Частый паттерн — лениво зачислять пользователей в программу: выпускаете токен по запросу, передавая tenantId, равный внутреннему ID пользователя; если партнёра ещё нет — RevRoute создаёт его и возвращает новый ID.
const res = await fetch("https://api.revroute.ru/tokens/embed/referrals", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.REVROUTE_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
tenantId: user.id, // ваш внутренний ID
programId: process.env.REVROUTE_PROGRAM_ID,
partner: { name: user.name, email: user.email }, // отправляется на первом вызове
}),
});tenantId уникален в пределах workspace — последующие вызовы возвращают того же партнёра.
Размер и компоновка
У embed внутренний скролл, если контейнер слишком мал. Выбирайте высоту под дизайн и пусть компонент скроллится внутри. Избегайте position: fixed у родителей — iframe может неверно сообщать свой размер при reflow.
Для responsive-layout’ов задавайте height: 100% на flex-родителе, а не viewport-единицы — последние прыгают на мобильных.
Прослушивание событий (продвинутое)
Embed постит события родительскому окну через postMessage. Можно слушать их для своей аналитики:
useEffect(() => {
function onMessage(e: MessageEvent) {
if (e.origin !== "https://app.revroute.ru") return;
if (e.data?.source !== "dub-embed") return;
// e.data.event: "link.copied" | "tab.changed" | "share.clicked" ...
track("embed_" + e.data.event, e.data.payload);
}
window.addEventListener("message", onMessage);
return () => window.removeEventListener("message", onMessage);
}, []);Слушайте события только от https://app.revroute.ru — никогда не доверяйте недоверенным origin’ам.
Решение проблем
| Симптом | Вероятная причина | Решение |
|---|---|---|
| Пустой iframe, ошибок нет | CSP блокирует frame-src | Добавьте frame-src https://app.revroute.ru в CSP |
401 при выпуске токена | Неверный или отсутствующий API-ключ | Проверьте заголовок Authorization: Bearer ... |
404 partner not found | Неверный partnerId / tenantId | Проверьте, что партнёр существует в этой программе |
| Компонент рендерится, но показывает “Session expired” | Токен истёк | Перевыпустите токен, передайте новое значение в token= |
| Тёмная тема не применяется | Тема установлена после первого монтажа | Передавайте тему в options до монтажа; не переключайте CSS-переменные на обёртке iframe |