Розробка реферальної системи

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

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

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

Розробка реферальної системи

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

Модель даних

CREATE TABLE referral_codes (
    id          BIGSERIAL PRIMARY KEY,
    user_id     BIGINT REFERENCES users(id),
    code        VARCHAR(32) UNIQUE NOT NULL,
    type        VARCHAR(32) DEFAULT 'personal', -- personal/promo/partner
    created_at  TIMESTAMPTZ DEFAULT NOW()
);

CREATE TABLE referral_clicks (
    id          BIGSERIAL PRIMARY KEY,
    code_id     BIGINT REFERENCES referral_codes(id),
    ip          INET,
    user_agent  TEXT,
    landed_at   TIMESTAMPTZ DEFAULT NOW(),
    converted   BOOLEAN DEFAULT FALSE
);

CREATE TABLE referrals (
    id              BIGSERIAL PRIMARY KEY,
    referrer_id     BIGINT REFERENCES users(id),   -- хто привів
    referred_id     BIGINT REFERENCES users(id),   -- кого привели
    code_id         BIGINT REFERENCES referral_codes(id),
    status          VARCHAR(32) DEFAULT 'pending', -- pending/qualified/rewarded/cancelled
    qualified_at    TIMESTAMPTZ,                   -- виконано умова
    created_at      TIMESTAMPTZ DEFAULT NOW()
);

CREATE TABLE referral_rewards (
    id              BIGSERIAL PRIMARY KEY,
    referral_id     BIGINT REFERENCES referrals(id),
    recipient_id    BIGINT REFERENCES users(id),   -- реферер або реферал
    type            VARCHAR(32),                   -- 'cashback', 'bonus_points', 'discount'
    amount          DECIMAL(14,2),
    currency        CHAR(3) DEFAULT 'RUB',
    status          VARCHAR(32) DEFAULT 'pending', -- pending/paid/cancelled
    paid_at         TIMESTAMPTZ
);

Генерація унікального коду

class ReferralCodeService {
    public function generateForUser(User $user): ReferralCode {
        // Перевіряємо, немає ли вже коду
        if ($existing = ReferralCode::where('user_id', $user->id)->first()) {
            return $existing;
        }

        do {
            // Читаємий код на основі імені користувача + випадковий суфікс
            $base = strtoupper(substr(preg_replace('/[^a-z]/i', '', $user->name), 0, 4));
            $code = $base . strtoupper(Str::random(4));
        } while (ReferralCode::where('code', $code)->exists());

        return ReferralCode::create([
            'user_id' => $user->id,
            'code'    => $code,
        ]);
    }
}

Реферальне посилання та cookie

Реферальний параметр передається через URL: https://example.com/register?ref=IVAN4X2K. Потрібно зберегти атрибуцію навіть якщо користувач не зареєструється одразу:

// Middleware: ReferralTracker
class ReferralTrackerMiddleware {
    public function handle(Request $request, Closure $next): Response {
        $code = $request->query('ref');

        if ($code && !session()->has('referral_code')) {
            $referralCode = ReferralCode::where('code', $code)->first();
            if ($referralCode) {
                session(['referral_code' => $code]);
                // Логуємо клік
                ReferralClick::create([
                    'code_id'    => $referralCode->id,
                    'ip'         => $request->ip(),
                    'user_agent' => $request->userAgent(),
                ]);
            }
        }

        return $next($request);
    }
}

Атрибуція при реєстрації

// У UserRegistrationService
public function register(array $data): User {
    $user = User::create($data);

    $referralCode = session()->pull('referral_code');
    if ($referralCode) {
        $code = ReferralCode::where('code', $referralCode)->first();
        if ($code && $code->user_id !== $user->id) {
            Referral::create([
                'referrer_id' => $code->user_id,
                'referred_id' => $user->id,
                'code_id'     => $code->id,
                'status'      => 'pending',
            ]);
            // Позначаємо клік як сконвертований
            ReferralClick::where('code_id', $code->id)
                ->where('converted', false)
                ->latest('landed_at')
                ->first()
                ?->update(['converted' => true]);
        }
    }

    return $user;
}

Умови начисління вознаграждення

Реферал вважається "кваліфікованим" тільки при виконанні певної умови: перша оплата, досягнення порога покупок, закінчення trial-періоду. Реалізується через Events:

// Подія: перша оплата нового користувача
class FirstPurchaseMade {
    public function __construct(public Order $order) {}
}

// Listener
class QualifyReferralOnFirstPurchase {
    public function handle(FirstPurchaseMade $event): void {
        $referral = Referral::where('referred_id', $event->order->user_id)
            ->where('status', 'pending')
            ->first();

        if (!$referral) return;

        DB::transaction(function() use ($referral, $event) {
            $referral->update([
                'status'       => 'qualified',
                'qualified_at' => now(),
            ]);

            $program = ReferralProgram::active()->first();

            // Вознаграждення рефереру
            ReferralReward::create([
                'referral_id'  => $referral->id,
                'recipient_id' => $referral->referrer_id,
                'type'         => $program->reward_type,
                'amount'       => $this->calculateReward($program, $event->order),
                'status'       => 'pending',
            ]);

            // Двостороння програма: бонус й новому користувачу
            if ($program->reward_referred) {
                ReferralReward::create([
                    'referral_id'  => $referral->id,
                    'recipient_id' => $referral->referred_id,
                    'type'         => $program->referred_reward_type,
                    'amount'       => $program->referred_reward_amount,
                    'status'       => 'pending',
                ]);
            }
        });
    }

    private function calculateReward(ReferralProgram $program, Order $order): float {
        return match($program->reward_type) {
            'fixed'      => $program->reward_amount,
            'percentage' => round($order->total * $program->reward_percent / 100, 2),
            default      => 0,
        };
    }
}

Виплата вознаграждень

Накопичені вознаграждення виплачуються пакетно (раз на тиждень) або одразу — залежить від типу:

// Бонусні бали — мгновенно
class CreditBonusPoints implements ShouldQueue {
    public function handle(ReferralRewardCreated $event): void {
        $reward = $event->reward;
        if ($reward->type !== 'bonus_points') return;

        BonusAccount::firstOrCreate(['user_id' => $reward->recipient_id])
            ->increment('balance', $reward->amount);

        $reward->update(['status' => 'paid', 'paid_at' => now()]);
    }
}

Особистий кабінет реферера

Страница статистики реферальної програми показує коди, посилання, статистику конверсій та вознаграждень.

Захист від фрода

Базові перевірки:

// Самореферал (користувач ввів власний код)
if ($referral->referrer_id === $event->order->user_id) {
    $referral->update(['status' => 'cancelled']);
    return;
}

// Один IP зареєстрував кілька аккаунтів
$sameIpUsers = DB::table('user_registrations')
    ->where('ip', $event->order->user->registration_ip)
    ->where('created_at', '>', now()->subDays(7))
    ->count();

if ($sameIpUsers > 3) {
    $referral->update(['status' => 'fraud_suspect']);
    return;
}

Терміни реалізації

Базова реферальна система з кодами, атрибуцією й нарахуванням фіксованого вознаграждення: 1–1,5 тижні. Двостороння програма з процентними бонусами, особистим кабінетом і захистом від фрода: 2–2,5 тижні. Багаторівнева (MLM-подібна) реферальна система з деревом рефералів: плюс 1–2 тижні.