WPForms hidden fields often receive UTM values from a mixture of query strings, cookies, browser storage, tag managers, and custom JavaScript. When the storage scope is undefined, a first-touch value may be overwritten by a later visit, tabs can leak campaign state into one another, consent withdrawal can leave stale identifiers behind, and the final form entry may disagree with analytics or the CRM.
Use this contract test for lead-generation sites that send WPForms entries to email, a CRM, Google Ads, Meta, analytics, or an internal attribution database.
Quick answer
List every attribution field and assign one approved source, storage location, write event, expiry, consent condition, and fallback. Test a first visit, a second campaign, two tabs, a direct return, consent denial, consent withdrawal, and a completed form. The hidden inputs, saved WPForms entry, CRM record, and analytics event should all follow the same first-touch and latest-touch policy.
What to check first
- Inventory each UTM, click ID, landing page, referrer, first-touch, latest-touch, and session field exposed to WPForms.
- Record whether the field lives in memory, sessionStorage, localStorage, a cookie, or server-side session data.
- Define exactly when each value may be created, preserved, replaced, expired, or purged after consent changes.
- Inspect the hidden inputs immediately before submit and compare them with the stored WPForms entry and destination record.
- Repeat the journey in two tabs, a private window, a returning visit, and a browser with storage disabled.
Diagnostic table
Use this table to connect the observed behavior to evidence and a verification step.
| Action | Evidence to collect | How to verify |
| Create the field-by-field storage contract before changing JavaScript. | Inventory each UTM, click ID, landing page, referrer, first-touch, latest-touch, and session field exposed to WPForms. | The same journey produces matching attribution in the hidden inputs, WPForms entry, CRM, and analytics destination. |
| Give each field one writer and one precedence order. | Record whether the field lives in memory, sessionStorage, localStorage, a cookie, or server-side session data. | Direct return visits do not erase an eligible first touch or invent a new campaign. |
| Apply consent gates and purge rules at storage and form-render time. | Define exactly when each value may be created, preserved, replaced, expired, or purged after consent changes. | Consent denial and withdrawal prevent disallowed identifiers from being stored or submitted. |
| Populate hidden fields from the approved normalized object immediately before submit. | Inspect the hidden inputs immediately before submit and compare them with the stored WPForms entry and destination record. | Storage failure leaves the form usable and records an observable attribution fallback. |
Why this usually happens
- Browser storage persists on different boundaries, so localStorage, sessionStorage, cookies, and in-memory variables do not share the same lifetime.
- Multiple scripts may write the same hidden input during page load, consent updates, form rendering, and submit callbacks.
- First-touch and latest-touch fields are often named clearly but lack an enforceable immutability rule.
Useful command or data shape
Adapt paths, IDs, and privacy handling to the site before running commands or storing data on production.
field,source,storage,write_event,expiry,consent
first_utm_source,query,localStorage,first_eligible_visit,90d,analytics
latest_utm_source,query,sessionStorage,eligible_pageview,session,analytics
gclid,query,cookie,eligible_landing,90d,ads
landing_page,location,memory,form_render,page,essential
Test scenarios to run
Run the same controlled fixture across these branches. Write down the expected result before testing so a surprising response is easy to identify.
| Scenario | Fixture | Expected result |
| First campaign | Fresh browser with utm_source=google | First and latest touch both record Google |
| Second campaign | Same browser later with utm_source=linkedin | First touch stays Google and latest touch becomes LinkedIn |
| Parallel tabs | Two campaign URLs opened before either submits | Each form follows the approved tab or session policy |
| Consent revoked | Stored identifiers exist before withdrawal | Disallowed values are purged and hidden fields stay empty |
Safe fix order
Use a sequence that makes each result easy to prove. Stop when new evidence changes the scope or owner of the problem.
- Create the field-by-field storage contract before changing JavaScript.
- Give each field one writer and one precedence order.
- Apply consent gates and purge rules at storage and form-render time.
- Populate hidden fields from the approved normalized object immediately before submit.
- Compare the WPForms entry, CRM record, and analytics payload for every journey fixture.
Decision rule
Approve the implementation only when first-touch values remain immutable, latest-touch values update on the approved event, parallel tabs follow the written policy, and consent withdrawal removes every disallowed stored and submitted value.
Production verification checklist
- The same journey produces matching attribution in the hidden inputs, WPForms entry, CRM, and analytics destination.
- Direct return visits do not erase an eligible first touch or invent a new campaign.
- Consent denial and withdrawal prevent disallowed identifiers from being stored or submitted.
- Storage failure leaves the form usable and records an observable attribution fallback.
Field notes
- Hash or redact browser storage values in shared screenshots when they contain click IDs or personal data.
- Treat a disabled-storage browser as a supported failure mode and document the fallback rather than forcing persistence.
- Keep first-touch and latest-touch fixtures separate so a passing latest-touch test cannot hide first-touch corruption.
Questions teams ask during testing
Can this be tested on staging?
Start on staging with production-like versions, cache, data shape, and integrations. Finish with one controlled production fixture when the result depends on real routing, provider, or edge behavior.
What evidence should be retained?
Keep the smallest useful set: stable IDs, UTC timestamps, sanitized request or log excerpts, expected result, actual result, version inventory, and the final verification.
When should the change be rolled back?
Roll back when a revenue, privacy, security, or publishing path fails and the cause cannot be isolated inside the approved maintenance window.
Mistakes to avoid
- Do not change several production layers at once. Preserve the failing evidence and isolate one variable per test.
- Do not use a successful status or screen message as the only proof. Verify the business outcome and the underlying record.
- Do not leave debug logging, broad credentials, test orders, or temporary exceptions active after the review.
- Do not close the incident without recording the fixture, timestamps, owner, result, and rollback point.
What to tell the client or owner
Give the owner the affected versions, exact fixture, stable IDs, UTC timeline, before and after evidence, decision, rollback point, unresolved risks, and next review date.
When HandL WP should help
Bring in help when this affects leads, checkout, search visibility, security, paid media reporting, or a client production site. HandL WP can trace the issue through WordPress, hosting, cache, tracking, and Search Console, then verify the workflow after the technical fix.
If this is active on a production site, audit WPForms attribution storage.
Related HandL WP guides
Use these related guides when the same issue touches tracking, security, checkout, or crawler visibility.
Test WPForms attribution when two campaign tabs race
Run the WPForms UTM tab-isolation and BroadcastChannel race test to define tab IDs, message versions, consent synchronization, stale-message rejection, pre-submit snapshots, and cross-system submission joins.
Test browser storage cleanup and the no-channel fallback
Inventory login, consent, UTM, cart, and form state with the WordPress Browser Extension storage privacy test, then verify tab ownership when coordination is missing with the WPForms BroadcastChannel fallback test.
Migrate returning browsers before reading hidden fields
Use the WPForms UTM storage schema returning-user migration to preserve approved first touch, consent, expiry, tab ownership, entry fields, and CRM evidence when browser records change shape.
Helpful references