File DA-022 View as Markdown

Browser API

Every method on window.doubleagent, what it returns, and whether it needs a key. Use this page when you write code against the script: reading the verdict, getting a signed token for your server, or protecting a form.

Methods

MethodReturnsNeeds a key
ready()Promise<Verdict>: the provisional verdict, in about 1.5 sNo
verdict()The current Verdict, or null before the first oneNo
on('verdict' | 'final', fn)An unsubscribe function. verdict runs on every new verdict, final on the server-checked oneNo
identify(sha256(userId))Nothing. Send a hash, never the raw id or an emailNo
ecommerce(event, payload)Nothing. GA4-shaped view_item, add_to_cart, begin_checkout, purchase. See EcommerceNo
use(plugin, config?)Nothing. Adds your own plugin. See PluginsNo
flush()Nothing. Sends the session report nowNo
reset({ reload })Promise<Verdict | undefined>. Ends the session and reloads the page. With { reload: false } it starts a new session and resolves with its first verdictNo
push('method', ...args) or push(da => …)Nothing. Queues a call until the script loadsNo
check(action, { signal }?)Promise<Verdict>: the server-checked verdict, with tokenYes
getToken(action?)Promise<string>: a signed token, cached per action until it expires. Defaults to the page's actionYes
stripeToken()Same as getToken('payment')Yes
protect(form, action?)Nothing. Adds a hidden da_token field to the form on submitYes

A verdict's fields are explained in Verdict.

Get a token for your server

const token = await doubleagent.getToken('signup');
await fetch('/api/signup', { method: 'POST', body: JSON.stringify({ email, da_token: token }) });

Or let the script add it to a form:

doubleagent.protect('#signup-form', 'signup');

Your server then verifies the token with @doubleagent-so/node. protect() waits at most 1.5 s for a token; if none arrives, the form submits without one and your server decides.

Errors

SituationWhat happens
No key (keyless install)check(), getToken() and stripeToken() reject, and protect() throws, with DoubleAgentError code key_required. See Capabilities
Cloud off (data-cloud="off")check(), getToken() and stripeToken() reject with code cloud_disabled. protect() does nothing and the form submits as normal. See Plugins
Action name not allowedcheck() throws bad action <name>

Actions

Built in: pageview, search, login, signup, password_reset, add_to_cart, checkout, payment, gift_card, promo, post, message, lead_form, api_key.

You can use your own name too: letters, digits, / and _, up to 64 characters (newsletter, quote/request). A custom action recommends challenge once the chance of a bot or agent reaches 0.8, on every site profile.

Options

init() takes the same options as the script tag's attributes, and more. The full list is in Script tag › Options. The ones most code touches:

doubleagent.init({ key?, profile?, consent?: 'auto' | 'granted' | 'denied', mode?: 'analytics' | 'security',
  block?: { adConversions?: 'bot' | 'bot+agent' | 'none', forms?: boolean }, siteSearch?: boolean, debug? })

siteSearch: false stops site-search terms (on by default).

Calling init({ key }) after a keyless install upgrades the page in place: tokens start working without a reload.

Next: Verify tokens on your server, or Plugins to send verdicts somewhere new.