WebApp Modules

Opt-in Forms

Lead capture forms you can embed inside your WebApp or on any external site — with built-in anti-spam, phone validation, and automatic tag + automation integration.

What are Opt-in Forms?

Opt-in Forms turn your Contacts module into an active intake system. You configure a form once in the admin, pick which fields to collect and which tags to apply, then drop the embed code on any page. When someone submits:

  1. A contact is created (or updated by email if one already exists).
  2. The configured tags are applied, firing contacts.tag_added events.
  3. Any email automations triggered by those tags start enrolling the contact immediately.
  4. The visitor is optionally redirected to a thank-you URL.

Email is always required on every form. Phone is optionally required per form. You can collect additional standard fields (first name, last name) and any Custom Contact Fields you've defined.

Prerequisite: If you want to collect business-specific data, define the fields first on the Custom Fields page. The form builder offers them as checkable options.

Embedding a Form

Every form exposes two embed options — pick whichever fits the page you're embedding on. The same form can be embedded either way; the data, tags, and behavior are identical.

React component (inside your WebApp)

For pages that live inside your WebApp. The form renders as a React component using the existing @dashnex/ui component library, so it automatically matches the rest of your admin / portal UI. The embed code is a React tag:

<OptinForm formId="cl123..." />

Vanilla JS embed (external sites)

For landing pages on any third-party site. You get a standalone self-contained JavaScript bundle (approximately 45KB — includes phone validation data) that renders plain HTML with predictable class names. No framework required on the host page. The embed code is a div plus a script tag:

<div id="dnx-optin-cl123..."></div>
<script src="https://your-webapp.com/api/contacts/optin/cl123.../embed.js"></script>

The script ships with default CSS so the form looks clean out of the box. Form elements also expose predictable class names — dnx-optin-field, dnx-optin-input, dnx-optin-submit, dnx-optin-phone-country, etc. — so you can override the defaults with your own CSS to match the host site.

Configuring a Form

From the edit page you can set:

  • Form Name — Internal label.
  • Redirect URL (optional) — Where to send the visitor after a successful submit. If blank, the inline success message below is shown instead.
  • Submit Button Text — Defaults to “Subscribe”.
  • Success Message — The inline message shown after a successful submit (when no redirect URL is configured). Defaults to “Thank you for subscribing!”.
  • Form Fields — Pick which fields to show on the form (details below).
  • Tags on Submit — Tags applied to the contact on successful submission. These are what trigger downstream automations.
  • Status — Active / Inactive. Inactive forms stop responding to new submissions.

Form Fields

Email is always present and always required — you can't turn it off, since email is the upsert key for contacts.

The remaining fields are opt-in via checkboxes. Each field you include shows a Required switch next to it so you can decide, per field, whether it must be filled to submit.

  • Standard fieldsFirst Name, Last Name, and Phone. Phone renders with a country selector and is validated client-side via libphonenumber-js when included.
  • Custom fields — Every custom contact field you've defined is offered here as a checkbox. Checked fields appear on the form with inputs matching their type (text, number, date, dropdown, checkbox, etc.), each with its own Required switch.

Anti-Spam Protection

Every form is spam-protected out of the box — no CAPTCHA setup or external service needed. Bot submissions, replay attacks, and high-volume abuse are blocked automatically, regardless of which embed option you use.

Validation

Every submission is validated server-side (with matching client-side validation for fast feedback):

  • Email — Always required, validated as a well-formed email address.
  • Phone — If the phone field is included on the form and a value is entered, it must pass libphonenumber-js' isValidPhoneNumber() check for the selected country. If the field is also marked Required, submission is blocked when empty.
  • Custom fields — Each value is validated against its field definition (number, dropdown option, required flag, etc.). See the Custom Fields validation rules.

On an existing contact, custom field values merge with what's already stored — the form only touches the keys it submits, leaving everything else intact.

Managing Forms

Go to Contacts → Opt-in Forms in the sidebar. The list page shows:

  • Name
  • Phone — whether the phone field is included on the form
  • Applied tags
  • Status toggle (activate / deactivate inline)
  • Created date
  • Actions: Edit, Delete, and other quick actions via the row menu

The edit page shows your live form preview on the right alongside two embed snippets — a React tab and a JavaScript tab — switch between them and use the Copy button to grab whichever embed code you need.

Downstream: Tags + Automations

Opt-in Forms don't have their own email logic — they feed the Automations engine. Pick tags on the form, build automations triggered by those tags, and you have a complete lead capture → nurture pipeline:

Form submit → contact upsert → tag applied
                                    ↓
                contacts.tag_added event
                                    ↓
                automation enrollment → drip emails

Next Steps

  • Contacts — Define custom fields and manage tags the form will apply.
  • Automations — Build tag-triggered email sequences that turn captured leads into customers.
  • Email Library — Pre-build the emails those automations will send.