Email Forms
ConvertForm — dynamic field definitions, anti-spam protection, and the submission flow.
Basic Usage
The simplest email capture form:
::convert-form{location="hero"}
::
This renders a single email field with a "Get Access" button. On submit, the email is delivered via webhook and the visitor is redirected to /success.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
fields | FieldDef[] | [{ name: 'email', type: 'email', ... }] | Form field definitions |
location | string | required | Location identifier for tracking |
submitLabel | string | 'Get Access' | Submit button text |
note | string | — | Small text below the form |
layout | 'stacked' | 'horizontal' | 'stacked' | Form layout direction |
successRedirect | string | — | Custom redirect path after submission |
offerSlug | string | — | Offer identifier for tracking and redirect |
Custom Fields
Define custom fields to capture more than just email:
::convert-form
---
location: apply-form
submitLabel: Apply Now
layout: stacked
fields:
- name: name
label: Full Name
type: text
placeholder: Jane Smith
required: true
- name: email
label: Email
type: email
placeholder: [email protected]
required: true
- name: message
label: Why are you interested?
type: textarea
placeholder: Tell us about your project...
required: false
---
::
FieldDef Shape
| Field | Type | Description |
|---|---|---|
name | string | Field identifier (used as form data key) |
label | string | Display label above the input |
type | 'text' | 'email' | 'textarea' | 'tel' | Input type |
placeholder | string | Placeholder text |
required | boolean | Whether the field must be filled |
Layouts
Stacked (default)
Fields stack vertically. Best for multi-field forms:
::convert-form{location="apply" layout="stacked" submit-label="Apply"}
::
Horizontal
Email field and button side by side. Best for single-field capture:
::convert-form{location="hero" layout="horizontal" submit-label="Get Early Access"}
::
Anti-Spam Protection
Every form submission includes three layers of anti-spam protection, handled automatically by useFormCapture:
- Honeypot — A hidden field that bots fill but humans don't. If filled, the form silently redirects (bot thinks it succeeded).
- Time-on-form — Tracks how long the form was visible. Submissions under 2 seconds are flagged as suspicious.
- JS token — A
crypto.randomUUID()generated on mount. Bots without JavaScript cannot produce a valid UUID.
These are sent with every submission and validated server-side. See Anti-Spam for the server-side scoring system.
Submission Flow
- User fills form and clicks submit
- Client-side validation — Dynamic Zod schema validates fields
- Honeypot check — If honeypot is filled, silently redirect (bot trap)
- Event fired —
form_submittedevent with formData + antiSpam payload - Webhook provider — Posts to
/api/v1/webhookserver handler - Server processing — Anti-spam scoring, rate limiting, webhook delivery
- Success redirect — Navigate to success page
- On error — Toast notification +
form_errorevent fired
Success Redirect
The redirect path is determined in this order:
successRedirectprop (if set)/success?offer={offerSlug}(ifofferSlugis set)/success(default)
Using in Vue Templates
<ConvertForm
location="pricing-page"
submit-label="Start Free Trial"
layout="horizontal"
offer-slug="trial"
:fields="[
{ name: 'email', type: 'email', placeholder: '[email protected]', required: true },
]"
/>