Documentation Index Fetch the complete documentation index at: https://docs.ansa.so/llms.txt
Use this file to discover all available pages before exploring further.
Forms let you collect structured data from users during conversations. You can trigger forms programmatically from your application code, define forms client-side with custom schemas, or use server-side forms created in the dashboard.
Quick Start
Forms created in the dashboard can be triggered by their tool name:
// Show a form defined in the dashboard
ansa . showForm ( "contact_form" );
Define and display forms entirely in your frontend code:
ansa . showForm ({
fields: [
{ name: "email" , label: "Email" , type: "email" },
{ name: "message" , label: "How can we help?" , type: "textarea" }
],
submitButtonText: "Send Message"
}, {
onSubmit : ( data ) => {
console . log ( "Form submitted:" , data );
// { email: "user@example.com", message: "I need help with..." }
}
});
Client-side forms are defined using a schema object:
interface FormSchema {
fields : FormField [];
title ?: string ;
description ?: string ;
submitButtonText ?: string ;
showLabels ?: boolean ;
successMessage ?: string ;
errorMessage ?: string ;
}
Field Types
Type Description Example Use textSingle-line text input Name, company emailEmail with validation Contact email telPhone number Phone callback numberNumeric input Quantity, budget textareaMulti-line text Message, description selectDropdown single select Category, plan multiselectDropdown multi-select Interests, features dateDate picker Appointment date datetimeDate and time picker Meeting schedule fileFile upload Documents imageImage upload Profile photo
Field Definition
interface FormField {
name : string ; // Field identifier (used in form data)
label : string ; // Display label
type : FormFieldType ; // One of the types above
placeholder ?: string ; // Input placeholder text
defaultValue ?: string ; // Pre-filled value
options ?: FormFieldOption []; // For select/multiselect
validation ?: FormFieldValidation ;
disabled ?: boolean ;
}
interface FormFieldOption {
label : string ; // Display text
value : string ; // Submitted value
}
Validation Rules
interface FormFieldValidation {
required ?: { value : boolean ; message : string };
minLength ?: { value : number ; message : string };
maxLength ?: { value : number ; message : string };
min ?: { value : number ; message : string };
max ?: { value : number ; message : string };
pattern ?: { value : string ; message : string }; // Regex pattern
}
Complete Examples
ansa . showForm ({
title: "Contact Us" ,
description: "We'll get back to you within 24 hours" ,
fields: [
{
name: "name" ,
label: "Full Name" ,
type: "text" ,
placeholder: "John Smith" ,
validation: {
required: { value: true , message: "Name is required" }
}
},
{
name: "email" ,
label: "Email Address" ,
type: "email" ,
validation: {
required: { value: true , message: "Email is required" }
}
},
{
name: "company" ,
label: "Company" ,
type: "text" ,
placeholder: "Optional"
},
{
name: "message" ,
label: "Message" ,
type: "textarea" ,
placeholder: "How can we help?" ,
validation: {
required: { value: true , message: "Please enter a message" },
minLength: { value: 10 , message: "Message must be at least 10 characters" }
}
}
],
submitButtonText: "Send Message" ,
successMessage: "Thanks! We'll be in touch soon."
}, {
onSubmit : async ( data ) => {
await fetch ( "/api/contact" , {
method: "POST" ,
headers: { "Content-Type" : "application/json" },
body: JSON . stringify ( data )
});
}
});
ansa . showForm ({
title: "Get a Custom Quote" ,
fields: [
{
name: "email" ,
label: "Work Email" ,
type: "email" ,
validation: { required: { value: true , message: "Required" } }
},
{
name: "company_size" ,
label: "Company Size" ,
type: "select" ,
options: [
{ label: "1-10 employees" , value: "1-10" },
{ label: "11-50 employees" , value: "11-50" },
{ label: "51-200 employees" , value: "51-200" },
{ label: "201-1000 employees" , value: "201-1000" },
{ label: "1000+ employees" , value: "1000+" }
]
},
{
name: "use_case" ,
label: "Primary Use Case" ,
type: "select" ,
options: [
{ label: "Customer Support" , value: "support" },
{ label: "Sales" , value: "sales" },
{ label: "Internal Tools" , value: "internal" },
{ label: "E-commerce" , value: "ecommerce" },
{ label: "Other" , value: "other" }
]
},
{
name: "budget" ,
label: "Monthly Budget" ,
type: "select" ,
options: [
{ label: "Under $100" , value: "<100" },
{ label: "$100 - $500" , value: "100-500" },
{ label: "$500 - $2000" , value: "500-2000" },
{ label: "$2000+" , value: "2000+" }
]
}
],
submitButtonText: "Get Quote"
}, {
onSubmit : ( data ) => {
// Send to CRM
analytics . track ( "Lead Qualified" , data );
},
sendToAgent: true // Agent can see the submitted data
});
Appointment Booking
ansa . showForm ({
title: "Schedule a Demo" ,
fields: [
{
name: "name" ,
label: "Your Name" ,
type: "text" ,
validation: { required: { value: true , message: "Required" } }
},
{
name: "email" ,
label: "Email" ,
type: "email" ,
validation: { required: { value: true , message: "Required" } }
},
{
name: "date" ,
label: "Preferred Date" ,
type: "date" ,
validation: { required: { value: true , message: "Please select a date" } }
},
{
name: "time" ,
label: "Preferred Time" ,
type: "select" ,
options: [
{ label: "9:00 AM" , value: "09:00" },
{ label: "10:00 AM" , value: "10:00" },
{ label: "11:00 AM" , value: "11:00" },
{ label: "2:00 PM" , value: "14:00" },
{ label: "3:00 PM" , value: "15:00" },
{ label: "4:00 PM" , value: "16:00" }
]
},
{
name: "notes" ,
label: "Anything specific you'd like to discuss?" ,
type: "textarea"
}
],
submitButtonText: "Book Demo"
}, {
onSubmit : async ( data ) => {
await fetch ( "/api/book-demo" , {
method: "POST" ,
headers: { "Content-Type" : "application/json" },
body: JSON . stringify ( data )
});
}
});
Register form schema providers that generate forms dynamically based on context:
ansa . registerFormSchema ({
// Form name -> schema provider function
"product_inquiry" : async ( args , user ) => {
// args: parameters from agent tool call
// user: { visitorId, userId?, userMetadata?, conversationId? }
// Fetch products from your API
const products = await fetch ( "/api/products" ). then ( r => r . json ());
return {
title: "Product Inquiry" ,
fields: [
{
name: "email" ,
label: "Email" ,
type: "email" ,
// Pre-fill from user identity
defaultValue: user . userMetadata ?. email
},
{
name: "product" ,
label: "Product" ,
type: "select" ,
// Dynamic options from API
options: products . map ( p => ({
label: ` ${ p . name } - $ ${ p . price } ` ,
value: p . id
})),
// Pre-select from agent args
defaultValue: args . productId
},
{
name: "quantity" ,
label: "Quantity" ,
type: "number" ,
defaultValue: "1" ,
validation: {
min: { value: 1 , message: "Minimum 1" },
max: { value: 100 , message: "Maximum 100" }
}
}
],
submitButtonText: "Request Quote"
};
}
});
The agent can then trigger this form:
Agent: I can help you get a quote for that product. Let me pull up the form.
[Shows product_inquiry form with productId pre-selected]
Context-Aware Pre-filling
ansa . registerFormSchema ({
"support_ticket" : async ( args , user ) => {
// Get user's recent orders for context
let orders = [];
if ( user . userId ) {
orders = await fetch ( `/api/users/ ${ user . userId } /orders` ). then ( r => r . json ());
}
return {
title: "Create Support Ticket" ,
fields: [
{
name: "email" ,
label: "Email" ,
type: "email" ,
defaultValue: user . userMetadata ?. email ,
disabled: !! user . userMetadata ?. email // Lock if known
},
{
name: "order" ,
label: "Related Order (optional)" ,
type: "select" ,
options: [
{ label: "No specific order" , value: "" },
... orders . map ( o => ({
label: `# ${ o . id } - ${ o . date } ($ ${ o . total } )` ,
value: o . id
}))
]
},
{
name: "issue" ,
label: "Issue Type" ,
type: "select" ,
options: [
{ label: "Order issue" , value: "order" },
{ label: "Product question" , value: "product" },
{ label: "Billing" , value: "billing" },
{ label: "Other" , value: "other" }
]
},
{
name: "description" ,
label: "Describe your issue" ,
type: "textarea" ,
validation: {
required: { value: true , message: "Please describe your issue" }
}
}
]
};
}
});
Handling Submissions
Client-Side Callback
ansa . showForm ( schema , {
onSubmit : async ( data ) => {
// data is an object with field names as keys
console . log ( data );
// { email: "user@example.com", message: "Hello..." }
// Send to your backend
const response = await fetch ( "/api/forms/submit" , {
method: "POST" ,
headers: { "Content-Type" : "application/json" },
body: JSON . stringify ({
formType: "contact" ,
data ,
visitorId: ansa . getVisitorId ()
})
});
if ( ! response . ok ) {
throw new Error ( "Submission failed" ); // Shows error in widget
}
},
onCancel : () => {
console . log ( "User closed the form" );
}
});
Send to Agent
When sendToAgent: true, the form data is also sent to the agent as a chat message:
ansa . showForm ({
fields: [
{ name: "email" , label: "Email" , type: "email" },
{ name: "question" , label: "Question" , type: "textarea" }
]
}, {
sendToAgent: true ,
onSubmit : ( data ) => {
// Still fires, but agent also receives the data
analytics . track ( "Form Submitted" , data );
}
});
The agent sees:
User submitted form:
- Email: user@example.com
- Question: How do I integrate with my CRM?
Triggering Patterns
On Page Load (Delayed)
// Show lead capture after 30 seconds on pricing page
if ( window . location . pathname === "/pricing" ) {
setTimeout (() => {
if ( ! ansa . isOpen ()) {
ansa . open ();
ansa . showForm ( "pricing_inquiry" );
}
}, 30000 );
}
On User Action
// Trigger quote form when user clicks CTA
document . querySelectorAll ( "[data-quote-form]" ). forEach ( btn => {
btn . addEventListener ( "click" , ( e ) => {
e . preventDefault ();
const product = btn . dataset . product ;
ansa . showForm ({
fields: [
{ name: "email" , label: "Email" , type: "email" },
{ name: "product" , label: "Product" , type: "text" , defaultValue: product , disabled: true }
]
}, { sendToAgent: true });
});
});
Exit Intent
let exitFormShown = false ;
document . addEventListener ( "mouseleave" , ( e ) => {
if ( e . clientY < 0 && ! exitFormShown && ! ansa . isOpen ()) {
exitFormShown = true ;
ansa . open ();
ansa . showForm ({
title: "Before you go..." ,
description: "Get 10% off your first order" ,
fields: [
{ name: "email" , label: "Email" , type: "email" }
],
submitButtonText: "Get Discount"
}, {
onSubmit : ( data ) => {
// Send discount code
}
});
}
});
Best Practices
Keep forms short. Each additional field reduces completion rates. Start with 2-3 essential fields.
Progressive disclosure — Ask for minimal info first, then follow up for details
Pre-fill when possible — Use identify() to pass user data for pre-filling
Validate client-side — Use validation rules to catch errors before submission
Provide context — Use title and description to explain why you need the info
Handle errors gracefully — Throw errors in onSubmit to show error state in form
Next Steps
Custom Events Trigger automations based on user actions
Identity Pre-fill forms with user data