Population Sizing
Population sizing can be estimated using targeting context metrics available for Firefox on Desktop, iOS, and Android. Fields needed to translate Advanced Targeting expressions may not be fully available for all platforms.
This page covers how to estimate the number of clients that match a particular targeting expression, not how to decide how many enrolled clients an experiment might need.
Accuracy
Population sizing accuracy of the queries below was investigated in EXP-6101, and the (estimated population from preceding week)/(observed population) ratios were in the following ranges for recent experiments run on Firefox versions that had been out for at least one week:
- Desktop: 0.9-1.3, average 1.163
- Android: 1.02-1.21, average 1.136
- iOS: 1.35-1.53, average 1.448
This means that Desktop estimates were up to +30% larger than observed enrollments, Android estimates were up to 21% larger than observed enrollments, iOS estimates were up to 53% larger than observed enrollments, so estimates may need to be adjusted accordingly to ensure sufficient minimum populations.
Estimating for Desktop
The following query can be used to estimate available population for Firefox Desktop, if not using Redash then {{ sql_targeting_expression }} should be replaced with the actual sql expression:
SELECT
COUNT(DISTINCT metrics.uuid.legacy_telemetry_profile_group_id) AS available_weekly_population,
FROM
`mozdata.firefox_desktop.nimbus_targeting_context`
WHERE
DATE(submission_timestamp) BETWEEN CURRENT_DATE - 7 AND CURRENT_DATE - 1
AND ({{ sql_targeting_expression }})
This is available as a templated query in Redash: https://sql.telemetry.mozilla.org/queries/112917?p_sql_targeting_expression=TRUE
Translating Desktop Targeting Expressions from JEXL to SQL
To determine the SQL targeting expression for a given experiment, first get the full targeting expression from the Audience section, which is in JEXL format. A simple targeting expression might look like this:
(browserSettings.update.channel in ["release"]) && (version|versionCompare('140.!') >= 0) && (locale in ['en-CA', 'en-GB', 'en-US']) && (region == 'US')
Translating one condition at a time:
browserSettings.update.channelis available asnormalized_channel, sobrowserSettings.update.channel in ["release"]could be translated asnormalized_channel = "release"- When comparing only the major version, it's available as
metrics.quantity.nimbus_targeting_context_firefox_version, so(version|versionCompare('140.!') >= 0)could be translated asmetrics.quantity.nimbus_targeting_context_firefox_version >= 140- The full version is available as
metrics.string.nimbus_targeting_context_version, so it could alternatively be translated asmozfun.norm.extract_version(metrics.string.nimbus_targeting_context_version, "major") >= 140
- The full version is available as
localeis available asmetrics.string.nimbus_targeting_context_locale, and[]should be converted to()for BigQuery SQLINexpressions, solocale in ['en-CA', 'en-GB', 'en-US']could be translated asmetrics.string.nimbus_targeting_context_locale IN ('en-CA', 'en-GB', 'en-US')- region is available as
metrics.string.nimbus_targeting_context_region, and SQL uses a single=for equality comparison, soregion == 'US'could be translated asmetrics.string.nimbus_targeting_context_region = 'US' ==,&&,||, and!translate to=,AND,OR, andNOTrespectively
So the SQL version of the targeting expression for Desktop could be:
(normalized_channel = "release")
AND (metrics.quantity.nimbus_targeting_context_firefox_version >= 140)
AND (metrics.string.nimbus_targeting_context_locale IN ('en-CA', 'en-GB', 'en-US'))
AND (metrics.string.nimbus_targeting_context_region = 'US')
NOT has a different operator precedence in BigQuery than ! in JEXL, so NOT should always be used inside a () with a single expression for clarity. For example !isMac && isFxAEnabled must be translated as (NOT BOOL(metrics.object.nimbus_targeting_context_os.isMac)) AND metrics.boolean.nimbus_targeting_context_is_fx_a_enabled
The Glean dictionary can be searched for available fields in Firefox Desktop
Estimating for Firefox on Android and iOS
The following queries can be used to estimate available population for release channel experiments on Android and iOS, if not using Redash then {{ sql_targeting_expression }} should be replaced with the actual sql expression:
For Android release channel:
SELECT
COUNT(DISTINCT client_info.client_id) AS available_weekly_population,
FROM
`mozdata.fenix.nimbus`
WHERE
DATE(submission_timestamp) BETWEEN CURRENT_DATE - 7 AND CURRENT_DATE - 1
AND ({{ sql_targeting_expression }})
For iOS release the table is mozdata.firefox_ios.nimbus:
SELECT
COUNT(DISTINCT client_info.client_id) AS available_weekly_population,
FROM
`mozdata.firefox_ios.nimbus`
WHERE
DATE(submission_timestamp) BETWEEN CURRENT_DATE - 7 AND CURRENT_DATE - 1
AND ({{ sql_targeting_expression }})
Translating Android and iOS Targeting Expressions from JEXL to SQL
To determine the SQL targeting expression for a given experiment, first get the full targeting expression from the Audience section, which is in JEXL format. A simple targeting expression might look like this:
((is_already_enrolled) || ((isFirstRun == 'true') && (app_version|versionCompare('146.!') >= 0)))
Firefox for Android and iOS have the targeting context available through the JSON field metrics.object.nimbus_system_recorded_nimbus_context, and can be converted into SQL types using BigQuery JSON functions, especially the converters BOOL, FLOAT64, INT64, and STRING, the LAZY_ prefixed lax converts, and JSON_QUERY_ARRAY and JSON_VALUE_ARRAY which return ARRAY<JSON> and ARRAY<STRING> respectively.
As of Firefox for Android 146 and Firefox for iOS 145 object keys are snake_case, but before that they were camelCase due to Bug 1931891.
Translating one condition at a time:
is_already_enrolledshould be omittedisFirstRuncould be translated asBOOL(metrics.object.nimbus_system_recorded_nimbus_context.is_first_run)app_version|versionCompare('146.!') >= 0could be translated asmozfun.norm.extract_version(STRING(metrics.object.nimbus_system_recorded_nimbus_context.appVersion), "major") >= 146
So the SQL version of the targeting expression could be:
BOOL(metrics.object.nimbus_system_recorded_nimbus_context.is_first_run)
AND mozfun.norm.extract_version(STRING(metrics.object.nimbus_system_recorded_nimbus_context.app_version), "major") >= 146
NOT has a different operator precedence in BigQuery than ! in JEXL, so NOT should always be used inside a () with a single expression for clarity. For example !isMac && isFxAEnabled must be translated as (NOT BOOL(metrics.object.nimbus_targeting_context_os.isMac)) AND metrics.boolean.nimbus_targeting_context_is_fx_a_enabled
The Glean dictionary contains additional info about the nimbus_system.recorded_nimbus_context metric in Firefox for Android and in Firefox for iOS. The Source link on those pages leads to the metric definition in metrics.yaml, which includes a JSONSchema definition of available object keys and types.