@formguard/sdk 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +842 -0
- package/dist/formguard.esm.js +235 -0
- package/dist/formguard.esm.js.map +1 -0
- package/dist/formguard.js +243 -0
- package/dist/formguard.js.map +1 -0
- package/dist/index.d.ts +76 -0
- package/package.json +45 -0
package/README.md
ADDED
|
@@ -0,0 +1,842 @@
|
|
|
1
|
+
# FormGuard SDK
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@formguard/sdk)
|
|
4
|
+
[](https://www.npmjs.com/package/@formguard/sdk)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
[](https://github.com/OmAiR1Kh/formguard-sdk/stargazers)
|
|
7
|
+
|
|
8
|
+
JavaScript SDK for FormGuard - Stop wasting time on fake form submissions. Detect bots, score lead quality, and track drop-offs automatically.
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
✅ **Lead Quality Scoring** - Automatically score every submission 0-100
|
|
13
|
+
✅ **Bot Detection** - Detect VPNs, proxies, and disposable emails
|
|
14
|
+
✅ **Drop-off Tracking** - See exactly where users abandon your forms
|
|
15
|
+
✅ **Multi-step Forms** - Track progress through complex forms
|
|
16
|
+
✅ **Real-time Actions** - Block, flag, or allow submissions instantly
|
|
17
|
+
✅ **Lightweight** - Only 9KB minified
|
|
18
|
+
✅ **Framework Agnostic** - Works with React, Vue, Angular, vanilla JS
|
|
19
|
+
✅ **TypeScript Support** - Full type definitions included
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
### Via NPM
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install @formguard/sdk
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Via Yarn
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
yarn add @formguard/sdk
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Via CDN
|
|
38
|
+
|
|
39
|
+
```html
|
|
40
|
+
<script src="https://cdn.jsdelivr.net/npm/@formguard/sdk@latest/dist/formguard.js"></script>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Quick Start
|
|
46
|
+
|
|
47
|
+
### 1. Get Your API Key
|
|
48
|
+
|
|
49
|
+
Sign up at [formguard.com](https://formguard.com) and create a form to get your API key.
|
|
50
|
+
|
|
51
|
+
### 2. Basic Usage (Vanilla JavaScript)
|
|
52
|
+
|
|
53
|
+
```html
|
|
54
|
+
<!DOCTYPE html>
|
|
55
|
+
<html>
|
|
56
|
+
<head>
|
|
57
|
+
<title>Contact Form</title>
|
|
58
|
+
</head>
|
|
59
|
+
<body>
|
|
60
|
+
<form id="contactForm">
|
|
61
|
+
<input type="email" name="email" placeholder="Email" required />
|
|
62
|
+
<input type="text" name="name" placeholder="Name" required />
|
|
63
|
+
<button type="submit">Submit</button>
|
|
64
|
+
</form>
|
|
65
|
+
|
|
66
|
+
<!-- Load FormGuard SDK -->
|
|
67
|
+
<script src="https://cdn.jsdelivr.net/npm/@formguard/sdk@latest/dist/formguard.js"></script>
|
|
68
|
+
|
|
69
|
+
<script>
|
|
70
|
+
// Initialize FormGuard
|
|
71
|
+
FormGuard.init("fg_live_your_api_key_here");
|
|
72
|
+
|
|
73
|
+
// Handle form submission
|
|
74
|
+
document
|
|
75
|
+
.getElementById("contactForm")
|
|
76
|
+
.addEventListener("submit", async (e) => {
|
|
77
|
+
e.preventDefault();
|
|
78
|
+
|
|
79
|
+
const form = e.target;
|
|
80
|
+
|
|
81
|
+
try {
|
|
82
|
+
const result = await FormGuard.submit({
|
|
83
|
+
email: form.email.value,
|
|
84
|
+
fields: {
|
|
85
|
+
name: form.name.value,
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
if (result.allowed) {
|
|
90
|
+
// ✅ High quality submission - proceed
|
|
91
|
+
console.log("Quality Score:", result.qualityScore);
|
|
92
|
+
form.submit();
|
|
93
|
+
} else if (result.action === "flagged") {
|
|
94
|
+
// ⚠️ Low quality - review manually
|
|
95
|
+
console.log("Submission flagged for review");
|
|
96
|
+
alert("Your submission will be reviewed");
|
|
97
|
+
} else {
|
|
98
|
+
// 🚫 Blocked - likely spam
|
|
99
|
+
console.log("Submission blocked");
|
|
100
|
+
alert("Submission blocked due to quality concerns");
|
|
101
|
+
}
|
|
102
|
+
} catch (error) {
|
|
103
|
+
console.error("FormGuard error:", error);
|
|
104
|
+
// Fail open - allow submission if FormGuard fails
|
|
105
|
+
form.submit();
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
</script>
|
|
109
|
+
</body>
|
|
110
|
+
</html>
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Framework Examples
|
|
116
|
+
|
|
117
|
+
### React / Next.js
|
|
118
|
+
|
|
119
|
+
```tsx
|
|
120
|
+
import { useEffect } from "react";
|
|
121
|
+
import FormGuard from "@formguard/sdk";
|
|
122
|
+
|
|
123
|
+
function ContactForm() {
|
|
124
|
+
useEffect(() => {
|
|
125
|
+
FormGuard.init({
|
|
126
|
+
apiKey: "fg_live_your_api_key_here",
|
|
127
|
+
debug: process.env.NODE_ENV === "development",
|
|
128
|
+
});
|
|
129
|
+
}, []);
|
|
130
|
+
|
|
131
|
+
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
|
132
|
+
e.preventDefault();
|
|
133
|
+
const form = e.currentTarget;
|
|
134
|
+
|
|
135
|
+
try {
|
|
136
|
+
const result = await FormGuard.submit({
|
|
137
|
+
email: form.email.value,
|
|
138
|
+
fields: {
|
|
139
|
+
name: form.name.value,
|
|
140
|
+
company: form.company.value,
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
if (result.allowed) {
|
|
145
|
+
// Process the form
|
|
146
|
+
console.log("Quality Score:", result.qualityScore);
|
|
147
|
+
} else {
|
|
148
|
+
alert(`Submission ${result.action}: Score ${result.qualityScore}`);
|
|
149
|
+
}
|
|
150
|
+
} catch (error) {
|
|
151
|
+
console.error("FormGuard error:", error);
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
return (
|
|
156
|
+
<form onSubmit={handleSubmit}>
|
|
157
|
+
<input name="email" type="email" placeholder="Email" required />
|
|
158
|
+
<input name="name" type="text" placeholder="Name" required />
|
|
159
|
+
<input name="company" type="text" placeholder="Company" />
|
|
160
|
+
<button type="submit">Submit</button>
|
|
161
|
+
</form>
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export default ContactForm;
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Vue.js
|
|
169
|
+
|
|
170
|
+
```vue
|
|
171
|
+
<template>
|
|
172
|
+
<form @submit.prevent="handleSubmit">
|
|
173
|
+
<input v-model="email" type="email" placeholder="Email" required />
|
|
174
|
+
<input v-model="name" type="text" placeholder="Name" required />
|
|
175
|
+
<button type="submit">Submit</button>
|
|
176
|
+
</form>
|
|
177
|
+
</template>
|
|
178
|
+
|
|
179
|
+
<script>
|
|
180
|
+
import FormGuard from "@formguard/sdk";
|
|
181
|
+
|
|
182
|
+
export default {
|
|
183
|
+
data() {
|
|
184
|
+
return {
|
|
185
|
+
email: "",
|
|
186
|
+
name: "",
|
|
187
|
+
};
|
|
188
|
+
},
|
|
189
|
+
mounted() {
|
|
190
|
+
FormGuard.init({
|
|
191
|
+
apiKey: "fg_live_your_api_key_here",
|
|
192
|
+
debug: true,
|
|
193
|
+
});
|
|
194
|
+
},
|
|
195
|
+
methods: {
|
|
196
|
+
async handleSubmit() {
|
|
197
|
+
try {
|
|
198
|
+
const result = await FormGuard.submit({
|
|
199
|
+
email: this.email,
|
|
200
|
+
fields: {
|
|
201
|
+
name: this.name,
|
|
202
|
+
},
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
if (result.allowed) {
|
|
206
|
+
console.log("Quality Score:", result.qualityScore);
|
|
207
|
+
// Process form
|
|
208
|
+
} else {
|
|
209
|
+
alert(`Submission ${result.action}`);
|
|
210
|
+
}
|
|
211
|
+
} catch (error) {
|
|
212
|
+
console.error("FormGuard error:", error);
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
},
|
|
216
|
+
};
|
|
217
|
+
</script>
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Angular
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
import { Component, OnInit } from "@angular/core";
|
|
224
|
+
import FormGuard from "@formguard/sdk";
|
|
225
|
+
|
|
226
|
+
@Component({
|
|
227
|
+
selector: "app-contact-form",
|
|
228
|
+
template: `
|
|
229
|
+
<form (ngSubmit)="onSubmit()">
|
|
230
|
+
<input
|
|
231
|
+
[(ngModel)]="email"
|
|
232
|
+
name="email"
|
|
233
|
+
type="email"
|
|
234
|
+
placeholder="Email"
|
|
235
|
+
required
|
|
236
|
+
/>
|
|
237
|
+
<input
|
|
238
|
+
[(ngModel)]="name"
|
|
239
|
+
name="name"
|
|
240
|
+
type="text"
|
|
241
|
+
placeholder="Name"
|
|
242
|
+
required
|
|
243
|
+
/>
|
|
244
|
+
<button type="submit">Submit</button>
|
|
245
|
+
</form>
|
|
246
|
+
`,
|
|
247
|
+
})
|
|
248
|
+
export class ContactFormComponent implements OnInit {
|
|
249
|
+
email = "";
|
|
250
|
+
name = "";
|
|
251
|
+
|
|
252
|
+
ngOnInit() {
|
|
253
|
+
FormGuard.init({
|
|
254
|
+
apiKey: "fg_live_your_api_key_here",
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
async onSubmit() {
|
|
259
|
+
try {
|
|
260
|
+
const result = await FormGuard.submit({
|
|
261
|
+
email: this.email,
|
|
262
|
+
fields: {
|
|
263
|
+
name: this.name,
|
|
264
|
+
},
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
if (result.allowed) {
|
|
268
|
+
console.log("Quality Score:", result.qualityScore);
|
|
269
|
+
} else {
|
|
270
|
+
alert(`Submission ${result.action}`);
|
|
271
|
+
}
|
|
272
|
+
} catch (error) {
|
|
273
|
+
console.error("FormGuard error:", error);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
## Advanced Usage
|
|
282
|
+
|
|
283
|
+
### Multi-Step Forms
|
|
284
|
+
|
|
285
|
+
Track user progress through multi-step forms to identify drop-off points:
|
|
286
|
+
|
|
287
|
+
```javascript
|
|
288
|
+
FormGuard.init("fg_live_your_api_key_here");
|
|
289
|
+
|
|
290
|
+
// Track when user completes each step
|
|
291
|
+
function goToStep(stepNumber) {
|
|
292
|
+
FormGuard.trackStep(stepNumber);
|
|
293
|
+
showStep(stepNumber);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// Track field validation errors
|
|
297
|
+
function validateEmail(email) {
|
|
298
|
+
if (!isValidEmail(email)) {
|
|
299
|
+
FormGuard.trackError("email", "Invalid email format");
|
|
300
|
+
return false;
|
|
301
|
+
}
|
|
302
|
+
return true;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// Track when user abandons the form
|
|
306
|
+
window.addEventListener("beforeunload", () => {
|
|
307
|
+
const currentStep = getCurrentStep();
|
|
308
|
+
FormGuard.trackDropOff(currentStep);
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
// Final submission
|
|
312
|
+
async function submitForm() {
|
|
313
|
+
const result = await FormGuard.submit({
|
|
314
|
+
email: form.email.value,
|
|
315
|
+
fields: getAllFormData(),
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
if (result.allowed) {
|
|
319
|
+
// Process submission
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### Custom Completion Time
|
|
325
|
+
|
|
326
|
+
By default, FormGuard tracks completion time from initialization. You can override this:
|
|
327
|
+
|
|
328
|
+
```javascript
|
|
329
|
+
const startTime = Date.now();
|
|
330
|
+
|
|
331
|
+
// ... user fills form ...
|
|
332
|
+
|
|
333
|
+
const completionTime = Math.floor((Date.now() - startTime) / 1000); // seconds
|
|
334
|
+
|
|
335
|
+
const result = await FormGuard.submit({
|
|
336
|
+
email: form.email.value,
|
|
337
|
+
fields: { name: form.name.value },
|
|
338
|
+
completionTime: completionTime,
|
|
339
|
+
});
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
### Custom Device/Browser Detection
|
|
343
|
+
|
|
344
|
+
Override automatic detection:
|
|
345
|
+
|
|
346
|
+
```javascript
|
|
347
|
+
const result = await FormGuard.submit({
|
|
348
|
+
email: form.email.value,
|
|
349
|
+
fields: { name: form.name.value },
|
|
350
|
+
device: "Mobile", // or 'Desktop', 'Tablet'
|
|
351
|
+
browser: "Chrome", // or 'Firefox', 'Safari', etc.
|
|
352
|
+
});
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### Debug Mode
|
|
356
|
+
|
|
357
|
+
Enable debug logging to see what's happening:
|
|
358
|
+
|
|
359
|
+
```javascript
|
|
360
|
+
FormGuard.init({
|
|
361
|
+
apiKey: "fg_live_your_api_key_here",
|
|
362
|
+
debug: true, // Logs all events to console
|
|
363
|
+
});
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### Custom API URL (Self-Hosted)
|
|
367
|
+
|
|
368
|
+
If you're self-hosting FormGuard:
|
|
369
|
+
|
|
370
|
+
```javascript
|
|
371
|
+
FormGuard.init({
|
|
372
|
+
apiKey: "fg_live_your_api_key_here",
|
|
373
|
+
apiUrl: "https://your-api-domain.com/api/v1/ingestion",
|
|
374
|
+
});
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
---
|
|
378
|
+
|
|
379
|
+
## API Reference
|
|
380
|
+
|
|
381
|
+
### `FormGuard.init(config)`
|
|
382
|
+
|
|
383
|
+
Initialize the SDK. Must be called before any other methods.
|
|
384
|
+
|
|
385
|
+
**Parameters:**
|
|
386
|
+
|
|
387
|
+
```typescript
|
|
388
|
+
config: string | {
|
|
389
|
+
apiKey: string; // Required: Your FormGuard API key
|
|
390
|
+
apiUrl?: string; // Optional: Custom API URL
|
|
391
|
+
debug?: boolean; // Optional: Enable debug logging
|
|
392
|
+
}
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
**Example:**
|
|
396
|
+
|
|
397
|
+
```javascript
|
|
398
|
+
// Simple initialization
|
|
399
|
+
FormGuard.init("fg_live_your_api_key_here");
|
|
400
|
+
|
|
401
|
+
// With options
|
|
402
|
+
FormGuard.init({
|
|
403
|
+
apiKey: "fg_live_your_api_key_here",
|
|
404
|
+
debug: true,
|
|
405
|
+
apiUrl: "https://custom-api.com/api/v1/ingestion",
|
|
406
|
+
});
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
---
|
|
410
|
+
|
|
411
|
+
### `FormGuard.submit(data)`
|
|
412
|
+
|
|
413
|
+
Submit form data for quality analysis.
|
|
414
|
+
|
|
415
|
+
**Parameters:**
|
|
416
|
+
|
|
417
|
+
```typescript
|
|
418
|
+
data: {
|
|
419
|
+
email: string; // Required: User's email
|
|
420
|
+
fields: Record<string, any>; // Required: All form fields
|
|
421
|
+
completionTime?: number; // Optional: Time in seconds
|
|
422
|
+
device?: string; // Optional: 'Desktop' | 'Mobile' | 'Tablet'
|
|
423
|
+
browser?: string; // Optional: Browser name
|
|
424
|
+
}
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
**Returns:** `Promise<SubmissionResponse>`
|
|
428
|
+
|
|
429
|
+
```typescript
|
|
430
|
+
{
|
|
431
|
+
success: boolean;
|
|
432
|
+
allowed: boolean; // true if submission should proceed
|
|
433
|
+
action: "allowed" | "flagged" | "blocked";
|
|
434
|
+
qualityScore: number; // 0-100
|
|
435
|
+
flags: {
|
|
436
|
+
vpn: boolean;
|
|
437
|
+
proxy: boolean;
|
|
438
|
+
disposableEmail: boolean;
|
|
439
|
+
duplicate: boolean;
|
|
440
|
+
fastCompletion: boolean;
|
|
441
|
+
}
|
|
442
|
+
submissionId: string; // Unique submission ID
|
|
443
|
+
}
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
**Example:**
|
|
447
|
+
|
|
448
|
+
```javascript
|
|
449
|
+
const result = await FormGuard.submit({
|
|
450
|
+
email: "user@example.com",
|
|
451
|
+
fields: {
|
|
452
|
+
name: "John Doe",
|
|
453
|
+
company: "Acme Inc",
|
|
454
|
+
message: "Hello world",
|
|
455
|
+
},
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
console.log("Quality Score:", result.qualityScore);
|
|
459
|
+
console.log("Action:", result.action);
|
|
460
|
+
console.log("Flags:", result.flags);
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
---
|
|
464
|
+
|
|
465
|
+
### `FormGuard.trackStep(step)`
|
|
466
|
+
|
|
467
|
+
Track when a user completes a step in a multi-step form.
|
|
468
|
+
|
|
469
|
+
**Parameters:**
|
|
470
|
+
|
|
471
|
+
- `step` (number): The step number (1, 2, 3, etc.)
|
|
472
|
+
|
|
473
|
+
**Example:**
|
|
474
|
+
|
|
475
|
+
```javascript
|
|
476
|
+
FormGuard.trackStep(1); // User completed step 1
|
|
477
|
+
FormGuard.trackStep(2); // User completed step 2
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
---
|
|
481
|
+
|
|
482
|
+
### `FormGuard.trackError(field, errorMessage?)`
|
|
483
|
+
|
|
484
|
+
Track field validation errors.
|
|
485
|
+
|
|
486
|
+
**Parameters:**
|
|
487
|
+
|
|
488
|
+
- `field` (string): Name of the field with the error
|
|
489
|
+
- `errorMessage` (string, optional): Description of the error
|
|
490
|
+
|
|
491
|
+
**Example:**
|
|
492
|
+
|
|
493
|
+
```javascript
|
|
494
|
+
FormGuard.trackError("email", "Invalid email format");
|
|
495
|
+
FormGuard.trackError("phone", "Phone number required");
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
---
|
|
499
|
+
|
|
500
|
+
### `FormGuard.trackDropOff(step?, field?)`
|
|
501
|
+
|
|
502
|
+
Track when a user abandons the form.
|
|
503
|
+
|
|
504
|
+
**Parameters:**
|
|
505
|
+
|
|
506
|
+
- `step` (number, optional): The step where they dropped off
|
|
507
|
+
- `field` (string, optional): The field they were on
|
|
508
|
+
|
|
509
|
+
**Example:**
|
|
510
|
+
|
|
511
|
+
```javascript
|
|
512
|
+
// On page unload
|
|
513
|
+
window.addEventListener("beforeunload", () => {
|
|
514
|
+
FormGuard.trackDropOff(2, "phone");
|
|
515
|
+
});
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
---
|
|
519
|
+
|
|
520
|
+
## Understanding Quality Scores
|
|
521
|
+
|
|
522
|
+
FormGuard assigns each submission a quality score from 0-100 based on multiple signals:
|
|
523
|
+
|
|
524
|
+
### Scoring Factors
|
|
525
|
+
|
|
526
|
+
| Signal | Impact | Description |
|
|
527
|
+
| ------------------------ | ------ | ------------------------------------------ |
|
|
528
|
+
| **Disposable Email** | -30 | Uses tempmail.com, guerrillamail.com, etc. |
|
|
529
|
+
| **VPN Detection** | -25 | Submission comes through a VPN |
|
|
530
|
+
| **Proxy Detection** | -25 | Submission comes through a proxy |
|
|
531
|
+
| **Fast Completion** | -20 | Form completed in less than 5 seconds |
|
|
532
|
+
| **Duplicate Submission** | -15 | Same email submitted within 24 hours |
|
|
533
|
+
| **Country Mismatch** | -10 | Location doesn't match expected country |
|
|
534
|
+
|
|
535
|
+
### Score Ranges
|
|
536
|
+
|
|
537
|
+
- **80-100**: High quality lead ✅
|
|
538
|
+
- **50-79**: Medium quality - worth following up 📧
|
|
539
|
+
- **20-49**: Low quality - likely spam ⚠️
|
|
540
|
+
- **0-19**: Very low quality - almost certainly fake 🚫
|
|
541
|
+
|
|
542
|
+
### Actions
|
|
543
|
+
|
|
544
|
+
Based on your form settings and the quality score:
|
|
545
|
+
|
|
546
|
+
- **allowed**: Submission passes all checks
|
|
547
|
+
- **flagged**: Low score, review manually
|
|
548
|
+
- **blocked**: Very low score or triggered auto-block rule
|
|
549
|
+
|
|
550
|
+
---
|
|
551
|
+
|
|
552
|
+
## Dashboard Features
|
|
553
|
+
|
|
554
|
+
View detailed analytics in your FormGuard dashboard:
|
|
555
|
+
|
|
556
|
+
- 📊 **Quality Score Distribution** - See the breakdown of submission quality
|
|
557
|
+
- 📉 **Drop-off Analysis** - Identify where users abandon your forms
|
|
558
|
+
- 🚨 **Flagged Submissions** - Review suspicious submissions
|
|
559
|
+
- 🔍 **Field Error Tracking** - See which fields cause the most problems
|
|
560
|
+
- 📈 **Submission Trends** - Track submissions over time
|
|
561
|
+
- 🌍 **Geographic Data** - See where your submissions come from
|
|
562
|
+
- 🤖 **Bot Detection Stats** - Monitor VPN, proxy, and disposable email usage
|
|
563
|
+
|
|
564
|
+
---
|
|
565
|
+
|
|
566
|
+
## Best Practices
|
|
567
|
+
|
|
568
|
+
### 1. Fail Open, Not Closed
|
|
569
|
+
|
|
570
|
+
Always handle errors gracefully. If FormGuard fails, allow the submission:
|
|
571
|
+
|
|
572
|
+
```javascript
|
|
573
|
+
try {
|
|
574
|
+
const result = await FormGuard.submit({ ... });
|
|
575
|
+
if (result.allowed) {
|
|
576
|
+
processForm();
|
|
577
|
+
}
|
|
578
|
+
} catch (error) {
|
|
579
|
+
console.error('FormGuard error:', error);
|
|
580
|
+
// Still process the form
|
|
581
|
+
processForm();
|
|
582
|
+
}
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
### 2. Show User-Friendly Messages
|
|
586
|
+
|
|
587
|
+
Don't expose technical details to users:
|
|
588
|
+
|
|
589
|
+
```javascript
|
|
590
|
+
if (result.action === 'blocked') {
|
|
591
|
+
alert('We couldn't process your submission. Please contact support.');
|
|
592
|
+
} else if (result.action === 'flagged') {
|
|
593
|
+
alert('Your submission is under review. We\'ll get back to you soon.');
|
|
594
|
+
}
|
|
595
|
+
```
|
|
596
|
+
|
|
597
|
+
### 3. Review Flagged Submissions
|
|
598
|
+
|
|
599
|
+
Don't automatically reject flagged submissions. Review them in your dashboard first.
|
|
600
|
+
|
|
601
|
+
### 4. Adjust Thresholds Based on Your Needs
|
|
602
|
+
|
|
603
|
+
In the dashboard, customize:
|
|
604
|
+
|
|
605
|
+
- Auto-block threshold
|
|
606
|
+
- VPN blocking
|
|
607
|
+
- Disposable email blocking
|
|
608
|
+
|
|
609
|
+
Different forms have different needs. A newsletter signup can be more lenient than a demo request form.
|
|
610
|
+
|
|
611
|
+
### 5. Track Everything in Multi-Step Forms
|
|
612
|
+
|
|
613
|
+
The more data you send, the better insights you get:
|
|
614
|
+
|
|
615
|
+
```javascript
|
|
616
|
+
// Track all steps
|
|
617
|
+
FormGuard.trackStep(1);
|
|
618
|
+
FormGuard.trackStep(2);
|
|
619
|
+
FormGuard.trackStep(3);
|
|
620
|
+
|
|
621
|
+
// Track all errors
|
|
622
|
+
FormGuard.trackError("email");
|
|
623
|
+
FormGuard.trackError("phone");
|
|
624
|
+
|
|
625
|
+
// Track drop-offs
|
|
626
|
+
window.addEventListener("beforeunload", () => {
|
|
627
|
+
FormGuard.trackDropOff(currentStep);
|
|
628
|
+
});
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
---
|
|
632
|
+
|
|
633
|
+
## TypeScript Support
|
|
634
|
+
|
|
635
|
+
Full TypeScript definitions are included:
|
|
636
|
+
|
|
637
|
+
```typescript
|
|
638
|
+
import FormGuard from "@formguard/sdk";
|
|
639
|
+
|
|
640
|
+
interface FormData {
|
|
641
|
+
email: string;
|
|
642
|
+
name: string;
|
|
643
|
+
company?: string;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
const handleSubmit = async (data: FormData) => {
|
|
647
|
+
const result = await FormGuard.submit({
|
|
648
|
+
email: data.email,
|
|
649
|
+
fields: {
|
|
650
|
+
name: data.name,
|
|
651
|
+
company: data.company,
|
|
652
|
+
},
|
|
653
|
+
});
|
|
654
|
+
|
|
655
|
+
// result is fully typed
|
|
656
|
+
console.log(result.qualityScore); // number
|
|
657
|
+
console.log(result.action); // 'allowed' | 'flagged' | 'blocked'
|
|
658
|
+
console.log(result.flags.vpn); // boolean
|
|
659
|
+
};
|
|
660
|
+
```
|
|
661
|
+
|
|
662
|
+
---
|
|
663
|
+
|
|
664
|
+
## Browser Support
|
|
665
|
+
|
|
666
|
+
FormGuard SDK works in all modern browsers:
|
|
667
|
+
|
|
668
|
+
- ✅ Chrome (latest)
|
|
669
|
+
- ✅ Firefox (latest)
|
|
670
|
+
- ✅ Safari (latest)
|
|
671
|
+
- ✅ Edge (latest)
|
|
672
|
+
- ✅ Opera (latest)
|
|
673
|
+
- ✅ Mobile browsers (iOS Safari, Chrome Mobile)
|
|
674
|
+
|
|
675
|
+
Minimum requirements:
|
|
676
|
+
|
|
677
|
+
- ES2015+ support
|
|
678
|
+
- Fetch API
|
|
679
|
+
- Promise support
|
|
680
|
+
|
|
681
|
+
For older browsers, include polyfills.
|
|
682
|
+
|
|
683
|
+
---
|
|
684
|
+
|
|
685
|
+
## Security & Privacy
|
|
686
|
+
|
|
687
|
+
### Data Collection
|
|
688
|
+
|
|
689
|
+
FormGuard collects:
|
|
690
|
+
|
|
691
|
+
- ✅ Email address
|
|
692
|
+
- ✅ Form field data you send
|
|
693
|
+
- ✅ IP address (for fraud detection)
|
|
694
|
+
- ✅ Device type and browser
|
|
695
|
+
- ✅ Completion time
|
|
696
|
+
- ❌ No passwords
|
|
697
|
+
- ❌ No payment information
|
|
698
|
+
- ❌ No tracking across sites
|
|
699
|
+
|
|
700
|
+
### GDPR Compliance
|
|
701
|
+
|
|
702
|
+
FormGuard is GDPR compliant:
|
|
703
|
+
|
|
704
|
+
- Data is encrypted in transit and at rest
|
|
705
|
+
- Users can request data deletion
|
|
706
|
+
- Data retention policies in place
|
|
707
|
+
- Privacy policy available at formguard.com/privacy
|
|
708
|
+
|
|
709
|
+
### Data Storage
|
|
710
|
+
|
|
711
|
+
- Data is stored securely in encrypted databases
|
|
712
|
+
- We don't sell or share your data
|
|
713
|
+
- You can export or delete your data anytime
|
|
714
|
+
|
|
715
|
+
---
|
|
716
|
+
|
|
717
|
+
## FAQ
|
|
718
|
+
|
|
719
|
+
### How much does FormGuard cost?
|
|
720
|
+
|
|
721
|
+
See pricing at [formguard.com/pricing](https://formguard.com/pricing)
|
|
722
|
+
|
|
723
|
+
- **Free**: 100 submissions/month
|
|
724
|
+
- **Starter**: $9/mo - 1,000 submissions
|
|
725
|
+
- **Pro**: $29/mo - 5,000 submissions
|
|
726
|
+
- **Agency**: $79/mo - 20,000 submissions
|
|
727
|
+
|
|
728
|
+
### Does FormGuard slow down my forms?
|
|
729
|
+
|
|
730
|
+
No. The SDK is only 9KB and all API calls are asynchronous. Average response time is under 200ms.
|
|
731
|
+
|
|
732
|
+
### What happens if FormGuard is down?
|
|
733
|
+
|
|
734
|
+
The SDK has built-in error handling. If the API is unreachable, the SDK will fail gracefully and your forms will continue to work.
|
|
735
|
+
|
|
736
|
+
### Can I use FormGuard with any form?
|
|
737
|
+
|
|
738
|
+
Yes! FormGuard works with:
|
|
739
|
+
|
|
740
|
+
- Custom HTML forms
|
|
741
|
+
- React forms
|
|
742
|
+
- Vue forms
|
|
743
|
+
- Angular forms
|
|
744
|
+
- WordPress forms
|
|
745
|
+
- Any JavaScript-based form
|
|
746
|
+
|
|
747
|
+
### Do I need a backend?
|
|
748
|
+
|
|
749
|
+
No. FormGuard handles all the processing. You just need to integrate the SDK in your frontend.
|
|
750
|
+
|
|
751
|
+
### Can I self-host FormGuard?
|
|
752
|
+
|
|
753
|
+
Not yet, but we're working on it. Contact us if you're interested.
|
|
754
|
+
|
|
755
|
+
### How accurate is the bot detection?
|
|
756
|
+
|
|
757
|
+
FormGuard uses multiple signals to detect bots:
|
|
758
|
+
|
|
759
|
+
- IP reputation databases
|
|
760
|
+
- Disposable email detection (99%+ accuracy)
|
|
761
|
+
- VPN/proxy detection (95%+ accuracy)
|
|
762
|
+
- Behavioral analysis
|
|
763
|
+
|
|
764
|
+
False positives are rare, and you can always review flagged submissions.
|
|
765
|
+
|
|
766
|
+
---
|
|
767
|
+
|
|
768
|
+
## Support
|
|
769
|
+
|
|
770
|
+
### Documentation
|
|
771
|
+
|
|
772
|
+
Full documentation: [docs.formguard.com](https://docs.formguard.com)
|
|
773
|
+
|
|
774
|
+
### Issues
|
|
775
|
+
|
|
776
|
+
Found a bug? [Open an issue on GitHub](https://github.com/OmAiR1Kh/formguard-sdk/issues)
|
|
777
|
+
|
|
778
|
+
### Email
|
|
779
|
+
|
|
780
|
+
Contact us: support@formguard.com
|
|
781
|
+
|
|
782
|
+
### Community
|
|
783
|
+
|
|
784
|
+
Join our Discord: [discord.gg/formguard](https://discord.gg/formguard)
|
|
785
|
+
|
|
786
|
+
---
|
|
787
|
+
|
|
788
|
+
## Changelog
|
|
789
|
+
|
|
790
|
+
### v1.0.0 (2026-01-01)
|
|
791
|
+
|
|
792
|
+
- 🎉 Initial release
|
|
793
|
+
- ✅ Lead quality scoring
|
|
794
|
+
- ✅ Bot detection (VPN, proxy, disposable email)
|
|
795
|
+
- ✅ Drop-off tracking
|
|
796
|
+
- ✅ Multi-step form support
|
|
797
|
+
- ✅ TypeScript support
|
|
798
|
+
- ✅ Framework agnostic
|
|
799
|
+
|
|
800
|
+
---
|
|
801
|
+
|
|
802
|
+
## License
|
|
803
|
+
|
|
804
|
+
MIT License - see [LICENSE](LICENSE) file for details.
|
|
805
|
+
|
|
806
|
+
---
|
|
807
|
+
|
|
808
|
+
## Contributing
|
|
809
|
+
|
|
810
|
+
Contributions are welcome! Please read our [contributing guidelines](CONTRIBUTING.md) first.
|
|
811
|
+
|
|
812
|
+
1. Fork the repo
|
|
813
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
814
|
+
3. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
815
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
816
|
+
5. Open a Pull Request
|
|
817
|
+
|
|
818
|
+
---
|
|
819
|
+
|
|
820
|
+
## Credits
|
|
821
|
+
|
|
822
|
+
Built with ❤️ by [Omair Khoder](https://github.com/OmAiR1Kh)
|
|
823
|
+
|
|
824
|
+
---
|
|
825
|
+
|
|
826
|
+
## Links
|
|
827
|
+
|
|
828
|
+
- 🌐 Website: [formguard.com](https://formguard.com)
|
|
829
|
+
- 📦 NPM: [@formguard/sdk](https://www.npmjs.com/package/@formguard/sdk)
|
|
830
|
+
- 📚 Documentation: [docs.formguard.com](https://docs.formguard.com)
|
|
831
|
+
- 🐙 GitHub: [github.com/OmAiR1Kh/formguard-sdk](https://github.com/OmAiR1Kh/formguard-sdk)
|
|
832
|
+
- 🐦 Twitter: [@formguard](https://twitter.com/formguard)
|
|
833
|
+
|
|
834
|
+
---
|
|
835
|
+
|
|
836
|
+
**Ready to stop wasting time on fake leads?**
|
|
837
|
+
|
|
838
|
+
```bash
|
|
839
|
+
npm install @formguard/sdk
|
|
840
|
+
```
|
|
841
|
+
|
|
842
|
+
[Get Started →](https://formguard.com/signup)
|