Built for startups,
scaled for unicorns
Successfully submitted!
Error! Please try again

Referral fraud β fake referrals, self-referrals, and referral rings β can drain your program budget and undermine trust. While GrowSurf includes built-in fraud prevention features, a custom webhook-based detection layer gives you additional protection tailored to your business's specific risk patterns.
This guide covers building a real-time fraud detection system that analyzes GrowSurf webhook events for suspicious patterns. You'll learn how to detect common fraud signals, implement scoring-based fraud thresholds, flag suspicious referrals for manual review, and automatically block fraudulent participants.
Understand the types of referral fraud you're likely to encounter so you can build detection rules.
Create a rules engine that scores each referral event for fraud risk.
Assign risk scores to each referral based on how many fraud signals are present.
Create a webhook handler that runs fraud checks on every new referral event in real-time.
PARTICIPANT_REFERRED event through the fraud rules engineCreate dashboards and alerts that help your team monitor fraud patterns over time.
Create a system for manually reviewing referrals that scored in the medium-risk range.
// Referral Fraud Detection Engine
const disposableDomains = require('disposable-email-domains');
const FRAUD_RULES = {
disposableEmail: { points: 30, check: (data) => {
const domain = data.participant.email.split('@')[1];
return disposableDomains.includes(domain);
}},
sameIpAsReferrer: { points: 40, check: (data) => {
return data.participant.ip && data.referrer?.ip &&
data.participant.ip === data.referrer.ip;
}},
highVelocity: { points: 25, check: async (data) => {
const recentReferrals = await db.referrals.countRecent(
data.referrer?.id, '1 hour'
);
return recentReferrals > 5; // More than 5 referrals in 1 hour
}},
similarNames: { points: 20, check: (data) => {
if (!data.referrer?.firstName || !data.participant.firstName) return false;
return levenshtein(
data.referrer.firstName.toLowerCase(),
data.participant.firstName.toLowerCase()
) <= 2;
}},
sequentialEmails: { points: 35, check: async (data) => {
const referrerReferrals = await db.referrals.getByReferrer(data.referrer?.id);
const emails = referrerReferrals.map(r => r.email).concat(data.participant.email);
return detectSequentialPattern(emails);
}}
};
async function calculateFraudScore(webhookData) {
let score = 0;
const triggeredRules = [];
for (const [rule, config] of Object.entries(FRAUD_RULES)) {
const triggered = await config.check(webhookData);
if (triggered) {
score += config.points;
triggeredRules.push(rule);
}
}
return { score, triggeredRules };
}
app.post('/webhooks/growsurf/fraud', async (req, res) => {
const { event, participant, referrer } = req.body;
if (event !== 'PARTICIPANT_REFERRED') {
return res.status(200).json({ skipped: true });
}
const { score, triggeredRules } = await calculateFraudScore(req.body);
if (score >= 61) {
// High risk: auto-block
await removeParticipant(participant.id);
await db.fraudLog.create({ participantId: participant.id, score, action: 'blocked', rules: triggeredRules });
} else if (score >= 31) {
// Medium risk: flag for review
await db.fraudReview.create({ participantId: participant.id, score, rules: triggeredRules });
await notifyFraudTeam(participant, score, triggeredRules);
}
// Low risk: auto-approve (no action needed)
res.json({ score, action: score >= 61 ? 'blocked' : score >= 31 ? 'flagged' : 'approved' });
});Begin with lenient fraud thresholds and tighten them as you collect data. It's better to let a few fraudulent referrals through initially than to block legitimate participants. Monitor your false positive rate and adjust scoring weights based on confirmed fraud cases.
Use a well-maintained list of disposable email domains (the npm package disposable-email-domains is a good start). Update this list regularly β new disposable email services appear constantly. Also consider flagging very new email domains (registered within the last month).
Log every fraud check, even for low-risk referrals that pass all checks. Over time, this data reveals fraud patterns you hadn't anticipated. Periodically review your fraud logs to identify new signals and refine your detection rules.
Yes. GrowSurf includes several built-in fraud prevention features: email verification requirements, IP-based deduplication, referral rate limiting, and suspicious activity detection. Custom webhook-based fraud detection adds an additional layer that's specific to your business's risk profile and catches edge cases the built-in features may miss.
Send flagged referrals to a review queue rather than auto-blocking them. Your fraud team reviews flagged referrals and approves legitimate ones. Track your false positive rate β if it exceeds 10%, loosen your rules. When you approve a false positive, add the participant to an allowlist to prevent future false flags.
Yes. Use GrowSurf's API to export all participants and run them through your fraud scoring engine in batch. This helps catch fraud that occurred before you implemented detection. Use GET /v2/campaign/{id}/participants to retrieve all participants and process them offline.
Trusted by marketing and product teams at fast-growing B2C, fintech, and SaaS companies
