# Forms and leads examples

> Concrete ClickClacks examples for forms: how many people start a lead form and how many submit it, where the rest drop off, and how many join the newsletter from each placement and campaign.

- Canonical URL: https://clickclacks.io/docs/examples/forms
- Section: Examples
- Last updated: 2026-09-26

How many people start your demo form and how many send it? Where do the others give up? Which newsletter box brings subscribers? Autocapture sees a little of this. Two custom events see all of it, without sending a word anyone types.

The snippets assume the [script tag](https://clickclacks.io/docs/install.md) and the [queue stub](https://clickclacks.io/docs/events.md#before-load) are in the page’s `<head>`. The `data-…` attributes are for your own script; ClickClacks doesn’t read them.

## How many people start the demo form, and how many send it? {#lead-form}

### Fastest: autocapture and a thank-you page {#lead-form-fast}

Clicks into form fields arrive as `$click` with **Clicked element** `input` or `textarea`, on the form’s **Page**, and never with any text. That is a rough “started”. A submit `<button>` sends its label as **Clicked text**, but a click isn’t a successful submission: the browser may refuse the form, or your server may. An `<input type="submit">` carries no text at all.

If a successful submission lands on its own page, such as `/demo/thanks`, that page’s `$pageview` is a reliable “submitted” with no code.

### Precise: “started” and “submitted” events {#lead-form-precise}

```html title="demo.html"
<form data-form="demo-request" action="/demo" method="post">
  <input name="company" autocomplete="organization">
  <input name="work_email" type="email" autocomplete="email">
  <button type="submit">Request a demo</button>
</form>

<script>
  document.querySelectorAll('form[data-form]').forEach(function (form) {
    var name = form.dataset.form
    var started = false

    // The first time anyone moves into a field of this form.
    form.addEventListener('focusin', function () {
      if (started) return
      started = true
      window.clickclacks?.('event', 'Form started', { form: name })
    })

    // Fires after the browser's own validation passes.
    form.addEventListener('submit', function () {
      window.clickclacks?.('event', 'Form submitted', { form: name })
    })
  })
</script>
```

Forms sent with `fetch` never fire a page load, and their `submit` event fires before your server has answered. Send `Form submitted` when the request succeeds instead:

```js title="demo-form.js"
async function sendDemoRequest(form) {
  const response = await fetch('/api/demo-requests', { method: 'POST', body: new FormData(form) })
  if (response.ok) {
    window.clickclacks?.('event', 'Form submitted', { form: 'demo-request' })
  }
  return response
}
```

### Read the answer {#lead-form-read}

1. In [Funnels](https://clickclacks.io/docs/guides/funnels.md), click **New funnel**. Step 1: `Form started`, **+ Filter** › **Form** _is_ `demo-request`.
2. Step 2: `Form submitted` with the same filter. Save it as _Demo form_.
3. Read **Overall conversion** and **Median time to convert**.
4. Click the drop to see who started and never sent it, and open **What they did instead**.
5. Choose **Break down by** › **Device** to check whether one device struggles.

> **What you should see**
>
> Something like _62% of people who start the form send it_, usually within a couple of minutes. A much lower rate on mobile points at the form’s layout. Open the page in [Heatmaps](https://clickclacks.io/docs/guides/heatmaps.md) on **Mobile** and check [Friction](https://clickclacks.io/docs/guides/friction.md) for dead or rage clicks on its button.

To see how many visitors to `/demo` start the form at all, add a step before both: `$pageview` where **Page** _is_ `/demo`.

## How many people join the newsletter, from which box and which campaign? {#newsletter}

### Fastest: autocapture, for clicks only {#newsletter-fast}

A _Subscribe_ button sends its label as **Clicked text**, and **Page** says which page it was on. That counts attempts, including invalid addresses and people already subscribed, not sign-ups.

### Precise: an event after the sign-up succeeds {#newsletter-precise}

```html title="footer.html"
<form id="newsletter" data-placement="footer">…</form>

<script>
  var newsletter = document.getElementById('newsletter')
  newsletter.addEventListener('submit', function (event) {
    event.preventDefault()
    fetch('/api/newsletter', { method: 'POST', body: new FormData(newsletter) })
      .then(function (response) {
        if (!response.ok) return
        // After the subscription succeeded, never with the address.
        window.clickclacks?.('event', 'Newsletter joined', {
          placement: newsletter.dataset.placement,
        })
      })
  })
</script>
```

### Read the answer {#newsletter-read}

1. In [Insights](https://clickclacks.io/docs/guides/insights.md), chart `Newsletter joined` as **Unique people**, **Weekly**.
2. **Add breakdown** › **Event property** › **Placement** to compare the footer box with the others.
3. Change the breakdown to **UTM source** or **Referrer**. They are the visit’s values, so a sign-up three pages after landing still counts toward the campaign that brought the visit.
4. For a sign-up rate, set series A to `$pageview` as **Unique people**, series B to `Newsletter joined`, and add the formula `B / A * 100`.

> **What you should see**
>
> Weekly sign-ups split by where the box sits, and which campaigns bring subscribers rather than just visits.

## Keep form data out {#privacy}

- Never send what people type, such as an email address, name or company, as a property. Send which form, which step and whether it worked.
- Autocapture never records field values or the text of anything clicked inside a field. See [what autocapture never captures](https://clickclacks.io/docs/autocapture.md#never).
- To tie a lead to a person you already know, call [identify](https://clickclacks.io/docs/identify.md) with your own user ID, not their email.
- Mark anything else sensitive with `data-cc-mask`: clicks inside it carry no text, and [heatmap captures](https://clickclacks.io/docs/heatmap-capture.md) leave it out.

## Related {#related}

- [All examples](https://clickclacks.io/docs/examples.md)
- [Marketing site](https://clickclacks.io/docs/examples/marketing-site.md): Buttons, FAQs, pricing, links and video.
- [Funnels](https://clickclacks.io/docs/guides/funnels.md): Steps, windows and who dropped off.
- [What’s collected](https://clickclacks.io/docs/privacy.md): What the tracker stores and strips.
