How to Integrate Convert.com Experiences with HubSpot Forms
Guide to help integrate Convert.com experience data to HubSpot forms
IN THIS ARTICLE YOU WILL:
- Know the Prerequisites for the Integration
- Learn the Implementation Steps
- Best Practices
- Troubleshooting Steps
This guide will show you how to append Convert.com experience data to HubSpot forms as hidden fields, allowing you to track which experiences and variations your form submissions were exposed to.
Prerequisites
- Active Convert.com account with experiences running
- HubSpot account with forms set up
- Access to modify your website's JavaScript
- HubSpot hidden fields created for the experience and variation data
- For HubSpot’s newer form renderer, access to the HubSpot Forms V4 global object on the page
Implementation Steps
1. Create Hidden Fields in HubSpot Form
First, create two hidden fields in your HubSpot form:
- convert_experience_names
- convert_variation_names
📒 Note:
In HubSpot’s newer form renderer, field names may be prefixed, for example 0-1/convert_experience_names and 0-1/convert_variation_names. The integration code below accounts for both prefixed and unprefixed field names.
2. Add the Integration Code
Add the following JavaScript code to your website where the HubSpot form is present or add it to the variation JS section of an independent Deploy experience targeted to the form page
<!-- Start of Convert.com A/B Test Form Tracking Code -->
<script>
(function() {
'use strict';
var DEBUG = false;
function log(message, data) {
if (!DEBUG) return;
if (data !== undefined) {
console.log('[Convert→HubSpot] ' + message, data);
} else {
console.log('[Convert→HubSpot] ' + message);
}
}
function getConvertData() {
if (!window.convert || !window.convert.currentData || !window.convert.currentData.experiences) {
log('Convert data not available yet');
return null;
}
var experiences = window.convert.currentData.experiences;
var experienceIds = [];
var variationNames = [];
Object.keys(experiences).forEach(function(experienceId) {
var experience = experiences[experienceId];
if (experience.variation) {
experienceIds.push(experienceId);
variationNames.push(experience.variation.name);
}
});
if (!experienceIds.length) {
log('No active experiences with variations found');
return null;
}
return {
experienceIds: experienceIds,
variationNames: variationNames
};
}
function findFieldName(formInstance, fieldName) {
if (!formInstance || typeof formInstance.getFormFieldValues !== 'function') {
return Promise.resolve(fieldName);
}
return formInstance.getFormFieldValues().then(function(fields) {
var match = fields.find(function(field) {
return field.name === fieldName || field.name.indexOf('/' + fieldName) > -1;
});
return match ? match.name : fieldName;
}).catch(function() {
return fieldName;
});
}
function populateHubSpotFormV4(formInstance, source) {
var data = getConvertData();
if (!data || !formInstance || typeof formInstance.setFieldValue !== 'function') {
return;
}
Promise.all([
findFieldName(formInstance, 'convert_experience_names'),
findFieldName(formInstance, 'convert_variation_names')
]).then(function(fieldNames) {
var experienceFieldName = fieldNames[0];
var variationFieldName = fieldNames[1];
formInstance.setFieldValue(experienceFieldName, data.experienceIds);
formInstance.setFieldValue(variationFieldName, data.variationNames);
log('Set HubSpot Forms V4 fields from ' + source, {
experienceFieldName: experienceFieldName,
variationFieldName: variationFieldName,
experienceIds: data.experienceIds,
variationNames: data.variationNames
});
});
}
function populateAllHubSpotFormsV4(source) {
if (!window.HubSpotFormsV4 || typeof window.HubSpotFormsV4.getForms !== 'function') {
log('HubSpotFormsV4 not available');
return;
}
var forms = window.HubSpotFormsV4.getForms();
forms.forEach(function(formInstance) {
populateHubSpotFormV4(formInstance, source);
});
}
function populateLegacyHubSpotForms(source) {
var data = getConvertData();
if (!data) {
return;
}
var forms = document.querySelectorAll('form.hs-form');
forms.forEach(function(form) {
var experienceField = form.querySelector('input[name="convert_experience_names"]');
var variationField = form.querySelector('input[name="convert_variation_names"]');
if (experienceField && variationField) {
experienceField.value = data.experienceIds.join(',');
variationField.value = data.variationNames.join(',');
log('Set legacy HubSpot form fields from ' + source);
}
});
}
window._conv_q = window._conv_q || [];
window._conv_q.push([function() {
populateAllHubSpotFormsV4('initial-check');
populateLegacyHubSpotForms('initial-check');
window.addEventListener('hs-form-event:on-ready', function(event) {
if (window.HubSpotFormsV4 && typeof window.HubSpotFormsV4.getFormFromEvent === 'function') {
populateHubSpotFormV4(
window.HubSpotFormsV4.getFormFromEvent(event),
'hs-form-event:on-ready'
);
}
});
window.addEventListener('hs-form-event:on-interaction:navigate', function(event) {
if (window.HubSpotFormsV4 && typeof window.HubSpotFormsV4.getFormFromEvent === 'function') {
populateHubSpotFormV4(
window.HubSpotFormsV4.getFormFromEvent(event),
'hs-form-event:on-interaction:navigate'
);
}
});
window.addEventListener('message', function(event) {
if (
event.data &&
event.data.type === 'hsFormCallback' &&
event.data.eventName === 'onFormReady'
) {
populateLegacyHubSpotForms('legacy-onFormReady');
}
});
}]);
})();
</script>
<!-- End of Convert.com A/B Test Form Tracking Code -->
3. How It Works
- The code uses Convert.com's queue system (_conv_q) to ensure all experience data is loaded before execution.
-
For newer HubSpot forms, it listens for HubSpot’s
hs-form-event:on-readyevent and useswindow.HubSpotFormsV4.getFormFromEvent(event)to access the form instance.For multi-step HubSpot forms, it also listens for
hs-form-event:on-interaction:navigateso hidden fields can be repopulated when the visitor moves between steps. - When triggered, it:
- Accesses theconvert.currentData.experiencesobject to get active experiences
- Creates arrays to store multiple experience IDs and variation names
- Finds the HubSpot field names, including newer prefixed names such as
0-1/convert_experience_names - Uses HubSpot’s Forms V4
setFieldValue()method for newer HubSpot forms - Passes values as arrays for newer HubSpot hidden fields
- Keeps a legacy fallback for older HubSpot forms that still use
form.hs-formand unprefixed field names
4. Accessing Experience Data
The code uses Convert.com's updated JavaScript object structure:
convert.currentData.experiences[experienceId] = {
firstTime: true,
variation: {
id: "1000244142",
name: "Original Page",
key: "1000244142-original-page",
status: "running",
changes: [
{
name: "Original Page"
}
]
}
}
5. Testing the Integration
To verify the integration:
- Open your website with both Convert.com experiences and HubSpot form
- Open browser developer tools
- Submit the form
- Check HubSpot submission data to confirm the Convert experience IDs and variation names are being captured in the hidden fields
- For newer HubSpot forms, verify that the submitted hidden field values are present even when the visible DOM input value does not appear to change manually
Best Practices
- Add error handling for cases when Convert.com data isn't available
- Consider adding timestamp data to track when the experiences were active
- Do not hardcode a HubSpot portal ID unless your implementation specifically requires it
- Avoid relying only on direct DOM writes such as
input.valuefor newer HubSpot forms, because React-rendered forms may overwrite those values - Keep
DEBUGset tofalsein production - Use the optional legacy fallback only when you still need to support older HubSpot forms
Troubleshooting
If experience data isn't appearing in form submissions:
- Verify Convert.com experiences are running
- Check browser console for JavaScript errors
- Confirm hidden fields are properly created in HubSpot
- Confirm whether the form is using HubSpot’s newer Forms V4 renderer
- Confirm the hidden field names in HubSpot, including possible prefixes such as
0-1/ - Confirm
window.HubSpotFormsV4is available on the page for newer HubSpot forms - Confirm the
hs-form-event:on-readyevent fires when the form loads - For multi-step forms, test each step and confirm the hidden fields are still populated before final submission
- If the form is an older HubSpot form, confirm it still uses
form.hs-formand the legacyhsFormCallbackevents