117 lines
6.5 KiB
Markdown
117 lines
6.5 KiB
Markdown
# iOS: Chat-Path Onboarding — Tracker Blocking Demo
|
|
|
|
> **Asana:** [Ship Review task](https://app.asana.com/1/137249556945/task/1214147157456478)
|
|
> **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:
|
|
1. "Try visiting a site!" dialog (address bar + toolbar hidden)
|
|
2. Trackers-blocked dialog after a site loads
|
|
3. "You've got this!" EOJ completion dialog
|
|
4. 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](https://github.com/duckduckgo/apple-browsers/pull/4544) | `demo-tracker-blocking-onboarding` | Open — needs fixes |
|
|
| [#4591](https://github.com/duckduckgo/apple-browsers/pull/4591) | `demo-tracker-blocking-onboarding-ui-polish` | Approved — needs rebase |
|
|
| [#4664](https://github.com/duckduckgo/apple-browsers/pull/4664) | `demo-tracker-blocking-onboarding-chat-path-dialog-polish` | Open — needs fix |
|
|
| [#4668](https://github.com/duckduckgo/apple-browsers/pull/4668) | `demo-tracker-blocking-onboarding-uti-flow` | Open — needs fix |
|
|
| [#4855](https://github.com/duckduckgo/apple-browsers/pull/4855) | `demo-tracker-blocking-onboarding-sr-feedback` | Open — needs fixes |
|
|
|
|
---
|
|
|
|
## Required Changes
|
|
|
|
### PR #4544 — main chat-path branch
|
|
|
|
- [x] **Danger CI**: No `@UserDefaultsWrapper` usage remains.
|
|
- [x] **Mock refactor** (alessandroboron): `MockDaxDialogsSettings.chatPathPhase` is a plain stored property, directly settable in tests.
|
|
- [x] **Sync restore exclusion**: Uncommented `guard case .introDialog(isReturningUser: false) = introSteps.first` in `OnboardingIntroViewModel.insertExperimentStepIfNeeded()`. Excludes all returning users (including sync-restore) from experiment enrollment.
|
|
- [x] **`return .treatmentA` override**: Removed hardcoded early return from `resolveDuckAIQueryExperimentCohortID()`. Now routes through the feature flagger.
|
|
- [x] **Pixels**: `onboardingChatPathTryVisitSiteUnique` and `onboardingChatPathTrackersBlockedUnique` defined in `PixelEvent.swift` with matching `onboarding.json5` entries. No overlap with PR #4687.
|
|
|
|
### PR #4664 — chat-path dialog polish
|
|
|
|
- [x] **Title scope** (alessandroboron): Fixed in commit `c15122a1b0` — `RebrandedNewTabDaxDialogFactory.createSubsequentDialog` uses the correct title per chat-path vs standard path.
|
|
|
|
### PR #4668 — UTI onboarding flow fixes
|
|
|
|
- [x] Dialog position, dismiss on navigation, UTI bar, completion path — all resolved.
|
|
- [x] **Hardcoded UTI override**: `FeatureFlag.swift` `.unifiedToggleInput` confirmed correct — `Config(source: .remoteReleasable(...))`, no `defaultValue: .enabled`.
|
|
|
|
### PR #4855 — sr-feedback
|
|
|
|
- [x] **Hide toolbar + address bar**: `NewTabPageViewController` now calls `chromeDelegate?.setBarsHidden(true/false, animated: false, customAnimationDuration: nil)` in the show block, `dismiss()`, and `dismissHostingController`. Replaces previous `setNavigationBarHidden` + `setChatPathVisitSiteControlsLocked` pair.
|
|
- [x] **Use delegate**: Added `newTabPageControllerCurrentTabIsLoading(_ controller:) -> Bool` to `NewTabPageControllerDelegate` (default `false`). Implemented in `MainViewController` as `currentTab?.isLoading == true`. All `(parent as? MainViewController)?` casts removed from `NewTabPageViewController`.
|
|
- [x] **Loading guard placement**: Folded into the outer `if` condition via the new delegate method. No orphaned lock possible.
|
|
- [x] **Revert Search Experience screen copy**: `UserText.swift` `searchAndDuckAIOption` reverted to `"Toggle between\nSearch and Duck.ai"`. All 26 lproj files updated.
|
|
- [x] **DuckAIQuery toggle copy**: `DuckAIQueryExperiment.toggleAILabel` = `"Ask AI"`.
|
|
|
|
---
|
|
|
|
## 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](https://app.asana.com/1/137249556945/task/1214601039604921) once experiment name is confirmed.
|
|
|
|
---
|
|
|
|
## Resolved / Dismissed
|
|
|
|
- **GJ6c** — No longer required.
|
|
- **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** — DuckAIQuery experiment toggle shows "Ask AI" (onboarding only; Search Experience screen keeps "Duck.ai").
|
|
- **"Try fire tabs" flash** — Suppressed via `isStillOnboarding()` in `DaxDialogs` for chat-path users.
|
|
- **GJ7** — 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, bar 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 |
|
|
| `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 | Value | Status |
|
|
|---|---|---|
|
|
| `DuckAIQueryExperiment.toggleAILabel` (onboarding experiment toggle) | `Ask AI` | Done |
|
|
| `searchAndDuckAIOption` (Search Experience screen) | `Toggle between\nSearch and Duck.ai` | Done |
|
|
|
|
---
|
|
|
|
## Experiment Config
|
|
|
|
```json
|
|
{
|
|
"experimentName": "TBD",
|
|
"targets": [{ "localeLanguage": "en", "localeCountry": "US" }],
|
|
"cohorts": ["control", "treatmentA", "treatmentB"]
|
|
}
|
|
```
|
|
|
|
> Feature flag: `FeatureFlag.onboardingDuckAIQueryExperiment`
|
|
> Cohort type: `FeatureFlag.DuckAIQueryExperimentCohort` (`.control`, `.treatmentA`, `.treatmentB`)
|