Розробка партнерської програми (Affiliate Platform)

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

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

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Розробка партнерської програми (Affiliate Platform)
Середня
від 1 тижня до 3 місяців
Часті питання
Наші компетенції:
Етапи розробки
Останні роботи
  • 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 Platform)

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

Схема даних

CREATE TABLE affiliates (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id         UUID UNIQUE NOT NULL REFERENCES users(id),
    ref_code        VARCHAR(20) UNIQUE NOT NULL,
    status          VARCHAR(20) NOT NULL DEFAULT 'pending'
                    CHECK (status IN ('pending','active','suspended','terminated')),
    commission_rate NUMERIC(5,2) NOT NULL DEFAULT 10,  -- % від суми
    commission_type VARCHAR(20) NOT NULL DEFAULT 'percent'
                    CHECK (commission_type IN ('percent','fixed','hybrid')),
    fixed_amount    NUMERIC(12,2),           -- для fixed/hybrid типів
    cookie_days     INTEGER NOT NULL DEFAULT 30,
    payout_min      NUMERIC(12,2) NOT NULL DEFAULT 1000,
    approved_at     TIMESTAMPTZ,
    created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE TABLE affiliate_links (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    affiliate_id    UUID NOT NULL REFERENCES affiliates(id),
    campaign_name   VARCHAR(200),
    landing_url     VARCHAR(500) NOT NULL,
    params          JSONB DEFAULT '{}',  -- UTM та кастомні параметри
    created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE TABLE affiliate_clicks (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    affiliate_id    UUID NOT NULL REFERENCES affiliates(id),
    link_id         UUID REFERENCES affiliate_links(id),
    ip              INET,
    user_agent      TEXT,
    referrer        VARCHAR(500),
    fingerprint     VARCHAR(64),   -- device fingerprint для cross-device
    created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_affiliate_clicks_date ON affiliate_clicks(affiliate_id, created_at DESC);

CREATE TABLE affiliate_conversions (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    affiliate_id    UUID NOT NULL REFERENCES affiliates(id),
    click_id        UUID REFERENCES affiliate_clicks(id),
    customer_id     UUID REFERENCES users(id),
    order_id        UUID,
    order_amount    NUMERIC(15,2),
    commission      NUMERIC(15,2) NOT NULL,
    status          VARCHAR(20) NOT NULL DEFAULT 'pending'
                    CHECK (status IN ('pending','confirmed','rejected','paid')),
    rejection_reason VARCHAR(200),
    hold_days       INTEGER NOT NULL DEFAULT 30,
    available_at    DATE,
    created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

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

import hashlib
from django.core.cache import cache


def track_affiliate_click(request, ref_code: str, landing_url: str) -> str | None:
    affiliate = Affiliate.objects.filter(
        ref_code=ref_code, status='active'
    ).first()

    if not affiliate:
        return None

    # Device fingerprint для cross-device атрибуції
    fingerprint_raw = f'{request.META.get("HTTP_USER_AGENT")}:{request.META.get("ACCEPT_LANGUAGE")}'
    fingerprint = hashlib.sha256(fingerprint_raw.encode()).hexdigest()[:32]

    click = AffiliateClick.objects.create(
        affiliate=affiliate,
        ip=get_client_ip(request),
        user_agent=request.META.get('HTTP_USER_AGENT', ''),
        referrer=request.META.get('HTTP_REFERER', ''),
        fingerprint=fingerprint,
    )

    # Кука для атрибуції
    cookie_value = str(click.id)
    return cookie_value  # встановлюється в response

Атрибуція конверсії

def attribute_conversion(order, request):
    """Викликається після успішної оплати замовлення"""
    click_id = request.COOKIES.get('aff_click')
    affiliate = None
    click = None

    if click_id:
        click = AffiliateClick.objects.filter(id=click_id).first()
        if click:
            # Перевіряємо, не istink cookie window
            cutoff = timezone.now() - timedelta(days=click.affiliate.cookie_days)
            if click.created_at >= cutoff:
                affiliate = click.affiliate

    if not affiliate:
        # Fallback: шукаємо за fingerprint (cross-device)
        fingerprint = compute_fingerprint(request)
        recent_click = AffiliateClick.objects.filter(
            fingerprint=fingerprint,
            created_at__gte=timezone.now() - timedelta(days=30)
        ).order_by('-created_at').first()
        if recent_click:
            affiliate = recent_click.affiliate
            click = recent_click

    if affiliate:
        commission = calculate_commission(affiliate, order.total_amount)
        AffiliateConversion.objects.create(
            affiliate=affiliate,
            click=click,
            customer=order.user,
            order=order,
            order_amount=order.total_amount,
            commission=commission,
            hold_days=affiliate.hold_days,
            available_at=date.today() + timedelta(days=affiliate.hold_days),
        )

        # Інвалідуємо куку після конверсії
        return True

    return False


def calculate_commission(affiliate, order_amount: Decimal) -> Decimal:
    if affiliate.commission_type == 'percent':
        return (order_amount * affiliate.commission_rate / 100).quantize(Decimal('0.01'))
    elif affiliate.commission_type == 'fixed':
        return affiliate.fixed_amount
    else:  # hybrid
        percent_part = order_amount * affiliate.commission_rate / 100
        return (percent_part + affiliate.fixed_amount).quantize(Decimal('0.01'))

Багаторівнева партнерська програма

class AffiliateRelation(models.Model):
    """Дерево партнерів для багаторівневої програми"""
    affiliate = models.OneToOneField(Affiliate, on_delete=models.CASCADE)
    parent = models.ForeignKey(
        'self', null=True, blank=True,
        on_delete=models.SET_NULL, related_name='children'
    )
    level = models.IntegerField(default=1)


REFERRAL_RATES = {
    1: Decimal('10'),   # прямий партнер: 10%
    2: Decimal('3'),    # партнер партнера: 3%
    3: Decimal('1'),    # третій рівень: 1%
}


def distribute_multilevel_commission(conversion):
    """Начислити комісію по всій ланцюжку вверх"""
    relation = AffiliateRelation.objects.filter(
        affiliate=conversion.affiliate
    ).first()

    level = 1
    current = relation

    while current and level <= 3:
        rate = REFERRAL_RATES.get(level)
        if rate:
            commission = (conversion.order_amount * rate / 100).quantize(Decimal('0.01'))
            AffiliateConversion.objects.create(
                affiliate=current.affiliate,
                order=conversion.order,
                order_amount=conversion.order_amount,
                commission=commission,
                status='pending',
                hold_days=current.affiliate.hold_days,
                available_at=date.today() + timedelta(days=current.affiliate.hold_days),
            )
        current = current.parent
        level += 1

Виплати партнерам

@shared_task
def process_affiliate_payouts():
    """Щоденно: виплачуємо партнерам з доступним балансом"""
    affiliates_with_balance = (
        Affiliate.objects
        .annotate(
            available=Coalesce(
                Subquery(
                    AffiliateConversion.objects.filter(
                        affiliate=OuterRef('pk'),
                        status='confirmed',
                        available_at__lte=date.today()
                    ).values('affiliate').annotate(s=Sum('commission')).values('s')
                ),
                Decimal('0')
            )
        )
        .filter(available__gte=F('payout_min'), status='active')
    )

    for affiliate in affiliates_with_balance:
        initiate_payout(affiliate, affiliate.available)

Антифрод

def check_conversion_fraud(conversion) -> bool:
    """Базові фрод-перевірки"""
    # Самореферрал
    if conversion.customer == conversion.affiliate.user:
        conversion.status = 'rejected'
        conversion.rejection_reason = 'self_referral'
        conversion.save()
        return True

    # Занадто багато конверсій з однієї IP за годину
    recent_from_ip = AffiliateConversion.objects.filter(
        click__ip=conversion.click.ip if conversion.click else None,
        created_at__gte=timezone.now() - timedelta(hours=1)
    ).count()

    if recent_from_ip > 10:
        flag_for_review(conversion, 'high_conversion_rate_from_ip')
        return True

    # Конверсія через кілька секунд після кліку
    if conversion.click:
        time_to_convert = (conversion.created_at - conversion.click.created_at).total_seconds()
        if time_to_convert < 30:
            flag_for_review(conversion, 'instant_conversion')
            return True

    return False

Строк

Базова партнерська програма (одноуровнева, percent-комісія, особистий кабінет, виплата на карту): 3–4 тижні. З багаторівневою структурою, антифродом, детальною аналітикою по кампаніях та автоматичними виплатами: 6–8 тижнів.