This guide explains how Userled Forms tracking works, how to integrate it, and what limitations to expect in production.
When a visitor submits a tracked form, Userled:
Tracks the conversion event to expose it in Userled analytics.
Attempts to identify the visitor using the submitted email (plus name fields if provided).
Associates the conversion with page and campaign context when available.
This works for HubSpot, Marketo, native forms and other form formats as long as you trigger the tracking call from your submit/success callback.
When the form tracking hook is added to your forms, Userled can track form submissions across your website, Userled assets built on top of pages on your website and Userled landing pages.
Note: in order to track form submissions on your website you need to first install the Userled SDK.
In order to successfully track a form submission, you need to pass the submission email to Userled via the tracking code. If no email is provided, tracking is skipped.
Use the same command everywhere:
window.Userled("trackFormSubmission", {
email: "user@company.com",
firstName: "Jane",
lastName: "Doe",
formType: "hubspot", // "hubspot" | "marketo" | "custom" | "unknown"
formId: "your-form-id",
formName: "Newsletter signup",
});
Add this inside your form success hook e.g. onSubmit, onFormSubmit, onSuccess, etc.
Supported fields for trackFormSubmission:
email (required)
firstName (optional)
lastName (optional)
name (optional, alternative to first/last)
formId (optional, strongly recommended)
formType (optional but recommended: hubspot / marketo / custom / unknown)
formName (optional, strongly recommended)
rawPayload (optional key-value object with submitted fields)
assetId (optional; used when you need explicit asset context)
hbspt.forms.create({
portalId: "YOUR_PORTAL_ID",
formId: "YOUR_FORM_ID",
onFormSubmit: function ($form) {
var emailInput = $form.querySelector('[name="email"]');
var email = emailInput ? emailInput.value.trim() : "";
if (!email || !window.Userled) return;
window.Userled("trackFormSubmission", {
email: email,
firstName: $form.querySelector('[name="firstname"]')?.value?.trim(),
lastName: $form.querySelector('[name="lastname"]')?.value?.trim(),
formType: "hubspot",
formId: "YOUR_FORM_ID",
formName: "Website demo request",
});
},
});
MktoForms2.loadForm("//your-instance.marketo.com", "MUNCHKIN_ID", FORM_ID, function (form) {
form.onSuccess(function (values) {
var email = String(values.Email || values.email || "").trim();
if (!email || !window.Userled) return false;
window.Userled("trackFormSubmission", {
email: email,
firstName: values.FirstName ? String(values.FirstName).trim() : undefined,
lastName: values.LastName ? String(values.LastName).trim() : undefined,
formType: "marketo",
formId: "mktoForm_" + form.getId(),
formName: "Marketo lead form",
});
return false; // optional: keep user on page
});
});
document.querySelector("#signup-form")?.addEventListener("submit", async function (e) {
e.preventDefault();
var form = e.target;
var formData = new FormData(form);
var response = await fetch("/api/signup", { method: "POST", body: formData });
if (!response.ok) return;
var email = String(formData.get("email") || "").trim();
if (!email || !window.Userled) return;
window.Userled("trackFormSubmission", {
email: email,
firstName: String(formData.get("firstName") || "").trim() || undefined,
lastName: String(formData.get("lastName") || "").trim() || undefined,
formType: "custom",
formId: "signup-form",
formName: "Signup form",
});
});
If the form is inside a cross-origin iframe, the iframe cannot directly access the parent window.Userled object due to browser security rules.
Typical symptom:
no tracking call fires, or
browser throws cross-origin/SecurityError behavior.
Recommended options:
host the form in a same-origin wrapper page, or
pass submission data to a same-origin parent page (e.g. postMessage) and call window.Userled("trackFormSubmission", ...) in the parent handler.
email is required for tracking and re-identification.
Missing or invalid emails will not produce a successful tracked submission.
Conversion events can still be recorded when an email is present, including personal domains, but no contact will be created. If this user didn’t have a contact before, the event will not be seen in the Userled dashboards.
Userled deduplicates rapid duplicate submits for the same key:
key: email + formId + formName
window: 5 seconds
If you trigger tracking multiple times for one submit, only one event may be kept.
Some pages/forms cannot be embedded in iframes because of CSP / frame policy restrictions.
If your own hosted content must be embedded in Userled experiences, update CSP frame-ancestors to allow Userled domains, for example:
frame-ancestors 'self' <https://app.userled.io> <https://<subdomain>.<yourdomain>.com>;
Notes:
include your custom Userled LP domain if configured
exact directives depend on your security setup
your web/security admin typically owns this policy
Submit with a valid work email and verify conversion appears.
Submit with missing email and verify tracking is skipped.
Submit twice quickly and verify deduplication behavior.
Test iframe deployments:
same-origin iframe (should work),
cross-origin iframe (expect direct parent access limitations).
If using embedded pages, verify CSP/frame policy allows embedding.
IP blocklisting: If you are registered to Userled, we will ignore any tracking activity originating from your IP/browser. You can test by opening an incognito browser and/or switching your device to use a cellular network rather than Wifi as your Wifi’s IP address has likely been blocklisted by Userled.
No conversion event appears: ensure callback runs, email is present, and window.Userled exists at callback time.
Iframe form not tracked: verify origin relationship; cross-origin cannot call parent API directly.
Unexpected missing contact/account linkage: test with a work email domain and confirm your identity/account creation flow.
Too many or too few events: check duplicate callback invocations and dedupe window assumptions.