Skip to main content

Affiliate Fraud Detection

Affiliate fraud — fake clicks, bot installs, and manufactured conversions — can drain your marketing budget. ShieldLabs flags low-quality traffic through device fingerprinting and IP intelligence.

Common affiliate fraud patterns

PatternScore rangeKey signals
Bot farm clicks100+Stun is not checked, UA OS not detected
Proxy traffic (fake geo)40–70Is proxy, Is datacenter, Browser timezone ≠ IP-timezone
Anti-detect multi-accounting30–60Fail by * os detect, Is vpn by base ip
Data center click farm60–100Is datacenter, Is abuser, Stun is not checked

Score conversion events

Add the snippet to your landing page and affiliate conversion confirmation page:
<!-- landing.html (affiliate traffic arrives here) -->
<script type="module">
  const mod = await import('https://cdn.shieldlabs.ai/snippet.js?publicKey=YOUR_PUBLIC_KEY');
  mod.checkAnonymous((ip, requestId) => {
    // Store in cookie/session for later attribution
    document.cookie = `shield_rid=${requestId}; max-age=3600; SameSite=Lax`;
  });
</script>

Gate conversions on score

app.post('/api/conversion', async (req, res) => {
  const { affiliateId, eventType } = req.body;
  const shieldRequestId = req.cookies.shield_rid;

  const shield = shieldRequestId
    ? await getScore(shieldRequestId)
    : null;

  const score = shield?.score ?? 0;
  const isQualityTraffic = score < 40;

  await db.conversions.create({
    affiliateId,
    eventType,
    shieldScore:   score,
    shieldSignals: shield?.signals,
    qualified:     isQualityTraffic,
    ip:            shield?.ip,
    country:       shield?.country,
    deviceId:      shield?.deviceId,
  });

  if (!isQualityTraffic) {
    // Record as suspected fraud — don't pay affiliate
    await flagAffiliateConversion(affiliateId, score, shield);
    return res.json({ ok: true }); // Don't tell the bot it was flagged
  }

  // Pay affiliate
  await recordQualifiedConversion(affiliateId, eventType);
  return res.json({ ok: true });
});

Detect affiliate-level fraud patterns

Aggregate scores per affiliate to identify systematic fraud:
// Daily job: check affiliate quality
async function auditAffiliates() {
  const affiliates = await db.conversions.groupBy('affiliateId', {
    last24h: true,
    select: {
      totalConversions: true,
      avgScore: true,
      highRiskCount: { where: { shieldScore: { gte: 40 } } },
    },
  });

  for (const aff of affiliates) {
    const fraudRate = aff.highRiskCount / aff.totalConversions;
    if (fraudRate > 0.3) {
      // >30% high-risk traffic — suspend affiliate
      await suspendAffiliate(aff.affiliateId, fraudRate);
      await notifyFraudTeam(aff);
    }
  }
}

Device-based deduplication

Bots often send the same device multiple times to inflate click counts. Use DeviceID to deduplicate:
app.post('/shieldlabs/webhook', async (req, res) => {
  const { Data } = req.body;
  res.status(200).end();

  // Check for duplicate device in attribution window
  const isDuplicate = await redis.exists(
    `affiliate:device:${affiliateId}:${Data.DeviceID}`
  );

  if (isDuplicate) {
    await db.conversions.update(
      { requestId: Data.RequestID },
      { duplicateDevice: true, qualified: false }
    );
    return;
  }

  // Mark device as seen for this affiliate (24h window)
  await redis.setex(
    `affiliate:device:${affiliateId}:${Data.DeviceID}`,
    86400,
    '1'
  );
});