> ## Documentation Index
> Fetch the complete documentation index at: https://docs.brosbots.com/llms.txt
> Use this file to discover all available pages before exploring further.

# The lead loop

> Form to call, call to spreadsheet, spreadsheet to follow-up calls - and how to set it up without calling anyone twice.

Two separate mechanisms make up the loop, and it is worth knowing which one is
doing what:

1. **The lead webhook** calls a person seconds after they submit your form.
   One person, one call, right away.
2. **A campaign watching a sheet** calls whoever is on a contact list, and
   keeps re-reading that list as it grows.

The spreadsheet sits between them: the agent writes a row after every call, and
a campaign can read a sheet as its contact list. Nothing connects the two
automatically - you point the campaign at a sheet yourself, once.

## What happens, in order

<Steps>
  <Step title="Someone submits your form">
    Your form posts to the agent's webhook URL. The payload is read whatever
    shape it arrives in, the phone number is normalized, and a duplicate
    submission within 10 minutes is ignored. See
    [Calling website form leads back](/en/integrations/leads/lead-webhook).
  </Step>

  <Step title="The agent calls">
    Inside your calling hours the call goes out immediately; outside them the
    lead is held and called when the window opens. Everything the form sent is
    available to the agent as a variable.
  </Step>

  <Step title="The call is written to the spreadsheet">
    With **Write every call to Google Sheets** switched on, a row is appended
    after every call: date, time, phone, the details the agent collected, the
    summary, next steps, whether the goal was reached, the call outcome and a
    link to the recording.
  </Step>

  <Step title="A campaign works the list">
    Point a campaign at a spreadsheet and switch on **Keep watching this
    sheet**. It re-reads the sheet on your interval, queues the numbers it has
    not queued before, and calls them. See [Campaigns](/en/features/campaigns).
  </Step>
</Steps>

## Setting up the follow-up campaign

The campaign reads the **first tab** of the spreadsheet, columns A to Z, with
the first row as headers. So do not point it at the agent's own results sheet -
put the people you want called into a spreadsheet of their own.

<Steps>
  <Step title="Make a spreadsheet for the follow-up list">
    In a new spreadsheet, pull in the rows worth calling again, for example:

    ```
    =QUERY(IMPORTRANGE("<results sheet URL>", "Leads!A:I"), "select Col3, Col4 where Col8 = 'nie'", 1)
    ```

    Adjust the columns and the condition to your sheet. Keep the headers in the
    first row and the data on the first tab.
  </Step>

  <Step title="Let the Sheets connection open it">
    Signed in with Google: nothing to share - pick the spreadsheet with
    **Choose spreadsheet** in the next step. An older service account
    connection: share the spreadsheet with its service account e-mail, with at
    least read access.
  </Step>

  <Step title="Create the campaign">
    **Campaigns → New campaign**, source **Google Sheet**, choose or paste the
    spreadsheet, switch on **Keep watching this sheet** and pick an interval.
  </Step>
</Steps>

## Which column holds the phone number

Any of them. The column is found by name (`phone_number`, `Phone`, `Telefon`,
`Mobile`, `Numer telefonu`…) and, when the name is unusual, by the shape of its
values. Numbers are normalized before dialling, so `600 123 456`,
`+48 600-123-456` and `0048600123456` are the same person.

Every other column is passed into the call as a variable under its own name -
`{{first_name}}` in the prompt or the first message greets the person by name.

## Who is called, and who is not

| Situation | What happens |
| - | - |
| A row is added to the watched sheet | Queued at the next read and called |
| A row that was already queued | Left alone - nobody is called twice by the same campaign |
| The same number written differently in two rows | One contact |
| Rows sorted, filtered or inserted above | Nothing is re-queued; contacts are keyed by number, not by row |
| A row without a usable number | Skipped, and counted in the sync log |
| The campaign is paused | New contacts are collected, nobody is dialled until you resume |
| The campaign had finished | It goes back to running as soon as somebody new turns up |
| The sheet cannot be read (unshared, renamed) | The campaign is left alone and the sheet is tried again next interval |

<Warning>
  The webhook and the campaign do not know about each other. If you point a
  campaign at a sheet holding leads the agent already called, those people get a
  second call - from the campaign. That is fine when you meant it (a follow-up
  wave for everyone who did not answer), so filter the follow-up sheet down to
  the rows you actually want called.
</Warning>

## When nothing happens

| Symptom | Usual cause |
| - | - |
| The campaign starts with 0 contacts | The data is not on the first tab, or the Sheets connection cannot open the sheet (not chosen with **Choose spreadsheet**, or not shared with an older service account) |
| New rows are not picked up | Watching is off, or its interval has not elapsed yet - the campaign page shows the last read |
| A lead from the form is never called | The form did not send a phone number the webhook could use - the form tool's delivery log shows the `400` |
| Everything is queued but nothing dials | The agent has no phone number assigned, or the organization is out of credit |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.