The snippet fills hidden inputs that live on your page. A form embedded in an iframe (Typeform, Jotform, Google Forms and most "paste this embed code" builders) lives on the vendor's page, so the snippet cannot reach its fields. Those builders accept values another way: in the URL that loads the form. This guide shows how to hand the attribution over that way. The pattern is tested on every release (tests/e2e/fixtures/embed-form.html); the vendor side is documented from their own help pages, so check it against your form before relying on it.
The pattern
- Create the hidden fields in the builder, named like the TraceLead fields you want (
channel,source,medium,utm_source,utm_campaign,gclid,landing_page,first_touch_at, and so on). - Do not paste the vendor's embed code as-is. Mount the form from a small script that asks the snippet for the stored touch and adds it to the embed URL.
- If consent has not been granted yet, mount the form anyway after a short wait, without attribution. A form that never appears is worse than a lead without a source.
<div id="enquiry"></div>
<script>
window.tracelead = window.tracelead || function () { (window.tracelead.q = window.tracelead.q || []).push(arguments); };
(function () {
var KEYS = ['channel', 'source', 'medium', 'utm_source', 'utm_medium', 'utm_campaign', 'gclid', 'landing_page', 'first_touch_at'];
var mounted = false;
function attribution(fields) {
var params = new URLSearchParams();
KEYS.forEach(function (key) {
if (fields && fields[key]) { params.set(key, fields[key]); }
});
return params;
}
function mount(fields) {
if (mounted) { return; }
mounted = true;
var params = attribution(fields).toString();
var iframe = document.createElement('iframe');
iframe.src = 'https://form.jotform.com/FORM_ID' + (params ? '?' + params : '');
iframe.title = 'Enquiry form';
iframe.style.cssText = 'width:100%;min-height:600px;border:0';
document.getElementById('enquiry').appendChild(iframe);
}
// Runs at once when a touch is already stored, or as soon as consent is granted on this page.
window.tracelead('touch', function (fields) { mount(fields); });
// No consent after 1.5 s: show the form without attribution.
setTimeout(function () { mount(null); }, 1500);
})();
</script>
Only the attribution values travel in that URL: channel, campaign names, click ids and the landing path. No name, email or form content is involved, and nothing is sent anywhere before consent, because tracelead('touch', …) only fires once a touch exists.
Jotform
Jotform prefills a field from a query parameter whose name is the field's unique name (Field properties → Advanced → Field details → Unique name). Add a Short Text field per attribution value, set its unique name to channel, utm_source and so on, hide it with the field's Hidden property, and load the form as above:
https://form.jotform.com/FORM_ID?channel=paid_search&utm_source=google&gclid=…
Typeform
Typeform uses hidden fields declared in the builder (Settings → Hidden fields). They are passed in the URL fragment of a standalone form link, or through the embed library's hidden option. With the embed library loaded (<script src="//embed.typeform.com/next/embed.js"></script>), replace the mount function above with:
function mount(fields) {
if (mounted) { return; }
mounted = true;
var hidden = {};
KEYS.forEach(function (key) {
if (fields && fields[key]) { hidden[key] = fields[key]; }
});
window.tf.createWidget('FORM_ID', { container: document.getElementById('enquiry'), hidden: hidden });
}
For a plain link instead of an embed: https://form.typeform.com/to/FORM_ID#channel=paid_search&utm_source=google.
Google Forms
A prefilled link (⋮ → Get pre-filled link) maps each question to an entry.<id> parameter. Use those ids as the keys instead of the TraceLead names and load the form URL the same way. Google Forms has no hidden question type, so the prefilled answers are visible to the respondent and can be edited: make those questions optional and say in their description what they are for.
Builders that render inline
Webflow, Elementor, Contact Form 7, WPForms, Gravity Forms, Unbounce, Leadpages and HubSpot's raw HTML forms render their inputs on your page, so use hidden fields and the normal install instead. See Installing the snippet, WordPress, Webflow, Landing page builders and HubSpot forms; the integrations ledger lists what is tested.
Limits
- Once the embed has loaded, its values are fixed. If consent arrives after the fallback has mounted the form, that page view's form carries no attribution; the next page does.
- The vendor stores whatever you pass, under its own terms. Pass only the attribution values you need.
- Pop-up and slider embeds work the same way as long as they are created from the script after the touch is known.