Files
obsidian-vault/work/wiki/apple-browsers/chat-path-onboarding-tracker-blocking.md
T

7.4 KiB

iOS: Chat-Path Onboarding — Tracker Blocking Demo

Asana: Ship Review task
Branch stack: demo-tracker-blocking-onboardingui-polishchat-path-dialog-polishsr-feedbackuti-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 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) with KeyedStoring protocol pattern — new @UserDefaultsWrapper definitions are blocked by Danger rule.
  • Mock refactor (alessandroboron): MockDaxDialogsSettings.chatPathPhase should expose var _chatPathPhase: DaxDialogs.ChatPathPhase = .visitSite for 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 variant parameter on existing pixels instead of adding new chat-path-specific pixel events.

PR #4664 — chat-path dialog polish

  • Title scope (alessandroboron): RebrandedNewTabDaxDialogFactory title 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 in unifiedInputContentContainer.
  • Dialog not dismissed on navigation: viewWillDisappear removes hosting controller parented to MainViewController.
  • UTI bar staying active after URL submission: preserveOmnibarSession now checks !tab.isLoading.
  • "You've got this" completion dialog path in UTI mode: showDuckAIOnboardingCompletionDialogInUTI.
  • UTI bar staying active after completion dismiss: call dismissUnifiedToggleInputToOmnibar directly.
  • Stale browsing-dialog flags: setAsChatFirstPath now resets all browsing-dialog flags to prevent chatPathPhase jumping to .trackerToEOJ from stale state.
  • Hardcoded cohort override (aataraxiaa): FeatureFlag.swift has 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: NewTabPageViewController should access the parent via NewTabPageControllerDelegate instead of (parent as? MainViewController)? cast.
  • Loading guard: Move currentTab?.isLoading != true check into the if condition, not a standalone guard (avoids orphaned reference and blank NTP on early exit).
  • Revert Search Experience screen copy: searchAndDuckAIOption was 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() in DaxDialogs for 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)