Appearance
The fields
You do not describe your fields to the agent — it reads them. These attributes are for the cases where the markup alone is not enough, or where you want a plain choice to be asked the way a quiz asks it.
What gets read
Every control inside the tagged form is extracted in DOM order, with its label, kind, required flag, options and validation constraints.
Supported kinds: text, email, tel, number, date, textarea, select, radio, checkbox.
Deliberately skipped, and therefore invisible to the agent: hidden, password, file, submit and button inputs, and anything disabled. Hidden inputs carrying lead ids and tracking tokens pass through your form untouched, exactly as they do today.
Where the label comes from
The first of these that yields anything:
data-nam-labelon the control<label for="…">- A wrapping
<label> aria-labelaria-labelledbyplaceholder- The
nameattribute, humanised
If the agent is calling a field something odd, that chain is why — and data-nam-label is the fix.
Helping the agent
| Attribute | Where it goes | What it does |
|---|---|---|
data-nam-label | Any control | Overrides the label chain above. Highest precedence. |
data-nam-help | A control, or its <fieldset> | The visitor-facing line under the question. Capped at 200 characters. |
data-nam-context | Any control | Background for the agent about this one field. Not shown to the visitor. Capped at 300. |
data-nam-help is written for the visitor; data-nam-context is written for the agent. Use the first to explain a choice, the second to explain a constraint you cannot express in the markup ("a US mobile; the plan is texted here").
Giving an answer a picture
On an <option>, on a radio <input>, or on that radio's <label>:
| Attribute | What it does |
|---|---|
data-nam-image | The picture for that answer. Resolved against the page, and must be http(s) — anything else is dropped. |
data-nam-description | One line under the answer. Capped at 200 characters. |
An image on any answer turns the whole question into a visual question unit: a heading, the help line, "Question 2 of 4", and the answers as image tiles rather than chips.
html
<fieldset data-nam-help="Pick whichever is closest — you can change it later.">
<legend>What are you hoping for?</legend>
<label>
<input
type="radio"
name="goal"
value="reconnect"
data-nam-image="/img/answers/reconnect.jpg"
data-nam-description="Someone you have lost touch with"
/>
Reconnect with a friend
</label>
…
</fieldset>Pictures are cropped to fit
Every image the SDK draws is object-fit: cover into a wide box, which keeps the middle band of the frame. Portrait art with faces high in the frame loses the heads. Either author the art at roughly 16:9, or move the crop for the whole page with --nam-image-position — see Theming. Your own stylesheet cannot reach the images, because the widget renders in a shadow root.
Keeping the agent out
| Attribute | Where | Effect |
|---|---|---|
data-nam-lock | A control | The field is extracted and visible to the agent, which may draw the visitor's attention to it, but set_field and ask_field are both refused. It is left out of the confirm recap. |
data-nam-ignore | A control, or any ancestor inside the form | The control is never extracted at all. The agent does not know it exists. |
data-nam-wrapper | Any ancestor between the control and the <form> | Names the element to hide in place of the field itself, overriding the automatic walk. Use it when hiding the input alone leaves a stray label or icon behind. |
data-nam-disclosure | Any element in the form | Marks a block as a legal disclosure. It is never hidden, never written to, and any checkbox inside it is locked. |
Consent is locked whether you ask for it or not
A checkbox is locked automatically when it sits inside a disclosure block, or when its own label matches any of agree, consent, authoriz, accept, terms, privacy, opt in, subscribe, newsletter, marketing, promotion, offers, updates, text me, email me, contact me or sms. In a checkbox group, wording on any member locks the whole group.
Disclosure blocks are detected from data-nam-disclosure and from a class containing disclaimer, disclosure, consent or tcpa.
The effect is the one you want: the agent can say "there is a box to tick below" and focus it, and only the visitor can tick it. If your disclosure uses none of those words or classes, add data-nam-disclosure yourself.
Sensitive values never leave the browser
Some fields are extracted so the agent knows they exist, but their value is never read, never sent to us and never reaches the model — not even the value your visitor's browser autofilled. They are locked too, so the agent can point at them and nothing more.
This applies to a control whose autocomplete is a cc-* type or one-time-code, and to one whose name or id looks like a card number, CVV/CVC, security code, SSN, tax id, bank routing number or passport number.
The agent can still focus such a field and tell the visitor it needs filling in; the visitor types into your input directly, exactly as they would with no assistant present.
A date of birth is not on this list, because it is a legitimate qualifying question on many forms. Add data-nam-ignore if you would rather we never saw it.
Input masks
data-mask is read, never written. If your page already masks a phone number or a post code with the jQuery-mask grammar — 0 for a digit, A for a letter, S for alphanumeric, up to 64 characters — the SDK parses it, uses it to decide whether a value is complete, and formats what it writes so your own mask plugin sees a value it agrees with.
html
<input type="tel" name="Phone" id="Phone" data-mask="000-000-0000" required />The agent reading back 3125550142 results in 312-555-0142 in your input, with input, keyup, change and blur all fired, in that order, so your validators run.
A field that is missing
If the agent never asks for a field you expected, it was one of:
- a skipped control kind (see above), or
disabledat extraction time; - inside something carrying
data-nam-ignore; - a locked consent checkbox, or a sensitive field whose value is withheld — both are working as intended;
- not in the DOM when the SDK booted, because it is rendered by JavaScript later. The browser sends an authoritative snapshot every turn, so a field that arrives late is picked up; one that never renders server-side is invisible to the registration CLI.