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.
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