Add duck.ai entry point pixel - #9550
Conversation
29001d4 to
0e965ef
Compare
e086b0f to
66dcdb8
Compare
7f575d2 to
7f795b8
Compare
77a8ba7 to
ca18c92
Compare
7f795b8 to
9ba46aa
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit ca18c92. Configure here.
9ba46aa to
94d6e20
Compare
ca18c92 to
20a76d0
Compare
malmstein
left a comment
There was a problem hiding this comment.
did not install or smoke-test the APK. nice work on the coverage, the truth-table test and the one that pins every enum to its wire value are the right tests to have written, and the contextual double-report case being tested explicitly is good to see. main things i'd like answered before merge are the has_prompt meaning on contextual expand and the narrowing of the existing direct-navigation pixel, since both change what analysts see. the rest is non-blocking: entry reporting would sit better in RealDuckChatPixels alongside fireCountAndDaily, and the prompt check now exists in three places with the url contract hardcoded in two of them.
| DuckChatPixelParameters.OPENS_NEW_TAB to opensNewTab.toString(), | ||
| DuckChatPixelParameters.HAS_PROMPT to hasPrompt.toString(), | ||
| ) | ||
| pixel.fire(DuckChatPixelName.DUCK_CHAT_ENTRY_POINT_COUNT, parameters = parameters) |
There was a problem hiding this comment.
suggestion: every other duck chat pixel goes through DuckChatPixels, and fireCountAndDaily there already fires this pair on io. can we move entry reporting into RealDuckChatPixels instead of firing both from here on whatever thread tapped?
There was a problem hiding this comment.
Good point, will do. Only caveat is that I’ll have to inject DuckChatPixels as Lazy to prevent cycles.
| } | ||
| } | ||
|
|
||
| private fun DuckChatEntryPoint.toPixelValue(): String = when (this) { |
There was a problem hiding this comment.
nit: RealDuckChatTest already asserts source equals entryPoint.name.lowercase() for every entry, so this when is 22 lines saying the same thing. can we just use name.lowercase()?
There was a problem hiding this comment.
Nice catch, didn’t think about it. Will update
20a76d0 to
b94db4e
Compare
malmstein
left a comment
There was a problem hiding this comment.
lgtm, the three changes landed as discussed. two things left: toggle_visible on omnibar_shown drops the inputContext == BROWSER half of the canonical predicate so it reads true on duck.ai tabs, and the direct_navigation description still doesn't mention it's USER submissions only. static only, didn't install the apk.


Task/Issue URL: https://app.asana.com/1/137249556945/project/1212810093780571/task/1217295011063283?focus=true
Tech Design URL (if applicable): https://app.asana.com/1/137249556945/project/481882893211075/task/1217382844057496?focus=true
API Proposals URL(s) (if applicable): https://app.asana.com/1/137249556945/project/1212810093780571/task/1217532302535418?focus=true
Description
Adds Duck.ai entry-point count/daily pixels with five bounded parameters:
source,duck_ai_enabled,input_screen_enabled,opens_new_tab, andhas_prompt.Every public
DuckChat.open*method requires aDuckChatEntryPointand reports automatically. Navigation paths that bypass those methods callDuckChat.reportDuckChatEntrybeside the navigation. Restored tabs and selecting an existing tab are passive and do not report.Steps to test this PR
Install the internal build; filter Logcat for
Pixel sent:andm_aichat_entry_point. Expect a count event for each action and at most one daily event per day. For every event, verify exactlysource,duck_ai_enabled,input_screen_enabled,opens_new_tab, andhas_prompt.address_bar_promptentry test, submit.Loaded page: repeat after opening
https://example.com/.falseLoaded page:
truetrueaddress_bar_iconfalsefalsesuggestion_ask_aientry test, and tap Ask Duck.ai. Repeat from an NTP and fromhttps://example.com/.falseLoaded page:
truetruebrowsing_menu_ntptruefalsebrowsing_menu_webpagehttps://example.com/, then ⋮ > New Chat.truefalsetab_switchertruefalsechat_history_new_chatuseNativeStorageChatDataenabled, open ⋮ > Chats, then tap toolbar New; if history is empty, tap Open Duck.ai.truefalsechat_history_open_chattrueAddress-bar row: NTP
false, loaded pagetruefalsevoicetruefalseonboardingtruetruedirect_urlhttps://duck.ai/.2. Type and submit
https://duck.ai/chat?duckai=5&q=Hello%20from%20entry%20test&prompt=1.3. Open
https://duckduckgo.com/duckduckgo-help-pages/duckai/and tap Navigate there directly.false;custom-tab handoff:
truefalseAuto-submit URL:
trueserphttps://duckduckgo.com/?q=duck.ai, then tap the result that openshttps://duck.ai/.falsefor normal same-tab navigationfalseicon_shortcuttruefalsecontextual_chatcontextualModeKillSwitchplus completed standalone migration orcontextualMode; open contextual mode from a loaded page, then use the contextual FE handoff that emitsopenAIChatinto full-screen Duck.ai.truefalsewidget_quick_actionstruefalsewidget_favoritehttps://duck.ai/as a Favorite, add the Search and Favorites widget, then tap that Duck.ai favorite.truefalsesystem_searchentry test, then tap the Duck.ai icon inside System Search.truetruedigital_assistanttruefalsedeep_link_otheradb shell am start -W -a android.intent.action.VIEW -d 'https://duck.ai/' -p '<applicationId>'.truefalsepaid_settingstruefalseaddress_bar_shortcut_chipfalsewith the selected NTP;trueonly in the no-selected-tab fallbackfalseaddress_bar_editing_statetruefalseUI changes
No UI changes
Note
Medium Risk
Public DuckChat open APIs now require an entry point, so every Duck.ai launch path is retouched. Risk is telemetry/API-contract, not auth or data handling.
Overview
Adds
m_aichat_entry_pointcount/daily pixels so every user-initiated Duck.ai open reportssource,duck_ai_enabled,input_screen_enabled,opens_new_tab, andhas_prompt.Public
DuckChat.open*methods now take aDuckChatEntryPointand fire automatically. Paths that navigate without those methods (typed URLs, SERP/in-page links, widgets, shortcuts, onboarding, NTP chip, tab switcher, menus) callreportDuckChatEntrynext to the navigation. Restored/selected existing tabs stay silent.Also converts direct-navigation
duck_ai_enabledto a boolean, addsinput_screen_enabledthere, and derives omnibartoggle_visiblefrom input-mode capability instead of toggle position.Reviewed by Cursor Bugbot for commit dad76c9. Bugbot is set up for automated code reviews on this repo. Configure here.