Fraud & Suspicion Detection
Every lead is assigned a suspicion score (0-100) based on multiple signals that indicate bot activity, competitor scraping, or spam submissions.
Suspicion Signals
| Signal | Points | Trigger |
|---|---|---|
| Honeypot filled | +40 | Invisible field has a value (bots fill all fields) |
| Fast submit (<5s) | +30 | Form submitted in under 5 seconds (inhuman speed) |
| Quick submit (5-10s) | +10 | Form submitted between 5-10 seconds (suspicious) |
| No tracking session | +15 | No visitor session found for this visitor_id or IP |
| Zero engagement | +10 | Tracking session exists but engagement score is 0 |
| VPN suspected (high) | +15 | VPN suspicion score > 50 |
| VPN suspected (moderate) | +5 | VPN suspicion score > 20 |
| High form velocity (3+ in 24h) | +20 | 3 or more form submissions from same visitor in 24 hours |
| Moderate form velocity (2 in 24h) | +10 | 2 form submissions from same visitor in 24 hours |
| Competitor email domain | +25 | Email from a known competitor domain |
Maximum possible score: 100 (signals are additive but capped)
How It Works
Honeypot Field
The form builder (/form.js) injects an invisible field named __pg_website that is:
- Positioned off-screen (
left: -9999px) - Hidden with
aria-hidden="true" - Has
tabindex="-1"andautocomplete="off"
Real users never see or fill this field. Automated bots that fill all fields will trigger a +40 suspicion score.
Time-to-Submit
The form records Date.now() when the form renders and calculates the elapsed seconds when the user submits. This is sent as __pg_tts.
- Under 5 seconds: +30 (bot speed — no human reads a form this fast)
- 5-10 seconds: +10 (suspicious — most real users take 15-30 seconds)
Multi-Form Tracking
countRecentSubmissions() queries the Leads table for submissions by the same VisitorId or ContactIP within the last 24 hours. The count is stored as FormSubmitCount on each lead.
- 2 submissions in 24h: +10
- 3+ submissions in 24h: +20
Note: Multiple submissions can be legitimate when a visitor inquires about multiple projects on the same page.
Competitor Email Detection
The system checks the email domain against a configurable list of known competitor domains. Leads from competitor emails receive +25 suspicion.
Data Stored
| Column | Type | Description |
|---|---|---|
SuspicionScore | REAL | Composite score 0-100 |
SuspicionReasons | TEXT | Comma-separated list of triggered signals |
TimeToSubmit | INTEGER | Seconds between form render and submit |
FormSubmitCount | INTEGER | Number of submissions by this visitor in 24h (including current) |
Usage in CRM
The suspicion score is included in the webhook payload to Make.com:
{
"suspicion_score": 55,
"suspicion_reasons": "fast_submit,no_tracking_session,form_velocity_high",
"time_to_submit": 3,
"form_submit_count": 4
}Sales teams can use this to:
- Auto-archive leads with suspicion > 70
- Flag for review leads with suspicion 30-70
- Prioritize leads with suspicion 0 + high engagement score
D1 Schema (Migration 006)
ALTER TABLE Leads ADD COLUMN FormSubmitCount INTEGER DEFAULT 1;
ALTER TABLE Leads ADD COLUMN SuspicionScore REAL DEFAULT 0;
ALTER TABLE Leads ADD COLUMN SuspicionReasons TEXT;
ALTER TABLE Leads ADD COLUMN TimeToSubmit INTEGER DEFAULT 0;