Account

API documentation / Recipes

Referral programs: no bonus for inviting yourself

The simplest referral fraud has one person on both sides: they share their own link, open it in the same browser and sign up again. Keep the device ID of every account, compare the new one with the referrer's, and pay the bonus only when the new customer is real.

The problem

A self-invite costs twice: the bonus for the referrer, and often a welcome bonus for the "friend". Programs that pay at sign-up are hit hardest.

This recipe never pays at sign-up. It pays when the invited customer makes a first payment, and it sends doubtful cases to a manual look instead of paying them automatically.

What the API gives you

device.idSaved with every account at sign-up. The same ID for the referrer and the new account means the same browser profile.
seen.accounts_on_device_30dSeveral accounts on the new account's device in 30 days: a farm of "friends".
verdictspoofed or automation: a browser that hides what it is, or a script.

The code

It calls the helper (sl_check_visitor and sl_user_ref), which sends the browser data from the form, the IP address, the headers and a hash of the email.

PHP

<?php
// sign-up through a referral link: decide how the referrer's bonus is paid
$r = sl_check_visitor(sl_user_ref($_POST['email']));
$deviceId = $r['device']['id'] ?? '';                      // save it with every new account
$referrer = findAccountByReferralCode($_GET['ref']);       // your lookup; it has the referrer's device_id
$sameDevice = $deviceId !== '' && $deviceId === $referrer['device_id'];
$doubtful = $r && (($r['seen']['accounts_on_device_30d'] ?? 1) >= 2
    || in_array($r['verdict'], ['spoofed', 'automation'], true));
$bonus = ($sameDevice || $doubtful) ? 'review' : 'on_first_payment';
// 'on_first_payment': credit the referrer when the new customer pays for the first time
// 'review': keep it pending until someone looks at both accounts

Node.js

// sign-up through a referral link (Express): decide how the referrer's bonus is paid
const r = await slCheckVisitor(req, slUserRef(req.body.email));
const deviceId = (r && r.device.id) || '';                 // save it with every new account
const referrer = await findAccountByReferralCode(req.query.ref);   // your lookup; it has the referrer's deviceId
const sameDevice = deviceId !== '' && deviceId === referrer.deviceId;
const doubtful = !!r && (((r.seen && r.seen.accounts_on_device_30d) || 1) >= 2
  || ['spoofed', 'automation'].includes(r.verdict));
const bonus = sameDevice || doubtful ? 'review' : 'on_first_payment';
// 'on_first_payment': credit the referrer when the new customer pays for the first time
// 'review': keep it pending until someone looks at both accounts

Python

# sign-up through a referral link (Flask): decide how the referrer's bonus is paid
r = sl_check_visitor(request, sl_user_ref(request.form['email']))
device_id = r['device']['id'] if r else ''                  # save it with every new account
referrer = find_account_by_referral_code(request.args['ref'])   # your lookup; it has the referrer's device_id
same_device = device_id != '' and device_id == referrer['device_id']
doubtful = bool(r) and ((r.get('seen') or {}).get('accounts_on_device_30d', 1) >= 2
    or r.get('verdict') in ('spoofed', 'automation'))
bonus = 'review' if same_device or doubtful else 'on_first_payment'
# 'on_first_payment': credit the referrer when the new customer pays for the first time
# 'review': keep it pending until someone looks at both accounts

Save device.id for every account, not only for invited ones: the comparison needs the referrer's ID from their own sign-up.

Soft steps instead of a ban

Rules in your account

Set them in Rules and alerts: the result comes back as decision in every answer, so your code does not change when the rules do.

Where it can be wrong

One line for your privacy policy

To prevent abuse of our referral program, we check technical characteristics of your browser with SpoofLens (spooflens.com) when you sign up.

Limits

Other recipes

Get a free key 1,000 checks a month free, no card.