Реалізація Affiliate Dashboard для партнерської програми сайту

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.
Розробка та обслуговування будь-яких видів сайтів:
Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Реалізація Affiliate Dashboard для партнерської програми сайту
Середня
~5 робочих днів
Часті питання
Наші компетенції:
Етапи розробки
Останні роботи
  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Партнерський дашборд (Affiliate Dashboard)

Affiliate-програма відрізняється від реферальної: партнери (аффілиати) — це зовнішні паблішери, блогери, сайти. Вони розміщують посилання та отримують комісію за конверсії. Дашборд — інструмент партнера для відстеження кліків, конверсій та виплат.

Архітектура трекингу

model Affiliate {
  id            String          @id @default(cuid())
  userId        String          @unique
  status        AffiliateStatus @default(PENDING)
  commissionRate Decimal        @default(0.20)    // 20%
  payoutThreshold Int           @default(5000)    // мінімум для виплати ($50)
  payoutMethod  String?         // 'paypal' | 'bank' | 'crypto'
  payoutDetails Json?

  user          User            @relation(fields: [userId], references: [id])
  links         AffiliateLink[]
  clicks        AffiliateClick[]
  conversions   AffiliateConversion[]
  payouts       AffiliatePayout[]
}

model AffiliateLink {
  id          String   @id @default(cuid())
  affiliateId String
  code        String   @unique // PARTNER123
  targetUrl   String
  campaign    String?
  createdAt   DateTime @default(now())

  affiliate   Affiliate      @relation(fields: [affiliateId], references: [id])
  clicks      AffiliateClick[]
}

model AffiliateClick {
  id          String   @id @default(cuid())
  linkId      String
  affiliateId String
  ip          String
  userAgent   String
  referrer    String?
  clickedAt   DateTime @default(now())
  converted   Boolean  @default(false)

  link        AffiliateLink @relation(fields: [linkId], references: [id])
}

model AffiliateConversion {
  id            String   @id @default(cuid())
  affiliateId   String
  clickId       String?
  orderId       String   @unique
  orderAmount   Int      // в копійках
  commission    Int
  status        String   @default('pending')
  createdAt     DateTime @default(now())
}

Трекинг кліків

// app/api/aff/[code]/route.ts
export async function GET(request: NextRequest, { params }: { params: { code: string } }) {
  const link = await db.affiliateLink.findUnique({
    where: { code: params.code },
    include: { affiliate: true }
  });

  if (!link || link.affiliate.status !== 'ACTIVE') redirect('/');

  // Записуємо клік (fire & forget)
  db.affiliateClick.create({
    data: {
      linkId: link.id,
      affiliateId: link.affiliateId,
      ip: request.headers.get('x-forwarded-for') ?? 'unknown',
      userAgent: request.headers.get('user-agent') ?? '',
      referrer: request.headers.get('referer') ?? '',
    }
  }).catch(console.error);

  // Cookie для атрибуції конверсії (30-дневне вікно)
  const response = Response.redirect(link.targetUrl, 302);
  response.headers.set(
    'Set-Cookie',
    `aff_code=${params.code}; Max-Age=${30 * 24 * 60 * 60}; Path=/; HttpOnly; SameSite=Lax`
  );
  return response;
}

Дашборд партнера

export default async function AffiliateDashboard() {
  const session = await auth();
  const affiliate = await db.affiliate.findUnique({
    where: { userId: session!.user.id },
    include: {
      links: {
        include: {
          _count: { select: { clicks: true } }
        }
      }
    }
  });

  if (!affiliate) redirect('/affiliate/apply');
  if (affiliate.status === 'PENDING') return <AffiliatePendingPage />;

  const thirtyDaysAgo = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000);

  const stats = await db.$transaction([
    db.affiliateClick.count({
      where: { affiliateId: affiliate.id, clickedAt: { gte: thirtyDaysAgo } }
    }),
    db.affiliateConversion.findMany({
      where: { affiliateId: affiliate.id, createdAt: { gte: thirtyDaysAgo } }
    }),
    db.affiliateConversion.aggregate({
      where: { affiliateId: affiliate.id, status: 'approved' },
      _sum: { commission: true }
    }),
  ]);

  const [clickCount, conversions, balance] = stats;
  const conversionRate = clickCount > 0
    ? (conversions.length / clickCount * 100).toFixed(1)
    : '0';

  return (
    <div className="space-y-8">
      <StatsGrid
        clicks={clickCount}
        conversions={conversions.length}
        conversionRate={conversionRate}
        balance={balance._sum.commission ?? 0}
        commissionRate={affiliate.commissionRate}
      />
      <LinksTable links={affiliate.links} affiliateId={affiliate.id} />
      <ConversionsTable conversions={conversions} />
      <PayoutSection
        balance={balance._sum.commission ?? 0}
        threshold={affiliate.payoutThreshold}
        payoutMethod={affiliate.payoutMethod}
      />
    </div>
  );
}

Виплати

import Stripe from 'stripe';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);

export async function processPayout(affiliateId: string) {
  const affiliate = await db.affiliate.findUnique({
    where: { id: affiliateId },
    include: {
      conversions: {
        where: { status: 'approved' }
      }
    }
  });

  const totalAmount = affiliate!.conversions.reduce(
    (sum, c) => sum + c.commission, 0
  );

  if (totalAmount < affiliate!.payoutThreshold) {
    throw new Error(`Below minimum payout threshold`);
  }

  const transfer = await stripe.transfers.create({
    amount: totalAmount,
    currency: 'usd',
    destination: affiliate!.payoutDetails?.stripeAccountId as string,
    metadata: { affiliateId },
  });

  await db.$transaction([
    db.affilaitePayout.create({
      data: {
        affiliateId,
        amount: totalAmount,
        stripeTransferId: transfer.id,
        status: 'processing',
      }
    }),
    db.affiliateConversion.updateMany({
      where: { affiliateId, status: 'approved' },
      data: { status: 'paid' }
    }),
  ]);
}

Розробка партнерської програми з трекингом кліків, конверсій та дашбордом партнера — 5–8 робочих днів.