Custom one-page form
Submit a linear Pollaris form atomically from your own HTML.
One-page mode connects familiar HTML forms—contact, lead, registration, and feedback forms—to Pollaris. It submits every field in one atomic request.
Requirements
The published form must be strictly linear:
- Each question flows unconditionally to the next question.
- The final question ends the form.
- There are no branches, backward edges, or quiz scoring rules.
- Each question has a unique stable field key.
- Enable atomic one-page submissions is turned on in Share → Embed.
If the form does not qualify, use the headless step-by-step SDK.
Stable field keys
Your HTML input names must match Pollaris question keys:
<input name="name">
<input name="email" type="email">
<textarea name="message"></textarea>Keys match ^[a-z][a-z0-9_]{0,63}$ and are unique within the form. Changing a prompt or moving a question does not change its key. Changing a key is a breaking change for your website integration.
Submit your HTML form
<form id="contact-form">
<label>
Name
<input name="name" autocomplete="name">
</label>
<label>
Email
<input name="email" type="email" autocomplete="email" required>
</label>
<label>
Message
<textarea name="message" required></textarea>
</label>
<button type="submit">Send</button>
<p id="contact-status" role="status"></p>
</form>
<script type="module">
import { createPollarisClient } from 'https://cdn.example.com/embed/v1/index.js';
const client = createPollarisClient({
form: 'FORM_SLUG',
apiBase: 'https://api.example.com'
});
const form = document.querySelector('#contact-form');
const status = document.querySelector('#contact-status');
form.addEventListener('submit', async (event) => {
event.preventDefault();
const button = form.querySelector('button[type="submit"]');
button.disabled = true;
try {
const values = Object.fromEntries(new FormData(form));
await client.submit(values, {
context: {
utm_source: new URLSearchParams(location.search).get('utm_source') ?? undefined,
language: navigator.language,
screen_w: window.innerWidth
}
});
form.reset();
status.textContent = 'Your message was sent.';
} catch (error) {
status.textContent = error.code === 'VALIDATION_FAILED'
? error.message
: 'Your message could not be sent. Please try again.';
} finally {
button.disabled = false;
}
});
</script>Manifest and version changes
client.submit() first loads /v1/embed/FORM_SLUG/manifest, validates keys and values locally, and submits the manifest version. Pollaris rejects stale versions so answers are never silently applied to a changed schema. The SDK manages this flow for you.
Unknown fields are rejected. Missing optional values are normalized to null; missing required values fail validation. The server remains authoritative even if browser validation is bypassed.
Idempotency
The SDK generates an idempotency key for each submission. To safely retry an application-managed submission, generate a key once and reuse it only for the identical values:
const idempotencyKey = crypto.randomUUID();
await client.submit(values, { idempotencyKey });Never reuse one key for a different submission. Pollaris rejects a reused key when the values differ.
Field-value notes
FormDataproduces strings. For rating, star, or NPS fields, convert the selected value to a number.- Multiple-choice fields expect an array, so collect repeated/checkbox values with
formData.getAll(key). - A contact question expects an object containing its configured contact fields; separate text questions are often easier for a custom one-page form.
- Client-side validation is for immediate feedback only; always handle server validation errors.