Skip to content

Commit 3c5729c

Browse files
Ship the onboarding widget prompt and remove the Add to Dock experiment (#9857)
Task/Issue URL: https://app.asana.com/1/137249556945/project/72649045549333/task/1217068101576174 Tech Design URL (if applicable): API Proposals URL(s) (if applicable): None ### Description The `onboardingPrompts` / `addToDockAndWidgetExperimentJul25` experiment concluded with the widget-only variant winning. This PR ships that variant and cleans up the experiment: - The widget prompt (`widget_prompt` + `add_widget` steps, right after the default browser prompt) is now a default step of the linear onboarding plan for every user without an installed widget, reinstallers included. - Removed `OnboardingPromptsExperimentManager`, `OnboardingPromptsToggles` and `OnboardingPromptsExperimentMetrics`, along with the metric calls in `WidgetAddedReceiver`, `SystemSearchViewModel` and `OnboardingCompletedMetricObserver`, and the prerequisite check in `SegmentedOnboardingExperimentManager`. The `onboardingPrompts` feature is also removed from the bundled `privacy_config.json`. - Removed everything Add to Dock related: step, dialog, step id, dialog type, `onboarding_add-to-dock` pixel, both welcome-page branches, the config-driven resolver/binder/controller entries, the tutorial video, sketch-frame drawable, include layout, `AspectRatioTextureView`, dimen, lint-baseline entry, and the English and translated strings (lint-vital fails release builds on `ExtraTranslation` otherwise). - Maestro: the widget prompt is now a mandatory step in `pre_onboarding.yaml`; the `linearWidgetPromptShown` output flag is gone and `onboarding_dismiss_all_dialogs.yaml` asserts the in-context widget CTA is not shown. ### Steps to test this PR _Fresh install, no widget_ - [x] Install a fresh build and go through onboarding - [x] After the default browser prompt, verify the "Try our Home screen widget" page shows with a step indicator - [x] Tap "Add widget" and verify the system pin dialog appears, then the flow continues to the address bar position page - [x] Complete onboarding, open a New Tab Page and verify the widget bottom sheet is NOT shown _Fresh install, skip widget_ - [x] Go through onboarding and tap "Not Now" on the widget page - [x] Verify the flow continues to the address bar position page and the widget bottom sheet is NOT shown afterwards _Widget already installed_ - [x] Add a DuckDuckGo widget to the home screen before the widget page is reached and verify the widget page is skipped _Reinstall_ - [x] Install the app as a reinstallers, choose to go through full onboarding, and verify the widget page is shown _Add to Dock_ - [x] Verify no "Add me to your favorites row" page appears anywhere in onboarding _Automated_ - [ ] Maestro `onboarding/onboarding.yaml` and `onboarding/onboarding_dismiss_all_dialogs.yaml` pass ### UI changes | Before | After | | ------ | ----- | Widget prompt only for the `treatmentWidgetOnly` / `treatmentDockAndWidget` cohorts; Add to Dock page for dock cohorts|Widget prompt for everyone without a widget; no Add to Dock page| 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
1 parent 0435707 commit 3c5729c

69 files changed

Lines changed: 44 additions & 1519 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.maestro/onboarding/onboarding_dismiss_all_dialogs.yaml‎

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -52,20 +52,11 @@ tags:
5252
text: ".*Remember: every time you browse with me a creepy ad loses its.wings..*"
5353
- runFlow: ../shared/browser_screen/click_on_tabs_button.yaml
5454
- tapOn: "New Tab"
55-
- runFlow:
56-
when:
57-
true: ${!output.linearWidgetPromptShown}
58-
commands:
59-
- assertVisible:
60-
text: ".*Try our Home screen widget!.*"
61-
- runFlow:
62-
when:
63-
true: ${output.linearWidgetPromptShown}
64-
commands:
65-
- extendedWaitUntil:
66-
visible:
67-
text: ".*Try our Home screen widget!.*"
68-
timeout: 3000
69-
optional: true
70-
- assertNotVisible:
71-
text: ".*Try our Home screen widget!.*"
55+
# The widget prompt in linear onboarding replaces the in-context widget CTA.
56+
- extendedWaitUntil:
57+
visible:
58+
text: ".*Try our Home screen widget!.*"
59+
timeout: 3000
60+
optional: true
61+
- assertNotVisible:
62+
text: ".*Try our Home screen widget!.*"

‎.maestro/shared/pre_onboarding.yaml‎

Lines changed: 3 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
appId: com.duckduckgo.mobile.android
22
---
3-
# Consumers need to know whether the linear widget step was shown: it and the end-of-onboarding widget
4-
# bottom sheet are mutually exclusive (see AddWidgetModalEvaluator).
5-
- evalScript: ${output.linearWidgetPromptShown = false}
63
- assertVisible:
74
text: ".*(Ready for a faster browser that protects you and lets you decide when and how to use.AI|Ready for a faster browser that puts you in.control).*"
85
- tapOn:
@@ -29,32 +26,9 @@ appId: com.duckduckgo.mobile.android
2926
true: ${SET_AS_DEFAULT != 'true'}
3027
commands:
3128
- tapOn: "cancel"
32-
# The "Add to Dock" / "Widget prompt" onboarding pages only show for some cohorts of the
33-
# addToDockAndWidgetExperimentJul25 experiment (see OnboardingPromptsToggles); both are optional so
34-
# this flow stays deterministic regardless of which cohort a run gets enrolled into.
35-
- extendedWaitUntil:
36-
visible:
37-
id: "addToDockTitle"
38-
timeout: 3000
39-
optional: true
40-
- runFlow:
41-
when:
42-
visible:
43-
id: "addToDockTitle"
44-
commands:
45-
- tapOn: "Got it!"
46-
- extendedWaitUntil:
47-
visible:
48-
id: "widgetPromptTitle"
49-
timeout: 3000
50-
optional: true
51-
- runFlow:
52-
when:
53-
visible:
54-
id: "widgetPromptTitle"
55-
commands:
56-
- tapOn: "Not Now"
57-
- evalScript: ${output.linearWidgetPromptShown = true}
29+
- assertVisible:
30+
id: "widgetPromptTitle"
31+
- tapOn: "Not Now"
5832
- assertVisible:
5933
text: ".*where should I put your address.bar?.*"
6034
- tapOn: "next"

‎PixelDefinitions/pixels/definitions/onboarding.json5‎

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -132,21 +132,6 @@
132132
}
133133
]
134134
},
135-
"onboarding_add-to-dock": {
136-
"description": "Add-to-Dock onboarding page. shown when the page is displayed; clicked when the user taps Continue. Unique once per user per event.",
137-
"owners": ["catalinradoiu"],
138-
"triggers": ["other"],
139-
"suffixes": ["form_factor"],
140-
"parameters": [
141-
"appVersion",
142-
"onboardingEvent",
143-
"onboardingInstallType",
144-
"onboardingDaysSinceInstall",
145-
"onboardingFlow",
146-
"onboardingPixelSource",
147-
{ "key": "value", "type": "string", "description": "Only set when event=clicked.", "enum": ["engage"] }
148-
]
149-
},
150135
"onboarding_widget-prompt": {
151136
"description": "Widget-prompt onboarding page. shown when the page is displayed; clicked engage/dismiss on the Add widget / Skip CTAs; confirmed added/not_added after the system add-widget prompt returns. Unique once per user per (event, value).",
152137
"owners": ["catalinradoiu"],

‎app/lint-baseline.xml‎

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5709,17 +5709,6 @@
57095709
column="20"/>
57105710
</issue>
57115711

5712-
<issue
5713-
id="VectorRaster"
5714-
message="Limit vector icons sizes to 200×200 to keep icon drawing fast; see https://developer.android.com/studio/write/vector-asset-studio#when for more"
5715-
errorLine1=" android:width=&quot;281dp&quot;"
5716-
errorLine2=" ~~~~~">
5717-
<location
5718-
file="src/main/res/drawable/onboarding_add_to_dock_sketch_frame.xml"
5719-
line="2"
5720-
column="20"/>
5721-
</issue>
5722-
57235712
<issue
57245713
id="VectorRaster"
57255714
message="Limit vector icons sizes to 200×200 to keep icon drawing fast; see https://developer.android.com/studio/write/vector-asset-studio#when for more"

‎app/src/main/java/com/duckduckgo/app/onboarding/OnboardingCompletedMetricObserver.kt‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ import javax.inject.Inject
3636
class OnboardingCompletedMetricObserver @Inject constructor(
3737
@AppCoroutineScope private val appCoroutineScope: CoroutineScope,
3838
private val userStageStore: UserStageStore,
39-
private val onboardingPromptsExperimentMetrics: OnboardingPromptsExperimentMetrics,
4039
private val segmentedOnboardingExperimentMetrics: SegmentedOnboardingExperimentMetrics,
4140
private val onboardingPasswordImportExperimentMetrics: OnboardingPasswordImportExperimentMetrics,
4241
) : MainProcessLifecycleObserver {
@@ -45,7 +44,6 @@ class OnboardingCompletedMetricObserver @Inject constructor(
4544
userStageStore.userAppStageFlow()
4645
.filter { it == AppStage.ESTABLISHED }
4746
.onEach {
48-
onboardingPromptsExperimentMetrics.fireOnboardingCompletedMetric()
4947
segmentedOnboardingExperimentMetrics.fireOnboardingCompletedMetric()
5048
onboardingPasswordImportExperimentMetrics.fireOnboardingCompletedMetric()
5149
}

‎app/src/main/java/com/duckduckgo/app/onboarding/OnboardingPromptsExperimentManager.kt‎

Lines changed: 0 additions & 74 deletions
This file was deleted.

‎app/src/main/java/com/duckduckgo/app/onboarding/OnboardingPromptsExperimentMetrics.kt‎

Lines changed: 0 additions & 106 deletions
This file was deleted.

‎app/src/main/java/com/duckduckgo/app/onboarding/OnboardingPromptsToggles.kt‎

Lines changed: 0 additions & 46 deletions
This file was deleted.

‎app/src/main/java/com/duckduckgo/app/onboarding/SegmentedOnboardingExperimentManager.kt‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ class SegmentedOnboardingExperimentManagerImpl @Inject constructor(
4242
private val onboardingBrandDesignUpdateToggles: OnboardingBrandDesignUpdateToggles,
4343
private val segmentedOnboardingFeatureToggles: SegmentedOnboardingFeatureToggles,
4444
private val onboardingPasswordImportToggles: OnboardingPasswordImportToggles,
45-
private val onboardingPromptsToggles: OnboardingPromptsToggles,
4645
private val appBuildConfig: AppBuildConfig,
4746
private val dispatcherProvider: DispatcherProvider,
4847
private val onboardingPrivacyConfigPersistedGate: OnboardingPrivacyConfigPersistedGate,
@@ -65,7 +64,6 @@ class SegmentedOnboardingExperimentManagerImpl @Inject constructor(
6564
private suspend fun checkPrerequisites() =
6665
onboardingBrandDesignUpdateToggles.brandDesignUpdate().isEnabled() &&
6766
onboardingBrandDesignUpdateToggles.configDrivenDialogs().isEnabled() &&
68-
!onboardingPromptsToggles.addToDockAndWidgetExperimentJul25().isEnabled() &&
6967
!onboardingPasswordImportToggles.passwordImportExperimentAug25().isEnabled() &&
7068
!appBuildConfig.isAppReinstall()
7169
}

‎app/src/main/java/com/duckduckgo/app/onboarding/orchestrator/NewUserOnboardingActivityDialog.kt‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ sealed interface NewUserOnboardingActivityDialog {
3737
data object AiComparisonChart : NewUserOnboardingActivityDialog
3838
data class SegmentedComparisonChart(val chart: ComparisonChartConfig) : NewUserOnboardingActivityDialog
3939
data object DefaultBrowserPrompt : NewUserOnboardingActivityDialog
40-
data object AddToDock : NewUserOnboardingActivityDialog
4140
data object WidgetPrompt : NewUserOnboardingActivityDialog
4241

4342
data object AddWidget : NewUserOnboardingActivityDialog

0 commit comments

Comments
 (0)