7.4 KiB
7.4 KiB
iOS: Chat-Path Onboarding — Tracker Blocking Demo
Asana: Ship Review task
Branch stack:demo-tracker-blocking-onboarding→ui-polish→chat-path-dialog-polish→sr-feedback→uti-flow
Due: 2026-05-15
Overview
A/B experiment adding a tracker-blocking demo step to onboarding for users who pick Duck.ai (chat-path). After the Fire Onboarding step, users see:
- "Try visiting a site!" dialog (address bar + toolbar hidden)
- Trackers-blocked dialog after a site loads
- "You've got this!" EOJ completion dialog
- Subscription upsell ("Oh, before I forget…")
Cohorts: Treatment A (address bar top) · Treatment B (address bar bottom) · Control (no change)
Audience: US only · iPhone only · Users who chose Duck.ai in onboarding, in A or B cohort
PR Stack
| PR | Branch | Status |
|---|---|---|
| #4544 | demo-tracker-blocking-onboarding |
Open — needs fixes |
| #4591 | demo-tracker-blocking-onboarding-ui-polish |
Approved — needs rebase |
| #4664 | demo-tracker-blocking-onboarding-chat-path-dialog-polish |
Open — needs fix |
| #4668 | demo-tracker-blocking-onboarding-uti-flow |
Open — needs fix |
| #4855 | demo-tracker-blocking-onboarding-sr-feedback |
Open — needs fixes |
Required Changes (not yet done)
PR #4544 — main chat-path branch
- Danger CI: Replace
@UserDefaultsWrapper(key: .daxChatPathVisitSiteSeen)withKeyedStoringprotocol pattern — new@UserDefaultsWrapperdefinitions are blocked by Danger rule. - Mock refactor (alessandroboron):
MockDaxDialogsSettings.chatPathPhaseshould exposevar _chatPathPhase: DaxDialogs.ChatPathPhase = .visitSitefor direct test control, not replicate real computed logic. - Sync restore exclusion: Exclude users who selected "Restore My Stuff" (sync restore) in
OnboardingIntroViewModel— Dax dialogs are disabled for those users, breaking the flow. - Pixels: Coordinate with rachelmcr (PR #4687) — may be able to use
variantparameter on existing pixels instead of adding new chat-path-specific pixel events.
PR #4664 — chat-path dialog polish
- Title scope (alessandroboron):
RebrandedNewTabDaxDialogFactorytitle change ("Next, try visiting a site!") must only apply to chat-path flow, not all onboarding flows.
PR #4668 — UTI (Unified Toggle Input) onboarding flow fixes
Fixes to make the chat-path onboarding dialogs work correctly when the Unified Toggle Input is active:
- Dialog position: anchor to
coordinator.viewController.view.bottomAnchor(UTI bar bottom), embed inunifiedInputContentContainer. - Dialog not dismissed on navigation:
viewWillDisappearremoves hosting controller parented toMainViewController. - UTI bar staying active after URL submission:
preserveOmnibarSessionnow checks!tab.isLoading. - "You've got this" completion dialog path in UTI mode:
showDuckAIOnboardingCompletionDialogInUTI. - UTI bar staying active after completion dismiss: call
dismissUnifiedToggleInputToOmnibardirectly. - Stale browsing-dialog flags:
setAsChatFirstPathnow resets all browsing-dialog flags to preventchatPathPhasejumping to.trackerToEOJfrom stale state. - Hardcoded cohort override (aataraxiaa):
FeatureFlag.swifthas a hardcoded test override — must revert before merge.
PR #4591 — ui-polish
- Approved. Rebase on current base.
PR #4855 — sr-feedback
- Hide toolbar + address bar: During visit-site step, hide both toolbar and address bar via
chromeDelegate?.setBarsHidden(true/false)— not just lock controls. Costas + Alessandro preference. Simplifies the code too. - Use delegate:
NewTabPageViewControllershould access the parent viaNewTabPageControllerDelegateinstead of(parent as? MainViewController)?cast. - Loading guard: Move
currentTab?.isLoading != truecheck into theifcondition, not a standaloneguard(avoids orphaned reference and blank NTP on early exit). - Revert Search Experience screen copy:
searchAndDuckAIOptionwas incorrectly changed to"Toggle between\nSearch and Ask AI". Must revert to"Toggle between\nSearch and Duck.ai"— the "Ask AI" rename is only for the DuckAIQuery experiment toggle (DuckAIQueryExperiment.toggleAILabel).
Privacy Config / Experiment Setup (TBD before shipping)
- Rename experiment in privacy config — create new experiment name, disable old one.
- Set
"targets": [{ "localeLanguage": "en", "localeCountry": "US" }]in the experiment payload. - Inform Pete in O-N Live Onboarding Experiment Details once experiment name is confirmed.
Resolved / Dismissed
- GJ6c ✅ — No longer required. Address bar hidden for visit-site step (GJ3), so user can't trigger a search at that point. Costas confirmed a search after the trackers-blocked dialog is acceptable.
- GJ3 ✅ — Hide address bar + toolbar for "Try visiting a site" step (chat-path only).
- GJ2 ✅ — X button removed from chat-path dialogs (PR #4664).
- GJ4 ✅ — Copy updated to "Next, try visiting a site!" after AI.
- GJ8 ✅ — "Duck.ai" → "Ask.ai" in DuckAIQuery toggle (onboarding only, not standard toggle).
DuckAIQueryExperiment.toggleAILabel = "Ask.ai". - "Try fire tabs" flash ✅ — Suppressed via
isStillOnboarding()inDaxDialogsfor chat-path users. - GJ7 (search-only path breakage) ✅ — Returning users guarded from experiment enrollment.
Key Files
| File | Purpose |
|---|---|
iOS/DuckDuckGo/DaxDialogs.swift |
Core onboarding dialog logic, chat-path phase state machine |
iOS/DuckDuckGo/OnboardingFlow/LinearOnboarding/OnboardingIntroViewModel.swift |
Experiment enrollment, step injection |
iOS/DuckDuckGo/NewTabPageViewController.swift |
Visit-site dialog presentation, toolbar hiding |
iOS/DuckDuckGo/MainViewController+DuckAIExperiment.swift |
Chat-path completion, EOJ dialog trigger |
iOS/Core/FeatureFlag.swift |
onboardingDuckAIQueryExperiment feature flag + cohorts |
iOS/DuckDuckGo/UserText.swift |
Onboarding copy strings (DuckAIQueryExperiment, SearchExperience) |
iOS/DuckDuckGo/OnboardingFlow/LinearOnboarding/OnboardingView+DuckAIExperimentSearchContent.swift |
DuckAIQuery toggle + experiment UI |
iOS/DuckDuckGo/OnboardingFlow/ContextualOnboarding/Rebranding/RebrandedNewTabDaxDialogFactory.swift |
Chat-path dialog creation |
Copy Changes Summary
| Location | Old | New | Status |
|---|---|---|---|
DuckAIQueryExperiment.toggleAILabel (onboarding toggle) |
Duck.ai |
Ask.ai |
✅ Done |
searchAndDuckAIOption (Search Experience screen) |
Toggle between\nSearch and Duck.ai |
(should remain Duck.ai) | ❌ Needs revert |
Experiment Config
{
"experimentName": "TBD",
"targets": [{ "localeLanguage": "en", "localeCountry": "US" }],
"cohorts": ["control", "treatmentA", "treatmentB"]
}
Feature flag:
FeatureFlag.onboardingDuckAIQueryExperiment
Cohort type:FeatureFlag.DuckAIQueryExperimentCohort(.control,.treatmentA,.treatmentB)