Skip to content

fix(rokt): read form email only once committed and unfocused, and require two-letter TLD - #1778

Open
crisryantan wants to merge 8 commits into
v3-developmentfrom
fix/read-form-email-on-blur-and-require-two-letter-tld
Open

crisryantan wants to merge 8 commits into
v3-developmentfrom
fix/read-form-email-on-blur-and-require-two-letter-tld

Conversation

@crisryantan

@crisryantan crisryantan commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

Why

When pre-selection scans a form while a shopper is still typing an email address, keystroke input events can capture a partial address that differs from the completed email sent on the confirmation page, causing a cache key mismatch on the email attribute. Reading the field only after a trusted change event when the field is no longer focused (or on a checkout commit intent), and requiring a multi-character top-level domain, avoids capturing partial emails mid-typing.

Programme

Standalone change, no programme.

What changes

  • recordShopperInput records an email candidate in shopperInputs on a trusted change event, removes it if a later input or other event fires before the next change, and removes an uncommitted candidate from touchedInputs on blur. A blur never marks a field finished, since a script can set the value silently first; only a trusted change does, and the listener still reads no value.
  • Rokt-Kit listens for capture blur events alongside input and change only so a blur drops a field no change committed. A blur never flushes pending dispatches, since a script can set the value silently before it; a field committed while focused waits for the next trigger or checkout commit intent.
  • isEmailInput skips document.activeElement, and scanFormEmails skips document.activeElement on background reads while reading a focused committed field on a checkout intent signal, counting an unsettled touched field toward the two-email rule when it is type="email", has autocomplete="email", is mid-edit after a committed change, or holds @ (testing a text field's value only for @), and reporting uncommitted_fill in describeMissingEmail.
  • EMAIL_PATTERN requires a top-level domain of two or more ASCII letters, a punycode xn-- label, or two or more non-whitespace, non-separator Unicode characters.
  • Unit and integration tests cover two-letter, punycode, internationalized, single-character, whitespace, and numeric TLDs, keystroke-only input events, re-editing a completed field and blurring without a change (including after a silent script write), focused inputs never flushing on blur (including after a silent script write) and firing on commit intent, unsettled second fields in the ambiguity check, and uncommitted_fill.

Linked work

  • Standalone fix in the Rokt kit pre-selection form email reader.

Rollout

No flag. Rollback is a revert.

Risks

  • A form email field is read on background scans only after change fires and the field is not focused, or while focused when checkout commit intent fires. A trusted change on an unfocused email field flushes pending pre-selection dispatches; a blur never does.

Who

Written by: an automated coding agent.
Checked: CI runs the kit's Vitest suite (mparticle-web-kit-tests) on this change. It was not run on the authoring machine.

Size

Hand-written: 4 files, 466 lines added and 71 removed.

@crisryantan
crisryantan requested a review from a team as a code owner November 7, 2026 04:09
@codecov

codecov Bot commented Nov 7, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.70130% with 1 line in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (v3-development@f39b38b). Learn more about missing BASE report.

Files with missing lines Patch % Lines
kits/rokt/src/preselection/preselection.ts 98.66% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@                Coverage Diff                @@
##             v3-development    #1778   +/-   ##
=================================================
  Coverage                  ?   64.20%           
=================================================
  Files                     ?       79           
  Lines                     ?    10722           
  Branches                  ?     3109           
=================================================
  Hits                      ?     6884           
  Misses                    ?     3514           
  Partials                  ?      324           
Flag Coverage Δ
core 54.51% <ø> (?)
rokt-kit 92.59% <98.70%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@mattbodle mattbodle left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated agent review; not an independent human approval.
Head 2ccf069.
A blur can flush a field value the change path would have ignored, and BrowserStack Beta Browsers Test is failing.

crisryantan and others added 2 commits November 7, 2026 00:36
… email field

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ield

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@mattbodle mattbodle left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated agent review; not an independent human approval.
Head 612e4ee.
Not verified: Safari event order. This is not an approval because a blur with event.isTrusted true can still flush a script-set value.

… a blur

A trusted blur can follow a script that set the field silently, so restoring a
committed field on blur could read the script's value. The field now waits for
the next trusted change, without the listener reading any value.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@mattbodle mattbodle left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated agent review; not an independent human approval.
Head e3bfb36. Moving focus after a script sets the value fires a trusted blur and no change, in Chrome, Firefox, and WebKit, and that blur still sends that value. Not an approval.
Kit Tests: Amplitude 8 is failing. Safari was not driven. The full kit suite was not run locally.

@mattbodle mattbodle left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated agent review; not an independent human approval.
Head e3bfb36.
A trusted blur after a committed email sends a value a script wrote with no input event. The previous code does not flush on that blur.

Comment thread kits/rokt/src/Rokt-Kit.ts Resolved
crisryantan and others added 2 commits November 7, 2026 08:12
…commit

A blur on a field committed before it had focus flushed pending pre-selection
dispatches too, reading a value a script may have set silently since. Only the
blur that ends a change heard while the field had focus retries now, once.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A script could keep the blur that ended a focused commit and dispatch it again
after rewriting the field. A replayed event is untrusted, so it never retries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@mattbodle mattbodle left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated agent review; not an independent human approval.
Head 028da73.
A change while a field has focus, then a script sets another value, then blur, still sends that value. The previous code does not flush on that blur. BrowserStack Test fails an identity custom-device assertion on Firefox 51. Safari was not driven.

crisryantan and others added 2 commits November 7, 2026 19:19
Any blur can follow a script that set the field silently, and the listener
reads no values to tell the two apart. A field committed while focused now
waits for the next trigger or checkout commit intent, as before blur was heard.
Blur still drops a field no change committed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@crisryantan crisryantan changed the title fix(rokt): read form email on blur and require two-letter TLD fix(rokt): read form email only once committed and unfocused, and require two-letter TLD Nov 8, 2026

@mattbodle mattbodle left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated agent review; not an independent human approval.
Head c10bc8f.
A focused commit does not flush, but the change fired when focus later leaves still sends a value written after that commit. The base sends the focused commit. Not an approval.

Comment thread kits/rokt/src/Rokt-Kit.ts
// Notes which fields the shopper types into or autofills, reading no value, and retries on a committed
// change. The form's own gates run before the changed field's value is read.
// change. A blur only drops a field no change committed. The form's own gates run before the changed
// field's value is read.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A change that fires after focus leaves still flushes the field's current value. A commit while the field is focused does not. A value written between them is what this change sends, where the base sends the focused commit.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants