Building blocks

Forms

A form is the list of fields a site asks visitors to fill in. Each website starts with a contact form; add a form for every different thing visitors ask for, like a quote, a pickup or a callback.

What a form is

A form belongs to one website and has a slug that is unique across 1DB, like acme-contact. The site names the form with that slug when it sends a lead, so 1DB knows which fields to expect and which settings to apply. The same visitor can fill in two forms and stay one contact.

Fields

Forms are built from fields, and fields come from your organization’s field library:

  • Standard fields such as email, phone, name, company and message, available to every organization and understood by alerts, contacts and HubSpot.
  • Custom fields your team creates once and reuses across forms, like a pallet size or a pickup window.
  • Presets: saved sets of fields a new form can start from, so every quote form on every site asks the same questions.

A field your site sends that the form doesn’t list isn’t lost. It’s stored with the lead exactly as sent, and added to the field library so you can map it later.

Two ways to put a form on a page

Hosted form, popup on a button
<script src="https://gallant-goshawk-513.convex.site/v1/embed.js?key=1db_YOUR_KEY&form=acme-contact" async></script>
<button data-1db>Get a quote</button>

Field names 1DB understands

Send these under these names and they fill the contact, the alert email and HubSpot without any mapping. Common spellings like firstName or zip work too.

Campaign fields (_1db_utm_source, _1db_gclid, the landing page and referrer) are stored as the lead’s attribution. See capturing UTM parameters.

How submissions are checked

Every lead’s email and phone are checked: an address that can’t receive mail, a throwaway address or a made-up number is refused. Add the header X-1DB-Contract: 2 and 1DB checks every field and answers with all the problems at once:

400 response
{
  "error": "Check the highlighted fields",
  "code": "INVALID_FIELDS",
  "fields": {
    "email": "Did you mean jo@gmail.com?",
    "quantity": "Enter a whole number from 1 to 1,000,000"
  },
  "suggestions": { "email": "jo@gmail.com" }
}

Show each message next to its field. Without the header, the lead is stored as sent unless every contact it gives is certainly wrong. The full rules are in the API reference.

What each form controls

One form per question, not per page

A quote form on twenty pages is one form. Split forms when they ask different things or should reach different people, not because they sit on different pages: the page each lead came from is stored anyway.

From the terminal

Create a form from a template, or list its fields. An asterisk marks a required field.

bash
npx @1db/cli form northfieldpallets --template quote-request
npx @1db/cli form northfieldpallets --name "Callback" --fields "phone*:phone,first_name,message:textarea"