Website Form Capture
When enabled, the widget watches every form on your site and forwards email / phone / name / company-name fields to the Identity Graph as soon as a visitor submits one. This identifies the visitor instantly, builds out their Person Profile, and (because it's a first-party form) directly verifies the session for cross-session AI context.
What gets captured
Across native HTML forms, single-page-app submit buttons, Enter-key submissions, and embedded third-party form iframes, the script extracts:
- Email —
<input type="email">, fields withname/id/label containing "email", or any field whose value matches an email pattern. - Phone —
<input type="tel">, fields withname/id/label containing "phone" / "tel" / "mobile" / "cell". - Name — fields named
name,full_name,first_name,last_name, etc. First + last are joined into one display name. - Company / business name — fields named
company,company_name,business,organization,employer,workplace.
That's it. No password fields. No hidden fields. No credit-card / CVV / SSN / routing-number fields. No file uploads. No fields outside the visible form.
What gets sent
A small JSON payload with the captured fields, your user_session_id, and your company_id. No raw form HTML. No DOM screenshots. No third-party services — the request goes to your Knock Knock backend over the existing widget connection.
To make sure ad-blockers, privacy extensions, and CORS configurations don't drop the submission, the script tries three transports in order:
- The widget's existing socket connection — invisible to ad-blockers because it's the chat product's own channel.
navigator.sendBeacon— survives page navigation immediately after submit.fetchwithkeepalive: true— final fallback.
All three send as text/plain (a CORS-safelisted content type), so no preflight is needed and there's nothing for blockers to filter on path or content-type.
Supported third-party form providers
When you embed a form from one of these providers as an iframe, the script also captures submissions from the iframe via the postMessage channel:
| Provider | Detected origin | Notes |
|---|---|---|
| HubSpot Forms | hsforms.net, hubspot.com | Listens for hsFormCallback / onFormSubmit events. |
| Calendly | calendly.com | Listens for calendly.event_scheduled (a booking is itself a verified identification trigger). |
| GoHighLevel | leadconnectorhq.com, msgsndr.com, gohighlevel.com, plus white-label customer domains | Recognises set-sticky-contacts, lc-form-submit, V2 form fields shape, and contact-id payloads. |
| Typeform | typeform.com | |
| Jotform | jotform.com, jotform.us | |
| Mailchimp | list-manage.com |
White-label deployments (e.g. a GHL form served from app.<your-customer>.com instead of leadconnectorhq.com) are auto-detected: the script scans the page for iframes whose src carries provider fingerprints (/widget/form/, /widget/survey/, /forms/<id>) and dynamically allowlists those iframe origins.
Turning it on
Owned by the super admin. The capture_website_forms flag lives in the global Identity Graph defaults (and can be overridden per company). On the customer side there's no toggle — when the admin enables it, the form-intercept script is injected alongside the widget on every page where the widget loads. See Admin Controls.
Known limitations
- Some GoHighLevel V2 forms submit server-to-server. If GHL's iframe doesn't post any client-side event after submit, we can't see it — the form data goes directly from the iframe to GHL's backend. In that case the canonical alternative is to set up a GHL workflow that webhooks form submissions back to your tenant.
- Iframes from origins not in the allowlist are ignored. If you're using an embedded form provider that isn't listed above, contact support and we can add it.
- Cleared browser storage loses the verification anchor. The next session will be treated as
claimeduntil another verification trigger fires (form, CRM landing, inbound call).