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

# iClosed

> Receive iClosed leads, booked calls, and call outcomes, and send them to your ad platforms.

When you finish, every iClosed lead, booked call, and closed deal arrives in **Events**, linked to the ad click that started it.

## What iClosed sends

| iClosed webhook | Condition | DATALYR event | Money role |
| - | - | - | - |
| Contact created, Contact updated | Status `Potential…` | `lead_submitted` | None |
| Contact created, Contact updated | Status `Qualified` | `lead_qualified` | None |
| Contact created, Contact updated | Status `Disqualified` | `lead_disqualified` | None |
| Call booked | | `call_booked` | None |
| Call rescheduled | | `call_rescheduled` | None |
| Call cancelled | | `call_cancelled` | None |
| Outcome added | `SALE` | `call_showed` and `deal_won` | Contract value. Never revenue |
| Outcome added | `NO_SALE`, reason `NO_SHOW` | `call_no_show` | None |
| Outcome added | `NO_SALE`, reason `FOLLOW_UP_SCHEDULE` | `call_showed` | None |
| Outcome added | `NO_SALE`, reason `ADMIN_CANCELLED` or `CONTACT_CANCELLED` | Nothing | None |
| Outcome added | `NO_SALE`, any other reason | `call_showed` and `deal_lost` | None |
| Outcome added | `APPROVED` (discovery call) | `call_showed` and `lead_qualified` | None |
| Outcome added | `REJECTED` (discovery call) | `call_showed` and `lead_disqualified` | None |

A contact without an email writes nothing. The next Contact updated carries the email and writes the stage.

`deal_won` carries the closer's deal value in `value`, `currency` (default `USD`), and `deal_id` (`iclosed_` plus the outcome ID).

<Warning>
  `deal_won` is contract value, not cash. No revenue report counts it. Connect a payment source such as [Commas](/integrations/commas) or [Stripe](/revenue/stripe) for cash.
</Warning>

## Before you start

| Requirement | Detail |
| - | - |
| DATALYR access | Owner or admin of the workspace |
| iClosed plan | Business plan. If **Settings → Developer → Webhooks** is missing, ask iClosed support to turn on webhooks |
| Web tracking | The [tracking script](/getting-started/install-web-tracking) on every page that links to your iClosed scheduler |
| Thank-you page | A page on your own site that iClosed can redirect to after a booking |

## Connect iClosed

<Steps>
  <Step title="Generate the webhook URL">
    Open **Sources**. On the **iClosed** card, select **connect**. Select **Generate URL**.
  </Step>

  <Step title="Copy the URL">
    Copy the webhook URL. Select **Done**.
  </Step>

  <Step title="Create the webhook in iClosed">
    In iClosed, open **Settings → Developer → Webhooks**. Select **Create Webhook**. Paste the URL.
  </Step>

  <Step title="Tick the triggers">
    Tick **Contact created**, **Contact updated**, **Call booked**, **Call rescheduled**, **Call cancelled**, and **Outcome added**. Save.
  </Step>

  <Step title="Install tracking">
    Add the tracking script to the `<head>` of every page that links to your scheduler.
  </Step>

  <Step title="Redirect after booking">
    In iClosed, open your event. Under **Confirmation page**, choose **Redirect** to your thank-you page. Turn on **Forward parameters**.
  </Step>

  <Step title="Add the thank-you snippet">
    On the thank-you page, paste the snippet below **above** the DATALYR tracking script.
  </Step>
</Steps>

You do not need **Contact by status**.

The URL holds a secret. Treat it like a password.

### The thank-you snippet

Copy it from the **iClosed** card. It removes the invitee's personal fields from the address bar and calls `identify()` with the email.

```html theme={null}
<script>
(function () {
  var PII = ['Invitee_email', 'invitee_email', 'invitee_full_name', 'invitee_uuid', 'text_reminder_number',
    'answer_1', 'answer_2', 'answer_3', 'assigned_to', 'iclosedEmail', 'iclosedName', 'iclosedPhone'];
  var params = new URLSearchParams(window.location.search);
  var email = (params.get('Invitee_email') || params.get('invitee_email') || '').trim().toLowerCase();
  if (!email || email.indexOf('@') < 1) return;
  var phone = params.get('text_reminder_number') || undefined;
  var name = params.get('invitee_full_name') || undefined;

  PII.forEach(function (key) { params.delete(key); });
  var query = params.toString();
  window.history.replaceState(window.history.state, '', window.location.pathname + (query ? '?' + query : '') + window.location.hash);

  var tries = 0;
  (function identify() {
    var dl = window.datalyr;
    if (dl && typeof dl.identify === 'function') {
      dl.identify(email, { email: email, phone: phone, name: name, source: 'iclosed_confirmation' });
      return;
    }
    if (++tries < 50) setTimeout(identify, 200);
  })();
})();
</script>
```

Below the tracking script, it runs too late: the tracker records the email from the URL first.

## How leads match to ad clicks

DATALYR checks these in order and stops at the first one that finds an ad click.

| Order | Source | Comes from |
| - | - | - |
| 1 | `dl_vid` | A DATALYR `visitor_id` on the scheduler link. iClosed returns it in the webhook tracking data |
| 2 | Email | The contact or invitee email, matched to an earlier visit. The thank-you snippet makes that link |
| 3 | UTMs and click IDs | What the iClosed widget read from your page: `utm_source`, `utm_medium`, `utm_campaign`, `utm_content`, `utm_term`, `fbclid`, `gclid`, `gbraid`, `wbraid`, `ttclid`, `li_fat_id`, `msclkid`, `sclid`, `_fbc`, `_fbp` |

UTMs and click IDs on the scheduler link carry through to contact and call webhooks. Outcomes carry no tracking data, so they match by email.

With no match, `visitor_id` is `iclosed_` plus the iClosed contact ID.

## Set up conversion rules

Select the flag icon on the connected **iClosed** card to open the starter rules.

| Event | Meta | TikTok | Value |
| - | - | - | - |
| `call_booked` | `Schedule` | `SubmitForm` | Set a fixed value: what a booked call is worth to you |
| `lead_qualified` | `Lead` | | Set a fixed value: what a qualified lead is worth |
| `deal_won` | `Purchase` | `CompletePayment` | The deal value from `value`. `deal_id` is the order ID |

Meta and TikTok optimize on a 7-day window. Most deals close later, so optimize them on `call_booked` or `lead_qualified`.

Google Ads has no starter rules for iClosed. Create a rule by hand in **Conversions** and pick your conversion action.

If a Commas or Stripe rule also sends `Purchase` to the same pixel, turn one off. Otherwise Meta counts the sale twice.

iClosed's own Meta events use custom names, so they do not collide with DATALYR's. Optimize a campaign on one, not both.

## Verify

1. Open a page that links to your scheduler in a private window. Add `?utm_source=doctest` to the URL.
2. Book a test call with a test email address.
3. Confirm the browser lands on your thank-you page with the personal fields removed from the address bar.
4. Open **Events**. Confirm a `call_booked` row with source `iclosed` and `utm_source` `doctest`.
5. Open **Users**. Find the test email. Confirm the `pageview` and `call_booked` sit on one user.
6. After the call time, add a `SALE` outcome in iClosed. Confirm `call_showed` and `deal_won` arrive with the deal value.

## When it does not work

| Symptom | Cause | Check | Fix |
| - | - | - | - |
| No iClosed events at all | The webhook URL is wrong or the triggers are not ticked | The webhook in **Settings → Developer → Webhooks** | Repaste the URL from the **iClosed** card. Tick all six triggers |
| iClosed shows `401` for each delivery | The `secret` in the URL changed or was cut off | The URL's `?secret=` part | Copy the URL again from the **iClosed** card |
| No `lead_submitted` rows | **Contact updated** is not ticked | The webhook's triggers | Tick **Contact updated** |
| `call_booked` arrives, no outcomes | **Outcome added** is not ticked, or no outcome was entered yet | The call in iClosed | Tick **Outcome added**. Enter the outcome after the call |
| `visitor_id` starts with `iclosed_` | No visit matched the email, and no click IDs reached iClosed | The thank-you page source order | Put the snippet above the tracking script. Install tracking on the page that links to the scheduler |
| The thank-you URL still shows the email | The redirect lands on a page without the snippet, or **Forward parameters** is off | The confirmation page settings | Add the snippet to that page. Turn on **Forward parameters** |
| `deal_won` has no value | The closer left the deal value empty | The outcome in iClosed | Enter the deal value on the outcome |
| Meta counts each sale twice | Two rules send `Purchase` for one sale | **Conversions** | Turn off one of the rules |

## Next

* [Commas](/integrations/commas): record the cash from deals your closers win.
* [Lead generation](/use-cases/lead-generation): choose the stage to optimize toward.
* [Conversion delivery](/advanced/conversion-delivery): how a rule resolves value and identity.


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