diff --git a/docs/platform-guides/desktop/targeting.md b/docs/platform-guides/desktop/targeting.md index f5d7a3939..5aab71463 100644 --- a/docs/platform-guides/desktop/targeting.md +++ b/docs/platform-guides/desktop/targeting.md @@ -169,9 +169,9 @@ os.isMac | Attribute | Type | Description | Example | |-----------|------|-------------|---------| -| `activeExperiments` | `string[]` | Currently enrolled experiment slugs | `'my-experiment' in activeExperiments` | -| `activeRollouts` | `string[]` | Currently enrolled rollout slugs | `!('some-rollout' in activeRollouts)` | -| `enrollmentsMap` | `array` | All enrollments as `{experimentSlug, branchSlug}` entries | Used for branch-level exclusion | +| `activeExperiments` | `string[]` | Currently enrolled experiment slugs (active only) | `'my-experiment' in activeExperiments` | +| `activeRollouts` | `string[]` | Currently enrolled rollout slugs (active only) | `!('some-rollout' in activeRollouts)` | +| `enrollmentsMap` | `object` | Map of experiment/rollout slug → branch slug for all enrollments (active and inactive). See [enrollmentsMap details](#enrollmentsmap) below. | `enrollmentsMap['my-holdback'] == 'treatment'` | ### New Tab & Home Page @@ -439,6 +439,30 @@ userMonthlyActivity|length >= 14 && userMonthlyActivity|length < 21 !('other-experiment-slug' in activeExperiments) ``` +### Branch-level dependency with `enrollmentsMap` {#enrollmentsmap} + +`enrollmentsMap` is an object that maps experiment/rollout slugs to branch slugs. Unlike `activeExperiments` and `activeRollouts` (which only contain currently active enrollments), `enrollmentsMap` includes **both active and inactive** enrollment records. This makes it useful for targeting based on a client's enrollment history — for example, requiring that a client was previously enrolled in a specific branch of a holdback experiment. + +``` +// Require enrollment in the delivery branch of a holdback +enrollmentsMap['long-term-holdback-2026-growth-desktop'] == 'delivery' +``` + +:::warning 12-Month Retention After Ending +Enrollment records stay in `enrollmentsMap` **indefinitely while the experiment/rollout is live** — there is no time limit for active enrollments. The retention limit only applies after an experiment **ends**: once an enrollment becomes inactive, its record is permanently deleted from the client's store **12 months (365.25 days) after the original enrollment date** (see [`_cleanupOldRecipes()`](https://searchfox.org/firefox-main/rev/62b11cf9d978f8c6f8144156feebf42af5d71cf9/toolkit/components/nimbus/lib/ExperimentStore.sys.mjs#390)). Once deleted, the key is removed from `enrollmentsMap` and any targeting expression that references it will no longer match. + +This means if experiment B's targeting depends on enrollment in experiment A via `enrollmentsMap`, and experiment A ends, you have a **12-month window** (from when each client originally enrolled in A) before clients start losing the record. After that point, clients will begin unenrolling from experiment B with `targeting-mismatch` as their `enrollmentsMap` entries for experiment A are cleaned up. Clients who enrolled earlier in experiment A's lifetime will be affected first. + +::: + +**Key differences between enrollment attributes:** + +| Attribute | Includes Active | Includes Inactive | Provides Branch | Retention | +|-----------|:-:|:-:|:-:|---| +| `activeExperiments` | ✅ | ❌ | ❌ | Current session only | +| `activeRollouts` | ✅ | ❌ | ❌ | Current session only | +| `enrollmentsMap` | ✅ | ✅ | ✅ | Indefinite while active; 12 months from enrollment date after ending | + ## Recorded Targeting Context (Telemetry) Firefox records a snapshot of all the targeting attribute values listed above in the `nimbus-targeting-context` ping, which lands in BigQuery at `mozdata.firefox_desktop.nimbus_targeting_context`. This is used for: diff --git a/yarn.lock b/yarn.lock index 79fe25590..d55310461 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8121,6 +8121,8 @@ webpack-sources@^3.2.2, webpack-sources@^3.2.3: "webpack@^4.0.0 || ^5.0.0", "webpack@^4.37.0 || ^5.0.0", webpack@^5.0.0, webpack@^5.1.0, webpack@^5.20.0, webpack@^5.73.0, "webpack@>= 4", webpack@>=2, "webpack@>=4.41.1 || 5.x", "webpack@3 || 4 || 5": version "5.89.0" + resolved "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz" + integrity sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw== dependencies: "@types/eslint-scope" "^3.7.3" "@types/estree" "^1.0.0"