Fraud Prevention Web SDK
The Fraud Prevention Web SDK runs on your page — a landing page, a signup or login screen, or any protected resource. It requests a verdict for the current visit and hands it back to your code, so you can decide what to do with the traffic — record it, flag it, or ask the visitor for one extra verification.
Quick start
<!-- Load the Fraud Prevention SDK -->
<script src="https://cdn.captcha-cdn.net/bot-signal.js"></script>
<script>
BotSignal.init({
appKey: 'YOUR_APP_KEY',
onVerdict: function (verdict) {
// verdict.is_bot, verdict.score, verdict.action — see Verdict Reference
if (verdict.is_bot) {
// exclude this visit from your funnel / suppress conversions
}
},
onError: function (err) {
console.error('bot-signal error', err);
},
});
</script>BotSignal.init() returns a Promise<BotVerdict> as well, so you can also await it instead of using onVerdict — both receive the same verdict object.
const verdict = await BotSignal.init({ appKey: 'YOUR_APP_KEY' });Options
| option | type | default | description |
|---|---|---|---|
appKey | string | — | Required. Your Fraud Prevention app key. |
domain | string | signal-v1.world-dynamic.com | Signal domain the SDK posts to. |
tokenParam | string | _ctk | URL query parameter the SDK reads the click token from. |
onVerdict | (v) => void | — | Called once with the final verdict. The primary integration point. init() also returns Promise<BotVerdict>. |
onError | (err) => void | — | Called on any failure. The SDK never throws into your page. |
onChallenge | (v) => creds | null | Promise<…> | — | Override the escalation credentials: return your own { appKey, serverToken } (serverToken issued by your backend), or null to skip escalation. If unset, the backend-issued default creds in verdict.escalate are used (zero-config). |
challengeConfig | object | — | Captcha appearance/placement: product (popup/float/embed), container, theme, lang. |
onEscalate | (displayType) => void | — | Called when an escalation captcha is shown. |
onEscalateDone | (passed, detail) => void | — | Called after escalation. passed = visitor cleared it; detail = { token, challengeId, cid } for server-side verification of the pass. |
Escalation is server-driven. The SDK shows a captcha only when the server's verdict action is challenge and the app is configured with a matching escalation action — there is no client-side toggle for it. Use onChallenge to supply your own credentials or to skip escalation, and challengeConfig to control its appearance. After a visitor passes, verify the result on your own backend with detail.token (plus challenge_id/cid) — don't trust the client-side passed flag alone.
Traffic-source scenarios
If a third party delivers visitors to you and both sides need to reconcile on a per-click conclusion, the SDK can also read a click token from the page URL. That is specific to paid-traffic flows — see the Ad fraud guide.
Using the verdict
onVerdict receives a BotVerdict object. The two fields you will use most:
verdict.is_bot—truewhen the visit is judged to be automated/invalid.verdict.action— what we recommend you do:record_only,challenge, orflag.
BotSignal.init({
appKey: 'YOUR_APP_KEY',
onVerdict: function (verdict) {
switch (verdict.action) {
case 'record_only':
// normal-looking traffic — proceed, just log the verdict
break;
case 'flag':
// suspicious — keep serving the page but mark this visit as low quality
markLowQuality(verdict);
break;
case 'challenge':
// high risk — handled by escalation if enabled (see below)
break;
}
},
});See the full field list and recommended handling in the Verdict Reference.
Escalation
When a visit looks high-risk, Fraud Prevention can ask the visitor to complete one additional verification before you treat them as a real user. This is driven by the server verdict, not a client-side flag — it runs whenever the verdict action is challenge and the app has an escalation action configured.
BotSignal.init({
appKey: 'YOUR_APP_KEY',
onEscalate: function (displayType) {
// an extra verification is being shown to the visitor
},
onEscalateDone: function (passed, detail) {
if (passed) {
// visitor cleared the extra check — verify detail.token on your backend
} else {
// not cleared — keep the original verdict's recommendation
}
},
onVerdict: function (verdict) {
// if the visitor cleared escalation, verdict.is_bot is updated to false
},
});Notes:
- Escalation only triggers when the verdict's
actionischallenge. For all other visits nothing is shown and the visitor experience is untouched. - By default the SDK uses the backend-issued credentials in
verdict.escalate(zero-config). UseonChallengeto supply your own{ appKey, serverToken }or to skip escalation, andchallengeConfigto control its appearance. - After a pass, verify
detail.token(pluschallenge_id/cid) on your own backend — don't trust the client-sidepassedflag alone. - If the visitor clears the extra verification, the verdict delivered to
onVerdictreflects that (treated as human). - Escalation fails open: if the extra verification can't be loaded or shown, the SDK keeps the original verdict rather than blocking your page.
INFO
Fraud Prevention never decides for you. Even on challenge/flag, your code stays in control of whether the visit proceeds — the SDK only surfaces the verdict and, optionally, runs the extra verification.
The risk level that triggers escalation (high by default, medium in strict mode) and the minimum CAPTCHA type are set per app in the dashboard — see Challenge threshold and type. onEscalate receives the type that is actually shown.
Resilience
If the verdict service is unreachable or any error occurs, the SDK returns a degraded verdict (degraded: true) instead of failing your page. A degraded verdict is conservative (is_bot: false, action: record_only) so it never blocks real users. Check verdict.degraded if you want to treat those visits specially.
Next steps
- Verdict Reference — every field and how to act on it
- Data API — pull and reconcile verdicts server-side