# Widget configuration

> The script tag, every data-* attribute of the declarative widget, render options, callbacks, languages and accessibility.

## The script

```html
<script src="https://agentgate.example/sdk/v1/agentgate.js" async></script>
```

- `/sdk/v1/agentgate.js` is the latest 1.x SDK. A breaking change would get
  `/sdk/v2/`. The loaded version is `AgentGate.version` and is also sent in
  the `X-AgentGate-SDK-Version` response header.
- The SDK talks to the origin that served the script unless you pass an
  `endpoint`.
- The proof of work runs in a Web Worker loaded from
  `/sdk/v1/worker.js` on the same endpoint.
- `async` and `defer` are both fine. Widgets render when the document is
  parsed.

## Declarative widget

Any element with the class `agentgate` and a `data-sitekey` attribute
becomes a widget when the document is ready:

```html
<form method="post" action="/signup">
  <input name="email" type="email" required>
  <div class="agentgate" data-sitekey="site_…" data-action="signup"
       data-mode="managed" data-lang="fr"></div>
  <button>Sign up</button>
</form>
```

| Attribute | Required | Default | Meaning |
| --- | --- | --- | --- |
| `class="agentgate"` | yes | | marks the element as a widget |
| `data-sitekey` | yes | | the site's public key, `site_…` |
| `data-action` | yes | | the action to verify, `[a-z0-9_]{1,64}`; must be configured for the site |
| `data-mode` | no | `invisible` | `invisible`, `managed` or `interactive` ([modes](/docs/widget-modes)) |
| `data-lang` | no | the page's `lang`, then the browser's languages | UI language: `en`, `es`, `fr`, `de`, `pt`, `hi`, `ja`, `zh` |
| `data-endpoint` | no | the script's origin | your AgentGate endpoint, when the script comes from elsewhere |

Declarative widgets have no callback attributes. To be told about tokens or
errors, render the widget from code with `AgentGate.render()` (below).

## What the widget does in a form

- It finds its enclosing `<form>` and adds a hidden input named
  `agentgate_token`, unless the form already has one (then it uses yours).
- When the form is submitted without a fresh token, the widget stops the
  submission, verifies, fills `agentgate_token`, and submits the form again
  with the same submit button (`requestSubmit`).
- After a submission the token is cleared, so the next submission verifies
  again. A token is also cleared five seconds before it expires.
- In `interactive` mode a submission before verification is blocked and
  the chip says "Please complete the verification first."

Your server reads `agentgate_token` from the form body and redeems it with
[`POST /v1/siteverify`](/docs/siteverify).

## Rendering from code

`AgentGate.render(element, options)` creates the same widget and returns
its id. `element` is an element or a CSS selector.

```js
const id = AgentGate.render("#signup-widget", {
  siteKey: "site_…",
  action: "signup",
  mode: "managed",
  callback: (token, result) => console.log("verified", result.decisionId),
  errorCallback: (err) => console.warn("AgentGate:", err.code),
  expiredCallback: () => console.log("token expired"),
});
```

| Option | Meaning |
| --- | --- |
| `siteKey` | the site key (else `data-sitekey`, else the `init()` site key) |
| `action` | the action (else `data-action`) |
| `mode` | `invisible`, `managed` or `interactive` (else `data-mode`) |
| `lang` | UI language (else `data-lang`, the page's `lang`, the browser's) |
| `endpoint` | the AgentGate endpoint (else `data-endpoint`, the `init()` endpoint, the script's origin) |
| `callback(token, result)` | a token was issued; `result` is `{token, expiresAt, decisionId, clearance?, clearanceExpiresAt?}` |
| `errorCallback(error)` | verification failed; `error.code` is one of `AgentGate.errors` |
| `expiredCallback()` | the token was cleared because it was about to expire |

The hyphenated names `error-callback` and `expired-callback` are accepted
too. Manage rendered widgets with `getResponse(id)`, `reset(id)` and
`remove(id)`; see the [JavaScript API](/docs/javascript-api).

## Languages

The widget has strings for English (`en`), Spanish (`es`), French (`fr`),
German (`de`), Portuguese (`pt`), Hindi (`hi`), Japanese (`ja`) and Chinese
(`zh`); `AgentGate.locales` lists them. The language is chosen from, in
order: the `lang` option or `data-lang`, the page's `<html lang>`, then the
browser's preferred languages, matched on the primary subtag (`fr-CA` uses
`fr`). Anything else falls back to English.

## Accessibility

- The status chip is a polite live region (`role="status"`).
- The check is a labelled group inline, or a modal dialog (`aria-modal`)
  when there is no widget element to hold it; focus moves into it and back
  afterwards, and Tab stays inside the dialog.
- Press and hold works with a mouse, touch, or Space / Enter held on the
  focused button. "Verify another way" needs no pointer, timing or puzzle
  (WCAG 2.2 success criterion 3.3.8).
- Progress is a `progressbar` with `aria-valuenow`, announced every five
  seconds during the wait alternative.
- Nothing animates when the person prefers reduced motion.
- The widget uses CSS system colours (`Canvas`, `CanvasText`, `ButtonFace`,
  `Highlight`), which follow the page's `color-scheme` and forced-colours
  (high contrast) mode.

## Styling hooks

The widget styles its own elements through the CSSOM, so there is no
stylesheet to load and CSP `style-src` needs no change. Stable class names you can target:
`agentgate-chip` (with `data-state`), `agentgate-start` (the Verify button),
`agentgate-check`, `agentgate-hold`, `agentgate-alt` and
`agentgate-overlay` (the dialog backdrop).
