feat(ntp): omnibar picker impression + upsell source telemetry (FE) - #2862
feat(ntp): omnibar picker impression + upsell source telemetry (FE)#2862moon0326 wants to merge 4 commits into
Conversation
… upsell Consume the new omnibar_getConfig shape: per-model description/isBeta/ accessTier and a structured reasoningEfforts list with availability status. Render model descriptions and Beta/Plus/Pro/Internal badges, show a gold "Try for Free" pill on gated reasoning efforts and subscriber-exclusive model sections, and wire a new omnibar_showSubscriptionUpsell notify (mockable until native lands).
…options
Introduce a per-item `upsell` field ("subscribe" | "upgrade") on models and
reasoning-effort options. Gated items now render "Try for free" or "Upgrade"
and route to the matching native notification (omnibar_showSubscriptionUpsell
vs the new omnibar_showSubscriptionUpgrade). Upgrade-gated reasoning options
are grayed out to signal they aren't selectable at the current tier, while the
badge stays legible.
The mock transport demos both flows (claude-haiku-4-5 => subscribe, Mistral
Small 3 => upgrade) and alerts as a placeholder until native ships the flows.
Gated reasoning options are role="option" and intentionally clickable to open an upsell, so aria-disabled would be wrong. Instead, stop DropdownItem from blanket-hiding its trailing slot so the "Try for free"/"Upgrade" badge is part of the option's accessible name. AttachMenu now marks its own decorative chevron aria-hidden.
Build Branch
Static preview entry points
QR codes (mobile preview)
Integration commandsnpm (Android / Extension): Swift Package Manager (Apple): .package(url: "https://github.com/duckduckgo/content-scope-scripts.git", branch: "pr-releases/moon0326/ntp-omnibar-picker-impression-pixels")git submodule (Windows): git -C submodules/content-scope-scripts fetch origin pr-releases/moon0326/ntp-omnibar-picker-impression-pixels
git -C submodules/content-scope-scripts checkout origin/pr-releases/moon0326/ntp-omnibar-picker-impression-pixelsPin to exact commitnpm (Android / Extension): Swift Package Manager (Apple): .package(url: "https://github.com/duckduckgo/content-scope-scripts.git", revision: "89df7f6fdd0747eec65ff89569b1ecb478625df8")git submodule (Windows): git -C submodules/content-scope-scripts fetch origin pr-releases/moon0326/ntp-omnibar-picker-impression-pixels
git -C submodules/content-scope-scripts checkout 89df7f6fdd0747eec65ff89569b1ecb478625df8 |
[Beta] Generated file diffTime updated: Mon, 13 Jul 2026 23:44:41 GMT AppleFile has changed IntegrationFile has changed WindowsFile has changed |
|
This PR requires a manual review and approval from a member of one of the following teams:
|
Add omnibar_modelPickerShown / omnibar_reasoningPickerShown notifications,
fired once when the user opens the model selector or reasoning-effort
picker (picker impressions). Add a `source` param ("model" | "reasoning")
to the existing omnibar_showSubscriptionUpsell / omnibar_showSubscriptionUpgrade
notifications so native can attribute the subscription funnel origin.
Frontend only. Native (macOS/Windows) must add the corresponding handlers
before this is shipped, so this lands on a dedicated branch pending native
coordination.
744b568 to
8aafda2
Compare
There was a problem hiding this comment.
Web Compatibility & Security Assessment — PR #2862
Commit: 8aafda23 · Scope: special-pages/pages/new-tab/ only (15 files, +284/−33). No injected/ changes.
Web Compatibility Assessment
| File | Lines | Severity | Finding |
|---|---|---|---|
| (all) | — | info | Changes are confined to the first-party NTP omnibar special page. This code does not inject into third-party web pages, so API-surface fidelity, prototype-chain, and third-party script compatibility concerns from the injected review rubric do not apply. |
useDropdown.js |
75–82 | info | onOpen fires synchronously on each closed→open transition inside open(), giving correct once-per-open impression semantics. Event listeners are cleaned up on close (pre-existing pattern). |
ModelSelectorTool.js |
18–26 | info | hasUpsell mirrors ModelDropdown's isUpsellSection logic (fully-gated section), so the upsell impression aligns with visible UI. |
ReasoningPickerTool.js |
56–69 | info | hasUpsell checks status === 'unavailable', matching per-option upsell badge visibility. |
No web-compatibility warnings or errors identified.
Security Assessment
| File | Lines | Severity | Finding |
|---|---|---|---|
omnibar-picker-source.json |
1–7 | info | source / picker values are enum-constrained ("model" | "reasoning"). No user-controlled or page-derived strings enter messaging payloads. |
omnibar_showSubscriptionUpsell.notify.json |
1–13 | info | Schema enforces additionalProperties: false and required source. No nativeData leakage risk. |
omnibar_showSubscriptionUpgrade.notify.json |
1–13 | info | Same hardening as upsell schema above. |
omnibar.service.js |
223–264 | info | Telemetry and upsell notifies use explicit, typed literals — no object spreading from untrusted input. |
omnibar_showSubscriptionUpsell.notify.json |
6–7 | warning | Breaking schema change: source is now required (previously {}). Native handlers on all platforms must accept and map source before this ships; older native builds will receive a payload shape they may not expect. This is a coordination risk, not a page-exploitation vector. |
No critical security findings.
Risk Level
Low Risk — Special-pages-only telemetry plumbing with enum-constrained messaging payloads, no injected runtime changes, no API overrides, and no hostile-page attack surface.
Recommendations
- (warning) Confirm native platform PRs land alongside this FE change to handle the now-required
sourcefield onomnibar_showSubscriptionUpsell/omnibar_showSubscriptionUpgrade. - (info) Integration tests cover picker/upsell impressions and source attribution for both model and reasoning pickers — 6/6 targeted tests pass.
- (info)
omnibar.mddocumentation for the new telemetry events andsourceparameter is thorough and matches implementation.
Sent by Cursor Automation: Web compat and sec
55bbe6d to
5259acf
Compare


Add omnibar_modelPickerShown / omnibar_reasoningPickerShown notifications, fired once when the user opens the model selector or reasoning-effort picker (picker impressions). Add a
sourceparam ("model" | "reasoning") to the existing omnibar_showSubscriptionUpsell / omnibar_showSubscriptionUpgrade notifications so native can attribute the subscription funnel origin.Frontend only. Native (macOS/Windows) must add the corresponding handlers before this is shipped, so this lands on a dedicated branch pending native coordination.
Asana Task/Github Issue:
Description
Testing Steps
Checklist
Please tick all that apply: