How To Identify Users From HubSpot Forms
Identify Users from HubSpot Forms
Learn how to automatically identify website visitors when they submit a HubSpot form, enabling cross-device tracking and enriched visitor profiles in Lytical.
What this enables: When a visitor fills out a form (demo request, contact form, newsletter signup), Lytical will link their anonymous browsing history to their real identity. You'll see their name and email in the Identified Users report, and can track them across multiple devices and sessions.
Prerequisites
- Lytical tracking code installed on your website
- One or more HubSpot forms embedded on your site
Where to Add the Code
Add the integration script site-wide so it works on all pages with HubSpot forms. The code only fires when a HubSpot form is submitted, so it's safe to include everywhere.
HubSpot CMS
Go to Settings → Website → Pages → Site Footer HTML and paste the script there.
Google Tag Manager
Create a new Custom HTML tag, paste the script, and set it to fire on All Pages.
Other Platforms
Add the script to your site's footer template, after the Lytical tracking code. Make sure it loads on all pages where HubSpot forms appear.
Choose Your Integration Method
HubSpot has two form systems with different event APIs. Choose the method that matches your setup:
| Method | Best For | Scope |
|---|---|---|
| Universal Script (Recommended) | Works with both legacy and new (V4) forms | Site-wide |
| V4 Global Events | New form editor only (2024+) | Site-wide |
| Legacy PostMessage | Legacy form editor, iframe embeds | Site-wide |
| JavaScript API Callback | Forms via hbspt.forms.create() |
Per-form |
Not sure which form type you have? Use the Universal Script — it listens for both legacy and V4 form events, so it will work regardless of which HubSpot form editor you used.
Method 1: Universal Script (Recommended)
This script listens for both legacy form events (hsFormCallback) and new V4 form events (hs-form-event), ensuring compatibility with any HubSpot form.
Why this is recommended: HubSpot has two different form systems with different event APIs. This script handles both, so you don't need to know which one you're using.
<script>
// Lytical + HubSpot Form Integration (Universal)
// Works with both legacy forms and new V4 forms
// Helper function to identify user
function lytIdentifyFromHubSpot(values) {
var email = values.email;
if (!email || typeof lyt === 'undefined') return;
// Auto-detect source from page URL
var source = 'hubspot_form';
if (location.pathname.includes('demo')) source = 'demo_request';
else if (location.pathname.includes('contact')) source = 'contact_form';
else if (location.pathname.includes('pricing')) source = 'pricing_inquiry';
else if (location.pathname.includes('newsletter')) source = 'newsletter_signup';
lyt.identify(email, {
email: email,
name: [values.firstname || '', values.lastname || ''].filter(Boolean).join(' '),
phone: values.phone || '',
company: values.company || '',
source: source
});
console.log('[Lytical] Identified user:', email);
}
// V4 Forms (new form editor)
window.addEventListener('hs-form-event:on-submission:success', function(event) {
if (!window.HubSpotFormsV4) return;
var form = HubSpotFormsV4.getFormFromEvent(event);
if (!form) return;
form.getFormFieldValues().then(function(fields) {
var values = {};
fields.forEach(function(field) {
// Clean field names (remove prefixes like "0-1/")
var name = field.name.replace(/^[\d]+-[\d]+\//, '');
values[name] = Array.isArray(field.value) ? field.value[0] : field.value;
});
lytIdentifyFromHubSpot(values);
});
});
// Legacy Forms (older form editor, iframes, HubSpot CMS)
window.addEventListener('message', function(event) {
if (event.data.type === 'hsFormCallback' &&
event.data.eventName === 'onFormSubmitted') {
var values = event.data.data.submissionValues || {};
lytIdentifyFromHubSpot(values);
}
});
</script>
Copy and paste this entire script into your site footer. It automatically detects the form source based on the page URL, but you can customize the source detection logic to match your site structure.
Method 2: V4 Global Form Events
If you're only using forms created with HubSpot's new form editor (2024+), you can use the newer hs-form-event API.
How to tell if you have V4 forms: If your form embed code looks like <script src="https://js.hsforms.net/forms/embed/v4/..."> or uses class="hs-form-frame", you have V4 forms.
<script>
window.addEventListener('hs-form-event:on-submission:success', function(event) {
var form = HubSpotFormsV4.getFormFromEvent(event);
if (!form) return;
form.getFormFieldValues().then(function(fields) {
var values = {};
fields.forEach(function(field) {
var name = field.name.replace(/^[\d]+-[\d]+\//, '');
values[name] = Array.isArray(field.value) ? field.value[0] : field.value;
});
var email = values.email;
if (email && typeof lyt !== 'undefined') {
lyt.identify(email, {
email: email,
name: [values.firstname || '', values.lastname || ''].filter(Boolean).join(' '),
phone: values.phone || '',
company: values.company || '',
source: 'hubspot_form'
});
}
});
});
</script>
Available V4 Events
| Event | When It Fires |
|---|---|
hs-form-event:on-ready |
Form has finished loading and rendering |
hs-form-event:on-submission:success |
Form submitted successfully (use this one) |
hs-form-event:on-submission:failed |
Form submission failed |
hs-form-event:on-interaction:navigate |
Multi-step form navigation |
Method 3: Legacy PostMessage Listener
For forms created with HubSpot's legacy form editor, or forms embedded in iframes, use the hsFormCallback postMessage event.
How to tell if you have legacy forms: If your form embed code uses hbspt.forms.create() or the embed version is v2/v3, you have legacy forms.
<script>
window.addEventListener('message', function(event) {
// Only process HubSpot form submission events
if (event.data.type === 'hsFormCallback' &&
event.data.eventName === 'onFormSubmitted') {
var values = event.data.data.submissionValues || {};
var email = values.email;
if (email && typeof lyt !== 'undefined') {
lyt.identify(email, {
email: email,
name: [values.firstname || '', values.lastname || ''].filter(Boolean).join(' '),
phone: values.phone || '',
company: values.company || '',
source: 'hubspot_form'
});
}
}
});
</script>
Available Legacy Events
| eventName | When It Fires |
|---|---|
onBeforeFormInit |
Before form construction |
onFormReady |
After form renders in DOM |
onBeforeFormSubmit |
Start of submission (has field data) |
onFormSubmitted |
After HubSpot accepts submission (use this one) |
Method 4: JavaScript API Callback
If you're embedding HubSpot forms using their JavaScript API (hbspt.forms.create()), you can add the onFormSubmitted callback directly to your embed code.
Note: This method is per-form — you'll need to add the callback to each hbspt.forms.create() call. For site-wide coverage without modifying each form, use the Universal Script instead.
hbspt.forms.create({
portalId: "YOUR_PORTAL_ID",
formId: "YOUR_FORM_ID",
onFormSubmitted: function($form, data) {
var values = data.submissionValues || {};
var email = values.email;
if (email && typeof lyt !== 'undefined') {
lyt.identify(email, {
email: email,
name: [values.firstname || '', values.lastname || ''].filter(Boolean).join(' '),
phone: values.phone || '',
company: values.company || '',
source: 'demo_request'
});
}
}
});
Available Embed Callbacks
| Callback | Parameters | Notes |
|---|---|---|
onFormReady |
$form | After form renders |
onBeforeFormSubmit |
$form, submissionValues | Before submission (preferred over onFormSubmit) |
onFormSubmitted |
$form, {redirectUrl, submissionValues} | After HubSpot accepts (use this one) |
How It Works
- Visitor browses your site — Lytical tracks their pageviews, clicks, and behavior anonymously
- Visitor submits a HubSpot form — The script captures their email, name, and other fields
- Identity is created — Lytical links all their previous anonymous activity to their real identity
- Cross-device tracking begins — If they visit from another device and submit a form with the same email, both devices are linked to the same identity
Viewing Identified Users
Once users are identified, you can view them in Lytical:
- Go to Analytics in the left sidebar
- Click Identified Users under the Data section
- You'll see a list of all identified users with their email, devices, sessions, and pageviews
- Click on any user to see their profile, custom properties, and complete activity history
- Click View Devices to see all browsers/devices linked to that user
Captured Fields
The default script captures these standard HubSpot form fields:
| HubSpot Field | Lytical Property |
|---|---|
email |
email (also used as identifier) |
firstname + lastname |
name |
phone |
phone |
company |
company (stored in custom properties) |
source |
source (auto-detected from URL) |
Adding Custom Fields
If your HubSpot forms have custom fields you want to capture, modify the identify call to include them. Any field not in the standard list will be stored as a custom property:
lyt.identify(email, {
email: email,
name: [values.firstname || '', values.lastname || ''].filter(Boolean).join(' '),
phone: values.phone || '',
company: values.company || '',
// Add your custom fields here:
job_title: values.jobtitle || '',
industry: values.industry || '',
company_size: values.company_size || '',
source: 'demo_request'
});
The field names must match your HubSpot form field internal names. You can find these in HubSpot under Forms → Edit Form → click on a field → "Internal name". Custom properties appear in the user's profile when you click into their Identity Detail page.
Troubleshooting
Users aren't appearing in Identified Users
- Verify the Lytical tracking code loads before the identify script
- Check that your form has an email field (required for identification)
- Open browser DevTools → Console and look for
[Lytical] Identified user:messages - Check the Network tab for requests to
i.lytical.aiafter form submission
Testing the integration
- Open your website in an incognito/private browser window
- Open DevTools → Console before submitting the form
- Browse a few pages to generate anonymous activity
- Submit a form with a test email address
- Look for
[Lytical] Identified user: test@example.comin the console - Wait 1-2 minutes, then check the Identified Users page in Lytical
No console message appears
If you don't see the [Lytical] Identified user message, the form event isn't being captured. Try these steps:
- Make sure you're using the Universal Script (Method 1) which handles both form types
- Check that the script is in your site footer and loads on all pages
- Verify there are no JavaScript errors in the console before form submission
Form values are empty or undefined
If the identify call fires but field values are empty, your HubSpot field names may be different. Add console.log(values) before the identify call to see what field names HubSpot is using, then update your script to match.
Why doesn't the DOM submit listener work?
HubSpot forms intercept the native form submit event and handle submission via AJAX. By the time a document.addEventListener('submit') fires, HubSpot has already processed and potentially cleared the form. That's why we use HubSpot's own event system (hsFormCallback or hs-form-event) instead.