Merge remote-tracking branch 'origin/main'
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
# Pixel Definitions: iOS Day-7 Subscription Promo
|
||||
|
||||
Defined in: `iOS/PixelDefinitions/pixels/definitions/subscription.json5`
|
||||
Fired from: `SubscriptionPromoExistingUserCoordinator`
|
||||
Android equivalents: `m_privacy-pro_skipped_onboarding_promotion_*` (same modal, different audience)
|
||||
|
||||
---
|
||||
|
||||
## Pixels
|
||||
|
||||
### `m_privacy-pro_existing_user_promotion_impression`
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| Trigger | The day-7 promo half-sheet is shown to an existing user (7+ days since install) who has never seen any subscription offer |
|
||||
| Fired from | `SubscriptionPromoExistingUserCoordinator.markLaunchPromptPresented()` |
|
||||
| Frequency | Once per install (guarded by `subscriptionPromotionDialogShown`) |
|
||||
|
||||
**Parameters**
|
||||
|
||||
| Key | Type | Description |
|
||||
|---|---|---|
|
||||
| `appVersion` | string | App version (added by default) |
|
||||
| `ru` | boolean | Whether the user is a returning user (reinstall) |
|
||||
| `free_trial` | boolean | Whether the user is eligible for a free trial |
|
||||
|
||||
**Suffixes:** `_ios`, `_phone` / `_tablet`
|
||||
|
||||
---
|
||||
|
||||
### `m_privacy-pro_existing_user_promotion_tap`
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| Trigger | User taps the CTA button ("Try It Free" or "Learn More") on the promo modal |
|
||||
| Fired from | `SubscriptionPromoExistingUserCoordinator.handleCTAAction()` |
|
||||
|
||||
**Parameters** — same as impression: `appVersion`, `ru`, `free_trial`
|
||||
|
||||
**Suffixes:** `_ios`, `_phone` / `_tablet`
|
||||
|
||||
---
|
||||
|
||||
### `m_privacy-pro_existing_user_promotion_dismiss`
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| Trigger | User dismisses the promo modal (taps close or swipes down) |
|
||||
| Fired from | `SubscriptionPromoExistingUserCoordinator.handleDismissAction()` |
|
||||
|
||||
**Parameters** — same as impression: `appVersion`, `ru`, `free_trial`
|
||||
|
||||
**Suffixes:** `_ios`, `_phone` / `_tablet`
|
||||
|
||||
---
|
||||
|
||||
## Funnel Origin
|
||||
|
||||
When the user taps the CTA, the subscription flow is opened with origin `funnel_modal_ios__subscriptionnudge`.
|
||||
|
||||
This origin flows through to two downstream pixels automatically:
|
||||
- `m_privacy-pro_offer_screen_impression` (param: `origin`)
|
||||
- `m_subscribe` (param: `origin`) — the subscription purchase success pixel
|
||||
|
||||
Origin defined in: `iOS/DuckDuckGo/Subscription/SubscriptionFunnelOrigin.swift`
|
||||
Origin request subtask: https://app.asana.com/1/137249556945/task/1214800683792174
|
||||
Android equivalent origin: `funnel_modal_android__subscriptionnudge`
|
||||
|
||||
---
|
||||
|
||||
## Relation to Existing Promo Pixels
|
||||
|
||||
All three subscription promo half-sheets use the same parameter shape (`ru`, `free_trial`) to allow cross-audience comparison:
|
||||
|
||||
| Pixel prefix | Audience | Origin |
|
||||
|---|---|---|
|
||||
| `m_privacy-pro_onboarding_promotion_*` | Users who see the promo during onboarding | `funnel_onboarding_ios` |
|
||||
| `m_privacy-pro_skipped_onboarding_promotion_*` | Reinstallers who skipped onboarding, 7+ days | `funnel_modal_ios__skippedonboardingupsell` |
|
||||
| `m_privacy-pro_existing_user_promotion_*` | Normal installers who never saw a subscription offer, 7+ days | `funnel_modal_ios__subscriptionnudge` |
|
||||
@@ -0,0 +1,82 @@
|
||||
# Privacy Triage: iOS Day-7 Subscription Promo Pixels
|
||||
|
||||
Status: **DRAFT** — to be reviewed and submitted before ship review
|
||||
Asana project task: https://app.asana.com/1/137249556945/project/1202406491309510/task/1214798984829406
|
||||
|
||||
---
|
||||
|
||||
## What pixels are being added?
|
||||
|
||||
Three new pixels fired from `SubscriptionPromoExistingUserCoordinator`:
|
||||
|
||||
| Pixel name | When fired |
|
||||
|---|---|
|
||||
| `m_privacy-pro_existing_user_promotion_impression` | The day-7 promo half-sheet is displayed |
|
||||
| `m_privacy-pro_existing_user_promotion_tap` | User taps the CTA ("Try It Free" / "Learn More") |
|
||||
| `m_privacy-pro_existing_user_promotion_dismiss` | User dismisses the promo modal |
|
||||
|
||||
---
|
||||
|
||||
## Parameters sent with each pixel
|
||||
|
||||
| Parameter key | Type | Value | Description |
|
||||
|---|---|---|---|
|
||||
| `appVersion` | string | e.g. `7.215.0` | App version, added automatically |
|
||||
| `ru` | boolean | `true` / `false` | Whether the user is a returning user (reinstall detected via variant `"ru"`) |
|
||||
| `free_trial` | boolean | `true` / `false` | Whether the user is eligible for a free trial at time of display |
|
||||
|
||||
No user identifiers, no browsing data, no PII.
|
||||
|
||||
---
|
||||
|
||||
## Privacy Assessment
|
||||
|
||||
### Is any new data collected about the user?
|
||||
|
||||
No new data is collected from the user. The parameters (`ru`, `free_trial`) are:
|
||||
- `ru` — derived from the install variant flag already stored locally; same parameter used by `m_privacy-pro_onboarding_promotion_impression` and `m_privacy-pro_skipped_onboarding_promotion_impression`
|
||||
- `free_trial` — derived from App Store product availability check already performed by `SubscriptionManager`; same parameter used by the existing promo pixels above
|
||||
|
||||
### Does this introduce any new data collection mechanism?
|
||||
|
||||
No. These pixels follow the identical pattern of the pre-existing `m_privacy-pro_skipped_onboarding_promotion_*` pixels, which have already passed privacy triage.
|
||||
|
||||
### Is the data linked to a user or device?
|
||||
|
||||
No. Pixels are sent anonymously via the standard pixel infrastructure. No user ID, device ID, or ATB is included.
|
||||
|
||||
### What is the purpose of the data?
|
||||
|
||||
Measure the effectiveness of the day-7 promo half-sheet:
|
||||
- **Impression** — how many eligible users see the promo
|
||||
- **Tap** — conversion rate from impression to CTA click
|
||||
- **Dismiss** — dismissal rate
|
||||
|
||||
This data will be used to evaluate whether the feature achieves the goal of 10 trial starts/day and to decide whether to keep the feature on.
|
||||
|
||||
### How long is the data retained?
|
||||
|
||||
Standard pixel retention policy applies. Pixels are not stored on device after firing.
|
||||
|
||||
### Are there any additional risks?
|
||||
|
||||
The `ru` parameter could theoretically indicate a user is a reinstaller, but:
|
||||
- This information is already sent in the existing promo pixels
|
||||
- It is aggregated data with no user-level linkage
|
||||
- It is used only to segment promo performance by user cohort
|
||||
|
||||
---
|
||||
|
||||
## Comparison to existing approved pixels
|
||||
|
||||
These pixels are structurally identical to `m_privacy-pro_skipped_onboarding_promotion_*`, which were already approved. The only differences are:
|
||||
1. Different pixel name (different audience segment)
|
||||
2. Different origin value (`funnel_modal_ios__subscriptionnudge` vs `funnel_modal_ios__skippedonboardingupsell`)
|
||||
|
||||
---
|
||||
|
||||
## Open questions for privacy reviewer
|
||||
|
||||
- [ ] Is the `ru` (returning user) parameter still acceptable given no new data is collected?
|
||||
- [ ] Is there any concern with the `free_trial` parameter being sent on dismiss (user never tapped CTA)?
|
||||
- [ ] Are there any additional parameters the privacy team would like to see for monitoring purposes?
|
||||
Reference in New Issue
Block a user