Creating Contact Form Capture in Welcome Messages
This guide demonstrates how to create a contact information capture form that appears when the chatbot opens. This is ideal for lead generation, user registration, or collecting contact details before users interact with your AI assistant.

Overview
The contact form capture feature allows you to:
- Collect user contact information (name, email, etc.) when the bot opens
- Validate form data before submission
- Send structured data to your system via JSON
- Provide a seamless user experience with form validation and feedback
- Automatically hide the form after successful submission
Use Cases
- Lead Generation: Capture potential customer information
- User Registration: Collect details for personalized experiences
- Support Tickets: Gather contact info before support conversations
- Newsletter Signups: Build email lists through bot interactions
- Event Registration: Collect attendee information
Implementation Steps
Step 1: Configure the Welcome Message
- Go to Web Controls → ai12z-bot → Your Configuration
- Navigate to Info tab → Welcome Message
- Configure the HTML, Styles, and Script tabs as shown below
Step 2: Add HTML Structure
Add this HTML in the HTML Tab:
<div class="ai12z-contact-panel my-welcome-panel">
<div class="ai12z-contact-header">
<span class="ai12z-contact-icon" aria-hidden="true">📩</span> Share Your
Contact Information
</div>
<div class="ai12z-contact-message">
Please provide your details so we can connect with you.
</div>
<div class="ai12z-contact-inputs">
<input
type="text"
id="firstName"
placeholder="First Name"
aria-label="First Name"
required
/>
<input
type="text"
id="lastName"
placeholder="Last Name"
aria-label="Last Name"
required
/>
<input
type="email"
id="email"
placeholder="Email Address"
aria-label="Email Address"
required
/>
<button type="button" class="ai12zBtn" id="contactSubmit">Submit</button>
</div>
</div>
Step 3: Add Styling
Add this CSS in the Styles Tab:
.ai12z-contact-panel {
background: #fff;
border-radius: 18px;
box-shadow: 0 2px 12px 0 rgba(32, 149, 174, 0.07);
padding: 28px 20px;
margin: 18px auto 0 auto;
max-width: 480px;
text-align: center;
font-family: inherit;
border: 1px solid #e3f2f7;
}
.ai12z-contact-header {
font-size: 1.35rem;
font-weight: 600;
margin-bottom: 12px;
color: var(--ai12zBot-v2-title-color, #2095ae);
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
letter-spacing: 0.01em;
}
.ai12z-contact-icon {
font-size: 1.5em;
}
.ai12z-contact-message {
font-size: 1.08rem;
margin-bottom: 20px;
color: #2a3342;
}
.ai12z-contact-inputs {
display: flex;
flex-direction: column;
gap: 12px;
align-items: stretch;
}
.ai12z-contact-inputs input {
padding: 12px;
border-radius: 7px;
border: 1px solid #d0e6ed;
font-size: 1rem;
outline: none;
}
.ai12z-contact-inputs input:focus {
border-color: #2095ae;
box-shadow: 0 0 0 3px rgba(32, 149, 174, 0.12);
}
.ai12zBtn {
color: var(--ai12zBot-v2-button-font-color, #fff);
background: var(--ai12zBot-v2-button-background, #2095ae);
font-weight: 500;
border: none;
border-radius: 7px;
padding: 13px 18px;
cursor: pointer;
font-size: 1rem;
box-shadow: 0 1px 4px 0 rgba(32, 149, 174, 0.07);
transition:
background 0.18s,
box-shadow 0.18s,
transform 0.02s ease-in-out;
}
.ai12zBtn:hover,
.ai12zBtn:focus {
background: #176e86;
color: #fff;
box-shadow: 0 2px 8px 0 rgba(32, 149, 174, 0.13);
}
.ai12zBtn:active {
transform: translateY(1px);
}
@media (max-width: 600px) {
.ai12z-contact-panel {
padding: 20px 10px;
max-width: 98vw;
margin: 10px auto 0;
}
.ai12z-contact-header {
font-size: 1.12rem;
}
}
Step 4: Add JavaScript Functionality
Add this JavaScript in the Script Tab:
;(() => {
// Run once per bot instance, even if the script is injected multiple times
if (ai12zBot.__contactFormLoaded) return
ai12zBot.__contactFormLoaded = true
/** Attach contact form behavior inside the Shadow DOM */
const initContactForm = (target) => {
const panel = target.querySelector(".my-welcome-panel")
if (!panel || panel.dataset.bound === "1") return
const firstNameEl = panel.querySelector("#firstName")
const lastNameEl = panel.querySelector("#lastName")
const emailEl = panel.querySelector("#email")
const submitBtn = panel.querySelector("#contactSubmit")
if (!firstNameEl || !lastNameEl || !emailEl || !submitBtn) return
const isValidEmail = (v) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v)
const handleSubmit = () => {
const firstName = firstNameEl.value.trim()
const lastName = lastNameEl.value.trim()
const email = emailEl.value.trim()
if (!firstName || !lastName || !email) {
alert("Please fill out all fields.")
return
}
if (!isValidEmail(email)) {
alert("Please enter a valid email address.")
emailEl.focus()
return
}
submitBtn.disabled = true
const prevText = submitBtn.textContent
submitBtn.textContent = "Sending..."
try {
// Send JSON data to your system
ai12zBot.sendJSON(
{ email, firstName, lastName },
"Users Contact information"
)
// Clear & hide panel (conversation continues)
firstNameEl.value = ""
lastNameEl.value = ""
emailEl.value = ""
panel.style.display = "none"
ai12zBot.sendMessage("Thank you! Your information has been submitted.")
} finally {
submitBtn.disabled = false
submitBtn.textContent = prevText
}
}
submitBtn.onclick = handleSubmit
panel.addEventListener("keydown", (e) => {
if (e.key === "Enter") {
e.preventDefault()
handleSubmit()
}
})
panel.dataset.bound = "1"
}
/** Translation support (if using multilingual features) */
const translateWelcomePanel = (target) => {
const innerContent = target.querySelector(".my-welcome-panel")
if (!innerContent) return
// Add your translation code here if needed
initContactForm(target)
}
// Observer to detect when bot opens
const observer = new MutationObserver((mutationsList) => {
for (const mutation of mutationsList) {
if (
mutation.type === "attributes" &&
mutation.attributeName === "class"
) {
const target = mutation.target
if (target.classList.contains("is-open")) {
translateWelcomePanel(target)
initContactForm(target)
}
}
}
})
const waitAndObserveLayout = () => {
const layoutNode = ai12zBot.shadowRoot?.querySelector(".layout")
if (!layoutNode) {
setTimeout(waitAndObserveLayout, 100)
return
}
observer.observe(layoutNode, {
attributes: true,
subtree: true,
attributeFilter: ["class"],
})
if (layoutNode.classList.contains("is-open")) {
translateWelcomePanel(layoutNode)
initContactForm(layoutNode)
}
}
waitAndObserveLayout()
})()
Key Features
Form Validation
- Required Fields: All fields must be filled out
- Email Validation: Validates email format using regex
- Real-time Feedback: Shows alerts for validation errors
- Focus Management: Automatically focuses invalid fields
User Experience
- Loading States: Button shows "Sending..." during submission
- Form Clearing: Automatically clears form after successful submission
- Form Hiding: Hides form panel after submission to continue conversation
- Keyboard Support: Submit form using Enter key
- Responsive Design: Optimized for mobile devices
Data Handling
- JSON Submission: Sends structured data using
ai12zBot.sendJSON() - Metadata: Includes descriptive metadata with the submission
- Error Handling: Graceful error handling with user feedback
Customization Options
Adding More Fields
You can extend the form with additional fields:
<!-- Add phone number field -->
<input
type="tel"
id="phone"
placeholder="Phone Number"
aria-label="Phone Number"
/>
<!-- Add company field -->
<input type="text" id="company" placeholder="Company" aria-label="Company" />
<!-- Add dropdown selection -->
<select id="interest" aria-label="Area of Interest">
<option value="">Select Interest</option>
<option value="sales">Sales</option>
<option value="support">Support</option>
<option value="partnership">Partnership</option>
</select>
Update the JavaScript to handle new fields:
const phoneEl = panel.querySelector("#phone")
const companyEl = panel.querySelector("#company")
const interestEl = panel.querySelector("#interest")
// In handleSubmit function:
const phone = phoneEl?.value.trim() || ""
const company = companyEl?.value.trim() || ""
const interest = interestEl?.value || ""
ai12zBot.sendJSON(
{
email,
firstName,
lastName,
phone,
company,
interest,
},
"Users Contact information"
)
Styling Customization
Customize the appearance by modifying CSS variables:
.ai12z-contact-panel {
/* Change colors */
--primary-color: #2095ae;
--border-color: #e3f2f7;
--background-color: #fff;
/* Customize spacing */
padding: 32px 24px;
margin: 20px auto;
/* Adjust sizing */
max-width: 500px;
border-radius: 20px;
}
Validation Rules
Add custom validation rules:
const isValidPhone = (v) => /^\+?[\d\s\-\(\)]+$/.test(v)
// In handleSubmit function:
if (phone && !isValidPhone(phone)) {
alert("Please enter a valid phone number.")
phoneEl.focus()
return
}