Complete reference for all embed.js features, configuration options, and JavaScript events.
Complete documentation for advanced features and customization.
You're here! Continue reading below.
/form/{form_key}
Retrieves a form by its key and displays the form template.
Returns an HTML form template that users can fill out and submit.
/send/{form_key}
Submits data to a form and sends an email notification.
replyto
, _replyto
) - Sender's email addresstitle
, _subject
) - Email subject (optional)Any additional form fields not listed above will be automatically included in email notifications. These fields will appear in an "Additional Information" section in the email.
first_name
) will be displayed as title case with spaces (e.g., "First Name") in email notifications for better readability.
<form action="https://send.webform.dev/send/your-form-key" method="POST">
<input name="name" type="text" placeholder="Your Name">
<input name="email" type="email" placeholder="Your Email" required>
<input name="subject" type="text" placeholder="Subject">
<textarea name="text" placeholder="Your Message" required></textarea>
<!-- Hidden honeypot field for spam protection -->
<input name="_gotcha" type="text" style="display:none">
<button type="submit">Send Message</button>
</form>
Configure form behavior using data attributes on the form element:
data-success-behavior
: "button" (default), "message", or "custom"data-success-message
: Custom success messagedata-success-class
: Custom CSS class for success elementsdata-reset-form
: "true" (default) or "false"data-error-position
: "inline" (default), "top", or "bottom"data-submit-text
: Text to show while submitting<form class="webform-embed"
action="https://send.webform.dev/send/YOUR_FORM_KEY"
method="POST"
data-success-behavior="replace"
data-success-message="Thank you! We'll be in touch soon."
data-error-position="top"
data-submit-text="Sending...">
<!-- form fields -->
</form>
Improve user experience with visual feedback:
data-loading-spinner
: "true" or "false" - Show spinner during submissiondata-disable-fields-on-submit
: "true" or "false" - Disable all form fields during submissiondata-loading-overlay
: "true" or "false" - Show overlay to prevent interaction<form class="webform-embed"
action="https://send.webform.dev/send/YOUR_FORM_KEY"
method="POST"
data-loading-spinner="true"
data-disable-fields-on-submit="true"
data-loading-overlay="false">
<!-- form fields -->
</form>
Handle network issues gracefully:
data-max-retries
: Number - Maximum retry attempts for network errors (default: 2)data-fallback-on-error
: "true" (default) or "false" - Fall back to regular form submission<form class="webform-embed"
action="https://send.webform.dev/send/YOUR_FORM_KEY"
method="POST"
data-max-retries="3"
data-fallback-on-error="true">
<!-- form fields -->
</form>
Enhance success feedback and user flow:
data-success-redirect
: URL - Redirect after successdata-success-redirect-delay
: Number - Delay before redirect in ms (default: 3000)<form class="webform-embed"
action="https://send.webform.dev/send/YOUR_FORM_KEY"
method="POST"
data-success-redirect="/thank-you"
data-success-redirect-delay="5000">
<!-- form fields -->
</form>
WebForm.dev includes built-in spam protection features:
<form action="https://send.webform.dev/send/YOUR_FORM_KEY" method="POST">
<!-- Regular form fields -->
<input name="name" type="text" placeholder="Your Name">
<input name="email" type="email" placeholder="Your Email" required>
<textarea name="message" placeholder="Your Message" required></textarea>
<!-- Honeypot field for spam protection -->
<input name="webform_gotcha" type="text" style="display:none">
<!-- Custom redirect after submission -->
<input name="webform_next" type="hidden" value="https://yoursite.com/thanks">
<button type="submit">Send Message</button>
</form>
The embed.js script fires custom events throughout the form submission process, allowing for advanced integrations and custom processing.
Fired before form submission, allowing you to modify form data or cancel the submission:
// Get the form element
const contactForm = document.querySelector('.webform-embed');
contactForm.addEventListener('webform:beforesubmit', function(e) {
const { formData, form, config } = e.detail;
// Add metadata to form submission
formData.set('timestamp', new Date().toISOString());
formData.set('page_url', window.location.href);
formData.set('referrer', document.referrer || 'direct');
// Validate form fields
const name = formData.get('name');
const email = formData.get('email');
const message = formData.get('message');
// Check required fields
if (!name || name.trim() === '') {
e.preventDefault();
displayValidationError(form, 'Name is required');
return;
}
if (!email || !validateEmail(email)) {
e.preventDefault();
displayValidationError(form, 'Please enter a valid email address');
return;
}
if (!message || message.trim().length < 10) {
e.preventDefault();
displayValidationError(form, 'Message must be at least 10 characters long');
return;
}
// Optional: Clean up the message text
const cleanedMessage = message.trim().replace(/\s+/g, ' ');
formData.set('message', cleanedMessage);
});
// Email validation function
function validateEmail(email) {
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailPattern.test(email);
}
// Display validation errors
function displayValidationError(form, message) {
// Remove existing error
const existingError = form.querySelector('.validation-error');
if (existingError) {
existingError.remove();
}
// Create error element
const errorElement = document.createElement('div');
errorElement.className = 'validation-error';
errorElement.style.cssText = `
background: #fee;
border: 1px solid #fcc;
border-radius: 4px;
color: #c33;
margin-bottom: 10px;
padding: 10px;
font-size: 14px;
`;
errorElement.textContent = message;
// Insert at top of form
form.insertBefore(errorElement, form.firstChild);
// Scroll to error
errorElement.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}
e.preventDefault()
to cancel submission. The FormData object can be modified directly.
event.preventDefault()
)Address autocomplete integration that combines street, city, and zip for submission:
// Store address components from autocomplete
let addressComponents = { street: '', city: '', zip: '' };
// Listen for address selection
addressInput.addEventListener('address-selected', (e) => {
addressComponents = e.detail;
});
// Process address before form submission
form.addEventListener('webform:beforesubmit', (e) => {
const { formData } = e.detail;
// Combine address components for submission
const fullAddress = [
addressComponents.street,
addressComponents.city,
addressComponents.zip
].filter(Boolean).join(', ');
if (fullAddress) {
formData.set('address', fullAddress);
}
// Update subject line with street address
const subject = addressComponents.street ?
`Contact - ${addressComponents.street}` :
'Contact Form';
formData.set('subject', subject);
});
The embed script is fully compatible with strict Content Security Policies:
.webform-error
- Error messages.webform-success
- Success message styling.webform-success-replace
- Full form replacement view.webform-loading
- Button loading state.webform-spinner
- Loading spinner.webform-submitting
- Form during submissionWebForm.dev automatically includes all form fields in email notifications, except for configuration fields (those starting with webform_
).
name
, email
, subject
, message
) appear in the main email bodywebform_
are used for form behavior but not displayed in emailsphone_number
becomes "Phone Number")webform_field_order
parameter<form action="https://send.webform.dev/send/YOUR_FORM_KEY" method="POST">
<!-- Core fields -->
<input name="name" type="text" placeholder="Your Name" required>
<input name="email" type="email" placeholder="Your Email" required>
<input name="subject" type="text" placeholder="Subject">
<textarea name="message" placeholder="Your Message" required></textarea>
<!-- Custom fields (automatically included in email) -->
<input name="company" type="text" placeholder="Company Name">
<input name="phone" type="tel" placeholder="Phone Number">
<select name="department">
<option value="sales">Sales</option>
<option value="support">Support</option>
<option value="billing">Billing</option>
</select>
<!-- Configuration fields (not included in email) -->
<input name="webform_gotcha" type="text" style="display:none">
<input name="webform_next" type="hidden" value="/thanks">
<button type="submit">Send Message</button>
</form>
Control the order of custom fields in email notifications using the webform_field_order
parameter:
<form action="https://send.webform.dev/send/YOUR_FORM_KEY" method="POST">
<input name="name" type="text" placeholder="Your Name" required>
<input name="email" type="email" placeholder="Your Email" required>
<textarea name="message" placeholder="Your Message" required></textarea>
<input name="company" type="text" placeholder="Company">
<input name="phone" type="tel" placeholder="Phone">
<input name="budget" type="text" placeholder="Budget Range">
<input name="timeline" type="text" placeholder="Timeline">
<!-- Order: phone, company, timeline (budget will appear last) -->
<input name="webform_field_order" type="hidden" value="phone,company,timeline">
<button type="submit">Send Message</button>
</form>
webform_field_order
will appear after the ordered fields in the email.
WebForm.dev automatically handles various HTML form field types:
<input type="text">
, <input type="email">
, etc.<textarea>
fields for longer text<select>
with single or multiple optionsAll data is encrypted in transit using TLS 1.3 and at rest using AES-256.
Built with privacy by design. Minimal data collection and transparent handling.
Automatic protection against abuse with configurable rate limits.
Complete audit trail of all form submissions and API calls.
<form action="https://send.webform.dev/send/business_inquiry_form" method="POST">
<!-- Core fields -->
<input type="text" name="name" placeholder="Full Name" required>
<input type="email" name="email" placeholder="Email Address" required>
<input type="text" name="subject" value="Business Inquiry">
<textarea name="message" placeholder="Tell us about your project" required></textarea>
<!-- Custom fields (automatically included in email) -->
<input type="text" name="company" placeholder="Company Name">
<input type="tel" name="phone" placeholder="Phone Number">
<select name="budget">
<option value="">Select Budget Range</option>
<option value="under-5k">Under $5,000</option>
<option value="5k-15k">$5,000 - $15,000</option>
<option value="15k-50k">$15,000 - $50,000</option>
<option value="over-50k">Over $50,000</option>
</select>
<select name="services">
<option value="">Services Needed</option>
<option value="web-design">Web Design</option>
<option value="development">Development</option>
<option value="consulting">Consulting</option>
<option value="maintenance">Maintenance</option>
</select>
<input type="text" name="timeline" placeholder="Desired Timeline">
<!-- Control field order in email -->
<input type="hidden" name="webform_field_order" value="company,phone,services,budget,timeline">
<!-- Configuration fields -->
<input name="webform_gotcha" type="text" style="display:none">
<input name="webform_next" type="hidden" value="/thanks">
<button type="submit">Submit Inquiry</button>
</form>
A form using all the enhanced user feedback features for the best user experience:
<form action="https://send.webform.dev/send/enhanced_contact_form" method="POST" class="webform-embed"
data-success-message="Thank you! We'll get back to you within 24 hours."
data-submit-text="Sending your message..."
data-error-position="top"
<!-- Enhanced user feedback features -->
data-loading-spinner="true"
data-disable-fields-on-submit="true"
data-loading-overlay="false"
<!-- Network resilience features -->
data-max-retries="3"
data-retry-delay="1500"
data-show-retry-message="true"
data-fallback-on-error="true"
data-error-details="false"
<!-- Success enhancements -->
data-success-animation="fade"
data-success-redirect="/thank-you"
data-success-redirect-delay="5000">
<!-- Form fields -->
<input type="text" name="name" placeholder="Your Name" required>
<input type="email" name="email" placeholder="Your Email" required>
<input type="tel" name="phone" placeholder="Phone Number">
<textarea name="message" placeholder="How can we help you?" required></textarea>
<!-- Configuration -->
<input name="webform_gotcha" type="text" style="display:none">
<button type="submit">Send Message</button>
</form>
<script>
// Enhanced event handling for better user experience
const form = document.querySelector('.webform-embed');
// Handle fallback gracefully
form.addEventListener('webform:fallback', (e) => {
console.log('Switching to backup submission method');
// Optional: Show user-friendly message
const notice = document.createElement('div');
notice.textContent = 'Using backup submission method...';
notice.style.cssText = 'color: orange; font-size: 14px; margin: 10px 0;';
form.insertBefore(notice, form.firstChild);
});
// Enhanced error handling with categories
form.addEventListener('webform:error', (e) => {
const { category, message } = e.detail;
// Track errors in analytics
if (window.gtag) {
gtag('event', 'form_error', {
error_category: category,
error_message: message
});
}
// Custom handling based on error type
if (category === 'network') {
console.log('Network issue detected - user may be offline');
}
});
// Track successful submissions
form.addEventListener('webform:success', (e) => {
console.log('Form submitted successfully!');
if (window.gtag) {
gtag('event', 'form_submit_success', {
form_type: 'contact'
});
}
});
</script>