Identify Users On Webflow
Identify Users on Webflow
Learn how to automatically identify website visitors when they submit forms on your Webflow site, enabling cross-device tracking and enriched visitor profiles in Lytical.
What this enables: When a visitor fills out a form (contact form, newsletter signup, waitlist), 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 Webflow site
- One or more Webflow forms on your site
Where to Add the Code
Add the integration script to your Webflow site using custom code:
Site-Wide (Recommended)
- Go to Project Settings → Custom Code
- Scroll to Footer Code
- Paste the script (make sure it's after your Lytical tracking code)
- Click Save Changes
- Publish your site
Single Page Only
If you only want to identify users on specific pages, go to Page Settings → Custom Code → Before </body> tag for that page.
Webflow Native Forms
This script works with Webflow's built-in form component. It listens for successful form submissions and captures the email and name fields.
<script>
// Lytical + Webflow Form Integration
(function() {
// Helper: Extract fields from form
function extractFields(form) {
var data = Object.fromEntries(new FormData(form));
var result = {};
// Find email field
var emailKeys = ['email', 'Email', 'EMAIL', 'email-address', 'your-email'];
for (var key in data) {
if (emailKeys.includes(key) || key.toLowerCase().includes('email')) {
result.email = data[key];
break;
}
}
// Find name field (full name or first + last)
var nameKeys = ['name', 'Name', 'NAME', 'full-name', 'your-name'];
var firstNameKeys = ['first-name', 'firstName', 'First-Name', 'fname'];
var lastNameKeys = ['last-name', 'lastName', 'Last-Name', 'lname'];
for (var key in data) {
if (nameKeys.includes(key) || key.toLowerCase() === 'name') {
result.name = data[key];
break;
}
}
if (!result.name) {
var firstName = '', lastName = '';
for (var key in data) {
if (firstNameKeys.some(function(k) { return key.toLowerCase().includes(k.toLowerCase()); })) {
firstName = data[key];
}
if (lastNameKeys.some(function(k) { return key.toLowerCase().includes(k.toLowerCase()); })) {
lastName = data[key];
}
}
if (firstName || lastName) {
result.name = [firstName, lastName].filter(Boolean).join(' ');
}
}
// Find phone field
var phoneKeys = ['phone', 'Phone', 'telephone', 'mobile'];
for (var key in data) {
if (phoneKeys.some(function(k) { return key.toLowerCase().includes(k.toLowerCase()); })) {
result.phone = data[key];
break;
}
}
return result;
}
// Auto-detect source from form name or page URL
function detectSource(form) {
var formName = form.getAttribute('name') || form.getAttribute('data-name') || '';
formName = formName.toLowerCase();
if (formName.includes('contact')) return 'contact_form';
if (formName.includes('newsletter') || formName.includes('subscribe')) return 'newsletter_signup';
if (formName.includes('waitlist')) return 'waitlist_signup';
if (formName.includes('demo')) return 'demo_request';
// Fallback to URL detection
var path = location.pathname.toLowerCase();
if (path.includes('contact')) return 'contact_form';
if (path.includes('newsletter')) return 'newsletter_signup';
if (path.includes('pricing')) return 'pricing_inquiry';
return 'webflow_form';
}
// Store form data before submit (Webflow clears on success)
var pendingForms = new WeakMap();
// Capture form data on submit
document.addEventListener('submit', function(e) {
var form = e.target;
if (form && form.tagName === 'FORM') {
pendingForms.set(form, extractFields(form));
}
}, true);
// Listen for Webflow form success
// Webflow adds .w-form-done class to success message
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
mutation.addedNodes.forEach(function(node) {
if (node.classList && node.classList.contains('w-form-done')) {
// Find the parent form
var formBlock = node.closest('.w-form');
var form = formBlock ? formBlock.querySelector('form') : null;
if (form) {
var fields = pendingForms.get(form);
if (fields && fields.email && typeof lyt !== 'undefined') {
var source = detectSource(form);
lyt.identify(fields.email, {
email: fields.email,
name: fields.name || '',
phone: fields.phone || '',
source: source
});
console.log('[Lytical] Identified user:', fields.email);
}
}
}
});
});
});
// Start observing for form success messages
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: true,
attributeFilter: ['style', 'class']
});
// Alternative: Listen for style changes on existing success divs
document.querySelectorAll('.w-form-done').forEach(function(successDiv) {
var formBlock = successDiv.closest('.w-form');
var form = formBlock ? formBlock.querySelector('form') : null;
if (form) {
var styleObserver = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if (mutation.attributeName === 'style') {
var display = window.getComputedStyle(successDiv).display;
if (display !== 'none') {
var fields = pendingForms.get(form);
if (fields && fields.email && typeof lyt !== 'undefined') {
var source = detectSource(form);
lyt.identify(fields.email, {
email: fields.email,
name: fields.name || '',
phone: fields.phone || '',
source: source
});
console.log('[Lytical] Identified user:', fields.email);
}
}
}
});
});
styleObserver.observe(successDiv, { attributes: true, attributeFilter: ['style'] });
}
});
})();
</script>
Simpler Alternative
If the MutationObserver approach doesn't work for your setup, you can use this simpler script that captures form data on submit (before Webflow redirects or shows the success message):
<script>
// Lytical + Webflow Form Integration (Simple)
document.addEventListener('submit', function(e) {
var form = e.target;
if (!form || form.tagName !== 'FORM') return;
// Only process Webflow forms
if (!form.closest('.w-form')) return;
var data = Object.fromEntries(new FormData(form));
// Find email
var email = data.email || data.Email || data['email-address'];
if (!email) {
for (var key in data) {
if (key.toLowerCase().includes('email')) {
email = data[key];
break;
}
}
}
if (!email || typeof lyt === 'undefined') return;
// Find name
var name = data.name || data.Name || '';
if (!name) {
var firstName = data['first-name'] || data.firstName || '';
var lastName = data['last-name'] || data.lastName || '';
name = [firstName, lastName].filter(Boolean).join(' ');
}
// Detect source
var formName = (form.getAttribute('data-name') || '').toLowerCase();
var source = 'webflow_form';
if (formName.includes('contact')) source = 'contact_form';
if (formName.includes('newsletter')) source = 'newsletter_signup';
if (formName.includes('waitlist')) source = 'waitlist_signup';
lyt.identify(email, {
email: email,
name: name,
source: source
});
console.log('[Lytical] Identified user:', email);
}, true);
</script>
Note: The simple script identifies users immediately on form submit. If the form submission fails (validation error, network issue), the user will still be identified. Use the full script with MutationObserver if you only want to identify on successful submissions.
Third-Party Form Tools
If you're using third-party forms embedded in Webflow, use these integrations instead:
Typeform
<script>
window.addEventListener('message', function(e) {
if (e.origin && e.origin.includes('typeform.com') &&
e.data && e.data.type === 'form-submit') {
var fields = e.data.data && e.data.data.fields ? e.data.data.fields : [];
var email = '', name = '';
fields.forEach(function(field) {
if (field.type === 'email') email = field.value;
if (field.type === 'short_text' && field.title &&
field.title.toLowerCase().includes('name')) {
name = field.value;
}
});
if (email && typeof lyt !== 'undefined') {
lyt.identify(email, {
email: email,
name: name,
source: 'typeform'
});
console.log('[Lytical] Identified user:', email);
}
}
});
</script>
Tally
<script>
window.addEventListener('message', function(e) {
if (e.data && e.data.event === 'Tally.FormSubmitted') {
var fields = e.data.payload && e.data.payload.fields ? e.data.payload.fields : [];
var email = '', name = '';
fields.forEach(function(field) {
var label = (field.label || field.key || '').toLowerCase();
if (label.includes('email')) email = field.value;
if (label.includes('name')) name = field.value;
});
if (email && typeof lyt !== 'undefined') {
lyt.identify(email, {
email: email,
name: name,
source: 'tally'
});
console.log('[Lytical] Identified user:', email);
}
}
});
</script>
Webflow Memberships
If you're using Webflow Memberships, you can identify logged-in members. Add this script to your site-wide footer code:
<script>
// Identify Webflow Members
// Note: Requires Webflow Memberships and member to be logged in
if (window.Webflow && Webflow.env && Webflow.env('member')) {
var member = Webflow.env('member');
if (member && member.email && typeof lyt !== 'undefined') {
lyt.identify(member.email, {
email: member.email,
name: member.name || '',
webflow_member_id: member.id || '',
source: 'webflow_membership'
});
}
}
</script>
Form Field Naming
For best results, use these field names in your Webflow forms (set in the field settings panel):
| Field | Recommended Name |
|---|---|
email |
|
| Full Name | name |
| First Name | first-name |
| Last Name | last-name |
| Phone | phone |
Troubleshooting
Users aren't appearing in Identified Users
- Verify the Lytical tracking code loads before the identify script
- Make sure the script is in the Footer Code section (not Head Code)
- Check that you've published the site after adding the code
- Open browser DevTools → Console and look for
[Lytical] Identified user:messages
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
Need help? If you're having trouble with the integration, reach out to our support team and we'll help you get it set up. Email support@lytical.ai.