Skip to content

Commit 93fdf4c

Browse files
docs: update desktop Feature API reference to match current source (#785)
* docs: update desktop Feature API reference to match current source Because * The `getExperimentMetaData()` method documented in feature-api.mdx no longer exists in the source code — it was replaced by `getEnrollmentMetadata()` on each NimbusFeatures instance * Three new methods (`getEnrollmentMetadata`, `getAllEnrollments`, `getAllEnrollmentMetadata`) are undocumented * Desktop supports co-enrollment via `allowCoenrollment` in the feature manifest but the docs only cover mobile * The `off()` heading didn't match the actual method name `offUpdate()` * The FeatureManifest.yaml example was missing required fields This commit * Replaces the removed `getExperimentMetaData` section with `getEnrollmentMetadata()` documenting all three query modes * Adds `getAllEnrollments()` and `getAllEnrollmentMetadata()` sections for co-enrolling features * Documents the `slug` parameter on `recordExposureEvent()` for co-enrolling features * Fixes `off()` heading to `offUpdate()` * Enriches the manifest example with `owner`, `hasExposure`, `exposureDescription`, and `allowCoenrollment` * Adds Desktop co-enrollment support to coenrolling-features.mdx with manifest example, JS API example, and cross-links Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * docs: address review feedback on desktop API docs Because * Reviewer suggested using EnrollmentType constants instead of string literals to encourage best practices * T[] syntax preferred over Array<T> for type signatures * "and/or" more accurate than "or" for co-enrollment scenarios This commit * Uses EnrollmentType constants in getEnrollmentMetadata() signature, parameter docs, and code examples * Adds import comment showing EnrollmentType is from the same module * Switches all type signatures to T[] syntax * Updates wording to "experiments and/or rollouts" Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 7b1cf42 commit 93fdf4c

2 files changed

Lines changed: 98 additions & 16 deletions

File tree

docs/platform-guides/desktop/feature-api.mdx

Lines changed: 67 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,16 @@ After adding the feature a build step is required to update the appropriate head
7575
# Our feature name
7676
aboutwelcome:
7777
description: The about:welcome page
78+
owner: user@mozilla.com
79+
hasExposure: true
80+
exposureDescription: >
81+
Recorded when the about:welcome page is first shown to the user.
7882
# Include this if you need synchronous access / very early access at startup
7983
# or if you are registering this to use for platform experiments.
8084
isEarlyStartup: true
85+
# Set to true to allow a client to be enrolled in multiple experiments/rollouts
86+
# for this feature simultaneously. See "Co-enrolling Features" docs.
87+
# allowCoenrollment: false
8188
variables:
8289
# Additional (optional) values that we can control
8390
# The name of these variables is up to you
@@ -216,6 +223,10 @@ NimbusFeatures.myFeature.recordExposureEvent();
216223

217224
// Only sends once per session, even if this function is called multiple times
218225
NimbusFeatures.myFeature.recordExposureEvent({ once: true });
226+
227+
// For co-enrolling features, you must specify which enrollment to record exposure for:
228+
NimbusFeatures.myFeature.recordExposureEvent({ slug: "experiment-slug" });
229+
NimbusFeatures.myFeature.recordExposureEvent({ once: true, slug: "experiment-slug" });
219230
```
220231

221232
</TabItem>
@@ -305,7 +316,7 @@ NimbusFeatures::OnUpdate("aboutwelcome"_ns, "skipFocus"_ns,
305316
</TabItem>
306317
</Tabs>
307318
308-
### `off()`
319+
### `offUpdate()`
309320
310321
Stop listening for changes.
311322
@@ -342,25 +353,67 @@ NimbusFeatures::OffUpdate("aboutwelcome"_ns, "skipFocus"_ns,
342353
</TabItem>
343354
</Tabs>
344355
345-
## Experiment Metadata
356+
### `getEnrollmentMetadata()`
346357
347-
If you need to know whether an experiment is active or get access to the experiment or branch identifier (for example, to report in `utm_params`), you can use `ExperimentAPI.getExperimentMetaData`:
358+
`getEnrollmentMetadata(enrollmentType?: EnrollmentType): { slug: string, branch: string, isRollout: boolean } | null` (JS Only)
348359
349-
```js
350-
const lazy = {}
351-
ChromeUtils.defineESModuleGetters(lazy, {
352-
NimbusFeatures: "resource://nimbus/ExperimentAPI.sys.mjs",
353-
});
360+
Returns metadata about the active enrollment for this feature, or `null` if there is no active enrollment.
354361
355-
const data = lazy.ExperimentAPI.getExperimentMetaData({ featureId: "myFeature" });
362+
The optional `enrollmentType` parameter controls what kind of enrollment to look for:
356363
357-
// If there is no experiment, data will be null.
358-
const slug = data?.slug;
359-
const branchSlug = data?.branch?.slug;
364+
- **No argument** (default) — returns the active experiment if one exists, otherwise falls back to the active rollout.
365+
- **`EnrollmentType.EXPERIMENT`** — returns only an active experiment enrollment, or `null`.
366+
- **`EnrollmentType.ROLLOUT`** — returns only an active rollout enrollment, or `null`.
367+
368+
```js
369+
// EnrollmentType is exported from the same module as NimbusFeatures:
370+
// ChromeUtils.defineESModuleGetters(lazy, {
371+
// EnrollmentType: "resource://nimbus/ExperimentAPI.sys.mjs",
372+
// });
360373
361-
if (experimentSlug && branchSlug) {
374+
const data = NimbusFeatures.myFeature.getEnrollmentMetadata();
375+
376+
// If there is no enrollment, data will be null.
377+
if (data) {
362378
sendSomeTelemetry(
363-
`The experiment identifier is ${slug} and the branch identifier is ${branchSlug}`,
379+
`Enrolled in ${data.slug}, branch: ${data.branch}, isRollout: ${data.isRollout}`,
364380
);
365381
}
382+
383+
// Query for a specific enrollment type:
384+
const rollout = NimbusFeatures.myFeature.getEnrollmentMetadata(lazy.EnrollmentType.ROLLOUT);
385+
```
386+
387+
:::note
388+
This method throws for [co-enrolling features](/technical-reference/fml/coenrolling-features). Use `getAllEnrollmentMetadata()` instead.
389+
:::
390+
391+
### `getAllEnrollments()`
392+
393+
`getAllEnrollments(): { meta: { slug, branch, isRollout }, value: object }[]` (JS Only)
394+
395+
Returns an array of all active enrollments for this feature, each with metadata and the resolved feature variable values. This is the primary data access method for [co-enrolling features](/technical-reference/fml/coenrolling-features) where a client may be enrolled in multiple experiments and/or rollouts for the same feature simultaneously.
396+
397+
For non-co-enrolling features, this also works but will return at most two entries (one experiment and one rollout).
398+
399+
```js
400+
const enrollments = NimbusFeatures.myFeature.getAllEnrollments();
401+
402+
for (const { meta, value } of enrollments) {
403+
console.log(`${meta.slug} (branch: ${meta.branch}):`, value);
404+
}
405+
```
406+
407+
### `getAllEnrollmentMetadata()`
408+
409+
`getAllEnrollmentMetadata(): { slug: string, branch: string, isRollout: boolean }[]` (JS Only)
410+
411+
Returns metadata for all active enrollments for this feature, without the resolved feature values. Use this when you only need enrollment identifiers (e.g., for telemetry) and not the feature configuration.
412+
413+
```js
414+
const enrollments = NimbusFeatures.myFeature.getAllEnrollmentMetadata();
415+
416+
for (const { slug, branch, isRollout } of enrollments) {
417+
sendSomeTelemetry(`Enrolled in ${slug}, branch: ${branch}`);
418+
}
366419
```

docs/technical-reference/fml/coenrolling-features.mdx

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@ A feature which allows co-enrollment allows a client to be enrolled in any numbe
1010
**Features supporting co-enrollment**
1111

1212
* [Messaging](/messaging/desktop/mobile-messaging) (Fenix, Firefox iOS, Focus for Android, Focus for iOS)
13+
* Firefox Desktop — any feature with `allowCoenrollment: true` in [FeatureManifest.yaml](https://searchfox.org/mozilla-central/source/toolkit/components/nimbus/FeatureManifest.yaml) (e.g., `prefFlips`)
1314

1415
## How to define a co-enrolling feature
1516

16-
A feature can be marked as allowing co-enrollment with a boolean flag in its feature definition in a Feature Manifest. For example, in your `messaging.fml.yaml` file:
17+
A feature can be marked as allowing co-enrollment with a boolean flag in its feature definition in a Feature Manifest.
18+
19+
**Mobile (FML):** In your `.fml.yaml` file:
1720

1821
```yaml
1922
features:
@@ -28,7 +31,18 @@ features:
2831
default: {}
2932
```
3033
31-
Once your messaging feature is defined as a co-enrolling feature, a client can be enrolled in any number of messaging experiments/rollouts.
34+
**Desktop:** In `FeatureManifest.yaml`:
35+
36+
```yaml
37+
prefFlips:
38+
description: Pref flips for incident response
39+
allowCoenrollment: true
40+
variables:
41+
prefs:
42+
type: json
43+
```
44+
45+
Once your feature is defined as a co-enrolling feature, a client can be enrolled in any number of experiments/rollouts for that feature.
3246

3347
## Recording exposure
3448

@@ -56,6 +70,21 @@ val slug = message.data.experiment ?: return message
5670
messagingFeature.recordExperimentExposure(slug)
5771
```
5872

73+
### Desktop
74+
75+
On Desktop, co-enrolling features use the `{slug}` option on `recordExposureEvent()`:
76+
77+
```js
78+
NimbusFeatures.myFeature.recordExposureEvent({ slug: "experiment-slug" });
79+
```
80+
81+
Standard per-feature methods like `getVariable()` and `getAllVariables()` throw for co-enrolling features. Instead, use these APIs:
82+
83+
- **`getAllEnrollments()`** — returns `{ meta: { slug, branch, isRollout }, value: object }[]` with both metadata and resolved feature values for each enrollment.
84+
- **`getAllEnrollmentMetadata()`** — returns `{ slug, branch, isRollout }[]` (metadata only).
85+
86+
See the [Desktop Feature API reference](/platform-guides/desktop/feature-api) for full details.
87+
5988
## Other things to note about co-enrollment
6089

6190
* Experiment feature values still take precedence over rollout feature values

0 commit comments

Comments
 (0)