Why this listener exists
Most Jotform setups count a lead with a page-view trigger on the thank-you URL. That trigger also fires on every reload, every back-button visit and every shared link.
The Jotform recipes online wait for Jotform’s submission-completed message. On a live site, a real submission from a form that redirects only posted setHeight and formSettled, then the page navigated away. No completion message ever arrived. If your form shows Jotform’s built-in Thank You screen the message fires. If it redirects, those listeners stay silent.
How it detects a submission
| ec_detection_method | When it fires | Strength |
|---|---|---|
submit_referrer |
Redirect mode. The next page load has a referrer on submit.jotform.com (also .eu, Enterprise /submit paths or your jotformSubmitHosts) and navigation type navigate. Only Jotform’s server sends visitors there, and only after it accepts the entry. Never fires on refresh, back or a direct visit |
Strong, verified live |
postmessage |
Jotform’s built-in Thank You screen posts submission-completed from a registered Jotform iframe |
Strong |
iframe_reload |
The iframe navigated after the visitor focused into it. Ignored when the frame is hidden or the page rewrote its src. 1.5 s grace | Inferred |
stored_recall |
Redirect where the referrer was stripped. Needs a marker under 15 s old, written while focus was inside the frame | Inferred |
pagehide |
Source-code embeds: the page unloaded inside the submit window with no validation error showing | Inferred |
Set strictSuccess: true to drop the inferred methods and keep only the strong ones.
Iframe embeds vs source-code embeds
- Iframe, JS or lightbox embed: the fields are cross-origin, so you get the success event and attribution, but no PII.
- Source-code embed (
form.jotform-formon your page): full field capture. Email, phone (E.164), first and last name (split from Jotform’s full name field) and address go to theec_*keys for Enhanced Conversions and advanced matching. A validation failure pushesjotform_form_failedwithvalidation_message.
If you need Enhanced Conversions, switch the form to Jotform’s Embed, Source Code option.
Install it in Google Tag Manager
- Download the GTM tag above, or copy
dist/uft-jotform-standalone-v3.3.0-jotform.1.htmlfrom GitHub. - Create a Custom HTML tag, paste it in, trigger it on All Pages and set the firing option to Once per page. The tag must also run on the page the form redirects to.
- Create a Custom Event trigger with the regex
^jotform_form_success$, or^jotform_form_(success|failed)$to include failures. - Create Data Layer Variables for the keys you need:
ec_email,ec_phone,ec_first_name,ec_last_name,form_id,ec_event_id,ec_detection_method. - Retire any thank-you page-view conversion so leads are not counted twice.
Configuration
| Key | Default | Notes |
|---|---|---|
debug |
false |
Console logs. window._ecFormTrackers.jotform.status() works either way |
hashPii |
false |
Emits normalized plaintext so each platform tag can hash its own way. true adds ec_email_sha256 and ec_phone_sha256 |
rawFields |
false |
Leaves ec_raw_fields out of the payload |
defaultCountryCode |
'1' |
Phone E.164 fallback. A country field on the form takes priority |
countryCodeField |
'' |
Exact field name that holds an ISO2 or dial code |
strictSuccess |
false |
true keeps only submit_referrer and postmessage |
jotformSubmitHosts |
none | e.g. ['forms.acme.com'] for Enterprise custom submit domains |
jotformReloadGraceMs |
1500 |
Grace period for iframe_reload |
The tag also respects Google Consent Mode v2, OneTrust and Cookiebot, removes PII when PII consent is denied, attaches first and last touch attribution, and suppresses duplicate successes within 5 minutes.
Running alongside other trackers
The standalone is namespaced (_ec_jotform_tracker_loaded, ec_jotform_form_data, ec_jotform_form_queue, ec_jotform_pending), so it can sit next to the other listeners in this library. Attribution (ec_attribution) and the dedupe ledger (ec_form_dedupe) are shared on purpose. The redirect marker holds no PII.
Test it before you publish
- Submit a real entry on a redirecting form. Expect one
jotform_form_successon the thank-you page withec_detection_method: submit_referrer. - Refresh the thank-you page and visit it directly. Expect nothing.
- On a source-code embed, submit with a required field empty. Expect
jotform_form_failed. - Run
window._ecFormTrackers.jotform.status()to see consent, attached forms and the last event.
Gotchas found in the field
- WP Rocket “Delay JavaScript execution” can hold GTM until the visitor interacts. A visitor who lands on the thank-you page and does not scroll never loads GTM, so every conversion tag on that page misses. Exclude
googletagmanager.comfrom the delay list. - The same form embedded twice on one page (for example a popup plus an inline form) reports the same form ID twice. Clone the form in Jotform if you need separate reporting.
- Validation errors inside an iframe post nothing cross-origin, so failure events only exist for source-code embeds.
Tests
The repository ships 88 jsdom checks in four groups: iframe embeds, redirect destination pages, source-code embeds (real Jotform markup with client details scrubbed) and the deploy build itself. Run npm install then npm test.
Changelog
- 3.3.0-jotform.1: first public release. Referrer-based redirect detection, iframe and source-code embed support, failure events for source embeds, strict mode, Enterprise submit hosts and the
status()debug API.