[2026-07-09] eagle: work/projects/ios-subscription-day7-promo-pixels.md
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
|
||||
- **Project:** [iOS: Show subscription half-sheet promo to new installers who don't see it during onboarding](https://app.asana.com/1/137249556945/project/1202406491309510/task/1214798984829406)
|
||||
- **Android counterpart:** [Grow active subscriptions by increasing paywall impressions with a day 7 promo half-sheet](https://app.asana.com/1/137249556945/project/72649045549333/task/1210994036696114) — the iOS implementation follows the same approach and target audience as Android
|
||||
- **Origin request:** [Request origin for iOS subscription promo half-sheet entry point](https://app.asana.com/1/137249556945/task/1214800683792174) — **origin not yet formally approved**; placeholder in code is `funnel_modal_ios__subscriptionnudge`. Android equivalent (formally approved, post-unification): `funnel_browsermodal_android` ([origin definition](https://app.asana.com/1/137249556945/task/1214454966691411), [unify origins task](https://app.asana.com/1/137249556945/task/1214440762354001))
|
||||
- **Origin request:** [Request origin for iOS subscription promo half-sheet entry point](https://app.asana.com/1/137249556945/task/1214800683792174) — origin not yet formally approved; suggested name `funnel_modal_ios__subscriptionnudge` follows Android equivalent `funnel_modal_android__subscriptionnudge`
|
||||
- We are adding a new half-sheet modal for existing users (7+ days since install) who have never seen any subscription offer. The modal reuses the pre-existing `SubscriptionPromoLaunchView` UI.
|
||||
- Existing subscription promo pixels already cover related audiences:
|
||||
- `m_privacy-pro_onboarding_promotion_[impression|tap|dismiss]` — users who see the promo during onboarding
|
||||
@@ -20,41 +20,26 @@
|
||||
|
||||
## Android reference
|
||||
|
||||
Android uses **shared pixels** for both the reinstaller promo and the day-7 promo, with **no `origin` pixel parameter** — origin is only embedded in the subscription purchase URL (`https://duckduckgo.com/pro?origin=…`) for downstream funnel attribution:
|
||||
Android has **separate pixels and origins per audience**, managed via a `SubscriptionPromoFlow` enum in `Cta.kt` (current main branch):
|
||||
|
||||
| Event | Android pixel string | `origin` in URL |
|
||||
|---|---|---|
|
||||
| Shown (both audiences) | `m_odc_s` | `funnel_browsermodal_android` (unified; was `funnel_skippedonboarding_android` / `funnel_newusermodal_android` before unification) |
|
||||
| CTA tapped (both audiences) | `m_odc_ok` | same as above |
|
||||
| Dismissed (both audiences) | `m_onboarding_dax_cta_dismiss` | same as above |
|
||||
| Flow | Audience | Origin (in URL) | Shown pixel | Subscribe pixel |
|
||||
|---|---|---|---|---|
|
||||
| `SKIPPED_ONBOARDING` | Reinstaller / skipped onboarding | `funnel_modal_android__skippedonboardingupsell` | `m_subscription_promo_modal_skipped_onboarding_shown` | `m_subscription_promo_modal_skipped_onboarding_subscribe_clicked` |
|
||||
| `NUDGE` | Day-7 existing users | `funnel_modal_android__subscriptionnudge` | `m_subscription_promo_modal_nudge_shown` | `m_subscription_promo_modal_nudge_subscribe_clicked` |
|
||||
|
||||
The two audiences are **indistinguishable at the pixel level** on Android — analysis relies on the origin flowing to downstream purchase pixels. Source: [Android PR #8369](https://github.com/duckduckgo/Android/pull/8369), `BrowserTabViewModel.kt` + `CtaViewModel.kt`.
|
||||
Both flows also fire legacy shared pixels (`m_odc_s` shown, `m_odc_ok` CTA tap, `m_onboarding_dax_cta_dismiss` dismiss) inherited from the base `Cta` interface — there is no dismiss-specific per-audience pixel on Android.
|
||||
|
||||
Android pixel definition / privacy triage tasks cover Phase 1 paywall instrumentation only (`m_subscription_paywall_not_seen_*`) — the promo modal itself got no separate pixel definition or privacy triage:
|
||||
The iOS origin task's suggested name `funnel_modal_ios__subscriptionnudge` follows the same format as Android's `funnel_modal_android__subscriptionnudge`. Source: `Cta.kt`, `CtaViewModel.kt` on Android main.
|
||||
|
||||
Android pixel definition / privacy triage tasks cover Phase 1 paywall instrumentation only (`m_subscription_paywall_not_seen_*`) — the promo modal pixels themselves got no separate pixel definition or privacy triage:
|
||||
- [Define pixels to track users who haven't seen the subscription paywall](https://app.asana.com/1/137249556945/task/1213904100962479)
|
||||
- [Privacy Triage: Android - Added new subscription_promo_shown pixel param](https://app.asana.com/1/137249556945/task/1214025242626360)
|
||||
|
||||
---
|
||||
|
||||
## Option A — Recommended: Reuse existing pixels (mirrors Android approach)
|
||||
## Proposed pixels (mirrors Android)
|
||||
|
||||
Reuse `m_privacy-pro_skipped_onboarding_promotion_[impression|tap|dismiss]` for the day-7 audience. Audience attribution relies on the origin URL parameter (`funnel_modal_ios__subscriptionnudge`) flowing to downstream purchase pixels — identical to Android's approach.
|
||||
|
||||
**No new pixels required. No privacy triage required for new pixels.**
|
||||
|
||||
| Pixel | Trigger |
|
||||
|---|---|
|
||||
| `m_privacy-pro_skipped_onboarding_promotion_impression` | Day-7 half-sheet shown |
|
||||
| `m_privacy-pro_skipped_onboarding_promotion_tap` | User taps CTA |
|
||||
| `m_privacy-pro_skipped_onboarding_promotion_dismiss` | User dismisses without tapping CTA |
|
||||
|
||||
**Trade-off:** Cross-audience analysis (reinstallers vs day-7 existing users) is not directly available from pixels alone; it requires joining on origin via downstream `m_privacy-pro_offer_screen_impression` / `m_subscribe` pixels.
|
||||
|
||||
---
|
||||
|
||||
## Option B — Alternative: Separate pixels per audience
|
||||
|
||||
Define three new pixels exclusively for the day-7 audience. Provides direct per-audience split in pixel dashboards without filtering by origin. Requires a new privacy triage.
|
||||
Separate pixels per audience, consistent with Android's `NUDGE` flow. Provides direct per-audience split in pixel dashboards. Requires a new privacy triage.
|
||||
|
||||
### Testing
|
||||
|
||||
@@ -99,15 +84,11 @@ Define three new pixels exclusively for the day-7 audience. Provides direct per-
|
||||
- The dismiss pixel fires on both explicit close (X button) and swipe-to-dismiss; neither path fires the tap pixel.
|
||||
- If the user taps CTA, tap fires but dismiss does not.
|
||||
|
||||
**Trade-off:** Three new pixels to triage. Structurally identical to `m_privacy-pro_skipped_onboarding_promotion_*` — no new parameter types are introduced.
|
||||
Structurally identical to `m_privacy-pro_skipped_onboarding_promotion_[impression|tap|dismiss]` — no new parameter types are introduced.
|
||||
|
||||
---
|
||||
|
||||
## Notes and status
|
||||
|
||||
- Option A pixels are already defined in `subscription.json5` as `m_privacy-pro_skipped_onboarding_promotion_[impression|tap|dismiss]`; reusing them for this audience requires no code changes to pixel definitions.
|
||||
- If Option B is chosen, new definitions must be added to `subscription.json5` and a privacy triage opened.
|
||||
- Privacy triage (for Option B): [Insert Privacy Triage link]
|
||||
- The iOS origin value needs to be formally submitted and approved via the [Origin Proposal form](https://form.asana.com/?k=Wy3aY17vglr2bihpUHoyBA&d=137249556945).
|
||||
- Suggested name: `funnel_modal_ios__subscriptionnudge`.
|
||||
- Android equivalent (post-unification): `funnel_browsermodal_android`.
|
||||
- New pixel definitions to be added to `subscription.json5`. Privacy triage required: [Insert Privacy Triage link]
|
||||
- The iOS origin value needs to be formally submitted and approved via the [Origin Proposal form](https://form.asana.com/?k=Wy3aY17vglr2bihpUHoyBA&d=137249556945). Suggested name: `funnel_modal_ios__subscriptionnudge`. Android equivalent: `funnel_modal_android__subscriptionnudge`.
|
||||
|
||||
Reference in New Issue
Block a user