Skip to content

fix(autocapture): prevent scroll gestures from triggering dead clicks - #1941

Merged
Mercy811 merged 1 commit into
mainfrom
codex/sdk-200-dead-click-scroll-flick
Aug 24, 2026
Merged

fix(autocapture): prevent scroll gestures from triggering dead clicks#1941
Mercy811 merged 1 commit into
mainfrom
codex/sdk-200-dead-click-scroll-flick

Conversation

@Mercy811

@Mercy811 Mercy811 commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Summary

  • use completed native click events as dead-click candidates so canceled touch scroll gestures are ignored
  • preserve pointerdown input for rage-click and error-click detection
  • add regression coverage for the detector event sources and a manual scroll-flick test page

Root cause

The shared click observable listened to pointerdown. On touch devices, beginning a scroll over an allowlisted element emitted a pointerdown even though the gesture never completed as a click. If the page did not navigate or mutate within the dead-click timeout, the SDK incorrectly reported a dead click.

Event-source history and rationale

Dead-click and rage-click tracking were originally introduced in #1146 using one shared native click observable. #1210 later changed that shared observable to pointerdown to improve rage-click capture on mobile. Rapid mobile taps can be consumed by browser scrolling, panning, or zoom gestures before a completed click is emitted, whereas pointerdown records each attempted press immediately. That makes pointerdown the appropriate signal for counting repeated rage interactions.

Because the observable was shared, the rage-click fix also moved dead-click detection to pointerdown, even though that was not the stated purpose of #1210. A dead click represents a completed activation that produced no response; a touch that begins a scroll is not a completed activation. This PR splits the streams so rage clicks keep the mobile behavior from #1210 while dead clicks return to their original native click boundary.

Error clicks continue to use pointerdown for a separate reason: the correlated browser error may occur in an early pointer handler before a native click is emitted. Other frustration signals retain their existing event sources.

Impact

Scroll flicks that begin over large interactive elements such as product-card links no longer produce dead-click false positives. Existing rage-click and error-click behavior remains unchanged.

Testing

  • pnpm --filter @amplitude/plugin-autocapture-browser build
  • pnpm --filter @amplitude/plugin-autocapture-browser exec jest --watchman=false --runInBand (24 suites, 418 tests)
  • pnpm --filter @amplitude/plugin-autocapture-browser lint
  • git diff --check

Linear

SDK-200: Need to be fixed: Dead Click false positives from scroll-flick touches


Note

Medium Risk
Changes frustration autocapture event sourcing for dead vs rage/error clicks; behavior is well-tested but affects analytics signal semantics on touch devices.

Overview
Dead-click detection now listens for completed native click events instead of sharing a single pointerdown stream, so touch scroll-flicks that start on links (e.g. product cards) no longer time out as dead clicks when no navigation or mutation occurs.

The frustration plugin wires two enriched observables: click for dead clicks and pointerdown for rage and error clicks, preserving prior mobile behavior for those signals. PointerDownObservable is added to ObservablesEnum and AllWindowObservables.

Regression tests cover scroll-gesture vs real dead click vs mutation cancellation and rage-from-pointerdown; unit tests mock the split streams. A manual scroll-flick test page was added under test-server/autocapture/.

Reviewed by Cursor Bugbot for commit b22f96d. Configure here.

@linear-code

linear-code Bot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

SDK-200

@Mercy811

Copy link
Copy Markdown
Contributor Author

bugbot run

@github-actions

Copy link
Copy Markdown

size-limit report 📦

Path Size
packages/analytics-browser/lib/scripts/amplitude-min.js.gz 61.58 KB (+0.07% 🔺)
packages/session-replay-browser/lib/scripts/session-replay-browser-min.js.gz 134.97 KB (0%)
packages/unified/lib/scripts/amplitude-min.umd.js.gz 215.63 KB (+0.02% 🔺)
@amplitude/element-selector (gzipped esm) 2.67 KB (0%)

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit b22f96d. Configure here.

@Mercy811
Mercy811 marked this pull request as ready for review August 19, 2026 22:31
@Mercy811
Mercy811 requested a review from a team as a code owner August 19, 2026 22:31

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b22f96d293

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/plugin-autocapture-browser/src/frustration-plugin.ts
Comment thread packages/plugin-autocapture-browser/src/frustration-plugin.ts
@Mercy811
Mercy811 merged commit 0807d88 into main Aug 24, 2026
19 checks passed
@Mercy811
Mercy811 deleted the codex/sdk-200-dead-click-scroll-flick branch August 24, 2026 19:18
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