Detecting Lead Form Fraud: From Blocking to Intelligent Filtering
Lead forms face multi-layered attacks—from simple bots to paid submissions by real people. Initially, bots scraped static pages and auto-filled fields. The shift to dynamic form generation using Vue.js temporarily disrupted this flow by hiding elements from scrapers.
Spammers adapted by reverse-engineering API endpoints and spoofing headers like User-Agent, screen resolution, and cookies. Traditional CAPTCHAs lost effectiveness as bots generated responses on the fly.
Introducing JWT tokens tied to user sessions, combined with server-side verification, restored control. Yet in competitive niches like real estate, paid form-filling services emerged—people complete quizzes for a fee, skewing conversion metrics.
Behavioral Analysis for Initial Filtering
Timestamps at each quiz stage help detect automated attempts. If response times fall below a threshold (e.g., <2 seconds per question), the lead is flagged as suspicious.
Digital footprint monitoring includes:
- Checking IPs for spikes from data centers.
- Analyzing cookies and fingerprinting (canvas, WebGL, fonts).
- Detecting repeated contacts in the database (threshold >3 per session).
These measures filter out 80–90% of automated spam, but paid attacks bypass them through clean-up and manual execution.
A New Paradigm: Control Over Blocking
Strict blocking triggers adaptation—spammers switch proxies and clear localStorage. Shifting to a 'soft' filtering approach changes the game.
All leads are processed successfully but routed through different scenarios:
- Complete Ignoring: Data isn’t saved in CRM or notifications—leads simply vanish.
- Black Tagging: Stored in an isolated database for analysis, never sent to operational integrations.
- Ghost Conversion: Sent to CRM with a 'spam' flag, but no events tracked in analytics (GA4, Yandex Metrika).
This discourages attackers: no rejection means no feedback, reducing ROI on paid fraud campaigns.
Technical Implementation of the Filter
A Node.js/Express server middleware checks feature vectors:
const fraudScore = calculateFraudScore(req.body, req.headers, sessionData);
if (fraudScore > 0.8) {
routeToBlackhole(req.body); // Scenario 1
} else if (fraudScore > 0.5) {
markAsSpamAndLog(req.body); // Scenario 2
} else if (fraudScore > 0.3) {
sendToCrmWithFlag(req.body); // Scenario 3, no analytics
} else {
processNormally(req.body);
}
function calculateFraudScore(data, headers, session) {
let score = 0;
score += data.quizTime < 30 ? 0.4 : 0; // Quiz time
score += isProxyIP(headers['x-forwarded-for']) ? 0.3 : 0;
score += session.repeatContacts > 2 ? 0.2 : 0;
return score;
}
Fingerprinting via client-side scripts collects entropy: device memory, timezone offset, audio context. Server aggregates data in Redis for real-time cluster detection.
Scaling and Monitoring
For high-load systems, integrate ML models (XGBoost trained on historical lead data). Training on labeled datasets (spam/legit) achieves precision >95% with 90% recall.
Monitor via Grafana dashboards tracking fraud rate and false positives. A/B test scenarios on traffic subsets to minimize risk.
Key Takeaways
- Paid fraud costs 10–50 RUB per lead but inflates CPC in ads by 20–30%.
- Soft filtering reduces attacker motivation without harming UX.
- Combine behavioral analysis with ML for long-term resilience.
- Log everything for post-analysis and model retraining.
- Test thoroughly on real traffic before rollout.
— Editorial Team
No comments yet.