# Capture leads

> Ask visitors for a name, email or phone number in the widget, turn the answer into a contact, and give the agent a number it can follow up on.

Source: https://docs.amomic.in/channels/web-chat-leads

---

A visitor asks a good question at 11 p.m., gets an answer, and leaves. Without a contact detail that conversation is over the moment the tab closes. With one, it is a contact your team can reach — and an agent that can follow up on WhatsApp instead of hoping they come back.

The lead form is a short panel inside the widget that asks for some combination of name, email and phone. It is off by default.

**Who can set it up:** owners and admins, on every plan. Open the agent, click **Deploy** → **Web widget** (or **Edit settings** on its live web deployment), go to the **Appearance** step and switch on **Ask for contact details**. The form is saved when you click **Save changes** (or **Set live**) on the **Install** step — not when you leave Appearance.

![Ask for contact details switched on: When to ask After the first reply, Name and Phone required, Email optional, Headline Before we start, a consent line and supporting text. The preview shows the form under the agent's first answer.](https://docs.amomic.in/screens/webchat/deploy-lead-capture.light.webp)

*The lead form settings, with the form in the live preview after the agent's first answer.*

## When it appears

Two timings, and the choice matters more than it looks.

| Timing | Console label | Trade-off |
|---|---|---|
| `before_chat` | `Before the chat` | *"Every visitor is identified, but some will leave rather than fill it in."* |
| `after_first_reply` | `After the first reply` | *"The assistant answers once first, so the ask lands with someone already engaged."* |

`before_chat` maximises capture rate per conversation and reduces the number of conversations. `after_first_reply` does the opposite: fewer forms shown, higher completion, and every lead has already seen the agent do something useful.

For support widgets, `after_first_reply` is almost always right — asking for an email before answering "where is my order" reads as a toll gate. For a sales enquiry form where every visitor is a potential deal, `before_chat` earns its friction.

With **Before the chat**, the form is the first thing in the panel. With **After the first reply**, it appears under the agent's first answer. Either way, when any field is **Required**, the composer is locked and reads *"Fill in the details above to start…"* until the form is submitted. When every field is optional, the composer stays open and the form has a **Skip** button.

::: note It is asked once per visitor, not once per conversation
A visitor who submits the form — or skips it — isn't asked again from the same browser, even after **Start a new chat**. The record lives in their browser storage, so clearing site data resets it.
:::

![The lead form inside the widget under the agent's answer: headline Before we start, Name, Email (optional) and Phone fields, a consent checkbox and a Save details button. The composer reads Fill in the details above to start…](https://docs.amomic.in/screens/webchat/widget-lead-form.light.webp)

*What a visitor sees with After the first reply: the form under the first answer.*

## Skipping

The form has a **Skip** button only when **no** field is marked **Required**. Mark any field required and the form can only be filled in, not dismissed: the visitor has to submit it to keep chatting.

## What you can ask for

Three fields. Each one can be shown or hidden, and each shown field can be optional or required.

| Field | Default |
|---|---|
| **Name** | Shown, required |
| **Email** | Shown, required |
| **Phone** | Shown, optional |

In the console, tick a field under **What to collect** to show it, and tick **Required** beside it to make it mandatory. In the widget, optional fields are labelled *(optional)*, and the phone field shows an example number from your workspace's country. The submit button reads **Start chat** with **Before the chat**, and **Save details** with **After the first reply**.

At least one field must be enabled. Untick all three and the console warns *"Pick at least one detail to collect, or turn the form off."*

A field you disable is not collected, even if something submits it anyway — it is dropped server-side, not just hidden.

Three pieces of copy frame the ask:

| Setting | Limit | Default |
|---|---|---|
| **Headline** | 80 characters | `Before we start` |
| **Supporting text** | 240 characters | `Tell us how to reach you and we'll pick up right where you left off.` |
| **Consent line** | 300 characters | Empty |

The consent line is optional and renders with a checkbox the visitor must tick. Use it when your privacy notice requires an explicit act of agreement — *"I agree to be contacted about my enquiry."* — rather than an inferred one. If you leave it empty, no checkbox is shown and no consent is recorded.

::: tip Ask for less than you want
Every field is a reason to close the tab. Phone plus name beats phone plus name plus email plus company plus role, and a phone number is worth more than the rest combined because it is the one channel your agent can follow up on by itself.
:::

## What happens to a submission

Three things, in this order:

**A contact is matched or created.** The email and phone are looked up in your **Contacts**. If either matches an existing contact, the lead is linked to that contact **as it is**: nothing on the existing contact is added or changed. If neither matches, a new contact is created with the name, email and phone.

**The conversation is stamped with the customer.** The chat that was anonymous ten seconds ago now carries a name, email and phone. Anyone opening it in the inbox sees who they are reading, and the agent has the same information for the rest of the conversation.

**A `lead.created` event fires.** If you have a webhook endpoint subscribed, your systems are told immediately — with the contact id, name, email and phone. That is the hook for pushing the lead into your own CRM, starting a nurture sequence, or paging a salesperson while the visitor is still on the page. See [Event reference](/webhooks/events).

::: note The lead is kept even when no contact is linked
Two cases leave a lead without a contact: the email matches one contact and the phone matches a different one (Amomic-AI won't guess which is right), or the contact lookup fails for a moment. Either way the submission is still recorded and the visitor still sees a success. Treat `contact_id` in the webhook payload as something that can be absent.
:::

## Validation

The form validates on submit, and the messages a visitor sees are these exactly.

| Message | Cause |
|---|---|
| *"Please fill in every required field."* | A field marked required was left empty. The response names which ones. |
| *"Please share at least one contact detail."* | Every field was left empty. |
| *"That email address doesn't look right."* | The email failed the format check. |
| *"That phone number doesn't look right."* | The phone number could not be normalised into a usable international number. |
| *"This widget is not collecting contact details."* | Lead capture is switched off for this widget. A visitor should never see this; it means something is submitting to a form that is not enabled. |

Submitting the form counts against the widget's [rate limit](/channels/web-chat#rate-limit) of 12 requests per 60 seconds per visitor, like sending a message does.

### Email

The check is a format check, not a delivery check: some text, an `@`, a domain with a dot, and a plausible ending. `asha@example.com` passes. `asha@example` fails. `asha at example.com` fails.

Nothing verifies that the mailbox exists. `nobody@example.com` is a perfectly valid-looking address and will be accepted. If your process depends on the address being real, send something to it and see.

### Phone numbers

Phone input from real people is a mess — spaces, dashes, brackets, a leading zero out of habit, sometimes a country code and sometimes not. All of it is normalised into a single international form before it is stored.

The rule, in two parts:

1. **A number that carries its own country code is taken at its word.** A leading `+` or `00` is the visitor stating which country they are in, and it is never overridden.
2. **A number without one is read as a local number in your workspace's country** — the country you chose when you created the workspace, under **Settings → Organization**.

Part 2 is why the same ten digits can be two different people. `4155552671` is a San Francisco line for a workspace based in the United States and a number in India for a workspace based in India, and nothing in the digits themselves distinguishes the two. Your workspace country is what decides.

The number is then checked against that country's own numbering plan — how long its numbers are, which prefixes it issues — and stored as `+` followed by the full international form. Anything that is not a real number in that country is rejected rather than completed, because a completed guess is a number that belongs to a stranger.

Worked examples, for a workspace based in **India**:

| Visitor typed | Stored as | Why |
|---|---|---|
| `9876543210` | `+919876543210` | A local mobile, read against the workspace's country. |
| `098765 43210` | `+919876543210` | Punctuation removed and the trunk zero dropped, which is India's own rule. |
| `+91 98765 43210` | `+919876543210` | Already carries its country code. |
| `(022) 6985 0800` | `+912269850800` | A Mumbai landline, written the way landlines are written. |
| `+1 415 555 2671` | `+14155552671` | Carries a country code, so the workspace's country is irrelevant. |
| `12345` | rejected | Not a number in any plan. *"That phone number doesn't look right."* |

The same table for a workspace based in the **United States**:

| Visitor typed | Stored as | Why |
|---|---|---|
| `4155552671` | `+14155552671` | A local line, read against the workspace's country. |
| `(415) 555-2671` | `+14155552671` | Punctuation removed. |
| `+91 98765 43210` | `+919876543210` | Carries a country code — an Indian customer of a US business stays Indian. |
| `9876543210` | rejected | Ten digits, but `987` is not a US area code. See below. |

That last row is the one worth understanding. `9876543210` is an ordinary mobile number in India, and read against a US workspace it would become `+19876543210` — an area code North America has never assigned, so a number that cannot ring. It is refused rather than stored, because a stored number that silently cannot be reached is worse than a visitor being asked to check what they typed.

The same is true in reverse, and in every direction: the check is always "is this a real number in *that* country", not "is this ten digits".

::: tip Selling into a country that isn't yours
The workspace country sets the default, not a restriction: a visitor anywhere can always type their full international number, and it will be stored exactly as they meant it. If most of your visitors are outside your own country, say so in the form: a **Supporting text** that reads *"Include your country code with your phone number"* removes the ambiguity. The field labels themselves can't be changed.
:::

## Duplicate submissions

The same person, twice, is one contact — but the second submission doesn't update it.

- A submission whose email **or** phone matches an existing contact is linked to that contact. No second contact is created.
- The existing contact keeps the details it already had. Someone who gave `meera.k@gmail.com` in March and `meera@krishnan.in` in August with the same phone number stays one contact with the March email. The August email is on the lead and in the `lead.created` event, not on the contact.
- If the email belongs to one contact and the phone to another, the lead is kept with no contact linked.

Update a contact's details yourself in **Contacts** when a lead tells you something new.

For your own systems: **treat `contact_id` from the `lead.created` event as the identity, not the email address.** Two events can carry different emails and the same contact.

## Why the phone number is the valuable field

A captured phone number is what lets an agent continue the conversation on WhatsApp.

The chain is short: the lead becomes the conversation's customer, the customer carries a phone number, and an agent that has a phone number can send a WhatsApp message to it. A visitor who asks about delivery to Pune at midnight and leaves can get an answer on WhatsApp when the warehouse confirms in the morning — on a channel they will actually see, rather than an email they will not.

Two things to keep in mind before you build on it:

- **The [24-hour window](/channels/whatsapp-window) still applies.** Capturing a number does not open a WhatsApp session. Outside an open window you need an approved template, not free text.
- **A number in your CRM is not consent to message it.** The visitor gave you a way to reach them about *their enquiry*. Use the consent line if you need a recorded basis for anything broader, and honour opt-outs — they are enforced across every number in your workspace.

## Troubleshooting

::: details The form never appears
Check four things: **Ask for contact details** is on, you clicked **Save changes** on the Install step after turning it on, at least one field is enabled, and the visitor hasn't already answered it. Their browser remembers a previous submission or skip — clear site data or use a private window to test again. With **After the first reply**, the form only appears once the agent has answered.
:::

::: details A visitor says their phone number was rejected
It is not a valid number in your workspace's country and did not carry a country code of its own. Usually an extension typed on the end, a partially entered number, a country code entered twice — or a visitor in another country who left their country code off. Ask for the full international number.
:::

::: details Leads arrive without a contact in the CRM
Contact resolution failed for that submission and the lead was kept anyway. The webhook payload will have no contact id. If it happens consistently rather than occasionally, something is wrong beyond one bad write — raise it with support.
:::

::: details Two leads created one contact
Working as designed: a matching email or phone links the lead to the existing contact. See [duplicate submissions](#duplicate-submissions).
:::

::: details A visitor gave a new email but the contact still has the old one
Leads never change an existing contact. The new email is on the lead and in the `lead.created` event. Edit the contact in **Contacts** if you want to keep it.
:::

::: details Visitors can't close the form
A form with any **Required** field has no **Skip** button. Untick **Required** on every field if you want visitors to be able to skip it.
:::

::: details An international number was stored under the wrong country
It was typed without a country code, so it was read as a local number in your workspace's country. Check that your workspace country is right under **Settings → Organization**, and ask visitors for a country code in the form's **Supporting text**.
:::

## Next

::: cards

::: card Install the widget
[The one-line tag](/channels/web-chat) and the domain allowlist that keeps it on your own site.
:::

::: card Customise it
[Appearance, greeting and image upload](/channels/web-chat-config) — the form lives in the same setup step.
:::

::: card Follow up on WhatsApp
[Set up WhatsApp](/channels/whatsapp) so a captured number becomes a conversation the customer will actually read.
:::

::: card Get the event
[`lead.created`](/webhooks/events) — push every capture straight into your own systems.
:::

:::
