Appearance
Passing Firefox add-on review with analytics
Firefox's add-on store, addons.mozilla.org, reviews extensions against Mozilla's add-on policies, and analytics touches several of them at once: no remote code, reviewable source, and consent for data collection. Since Firefox 140 there is also a built-in consent system that new extensions must declare in their manifest. This article covers what an extension that sends analytics needs to get through review.
This is not legal advice. Policies and review practice change, so check each point against Mozilla's current documentation before you submit.
No remote code
Mozilla's policies say add-ons "must be self-contained and not load remote code for execution" (Mozilla: add-on policies). An analytics snippet that fetches its script from a provider's server is remote code. Bundle the analytics library into the extension, or send plain HTTP requests from your own bundled code. What leaves the extension is data; what runs is only the code in the package.
Reviewable source
Most extensions today are built with a bundler, a minifier or a transpiler. Mozilla needs to review "a copy of the source code before any of these steps have been applied", and allows minification but not obfuscation (Mozilla: add-on policies).
When your extension's code was produced by a minifier, a bundler such as webpack or one that "generate[s] a single file from other files", a template engine or another custom tool, you must upload the source as well (Mozilla: source code submission). The reviewer follows your build instructions and compares the result with the package: "There must be no differences." In practice that means:
- the source, including your analytics library's configuration;
- a lockfile, so dependencies resolve to the same versions;
- written steps that rebuild the package, using open-source tools that run locally;
- the versions of Node and npm you build with.
An analytics library you install from npm is fine here: it is a dependency the lockfile pins, and the reviewer can read it.
Declare data collection in the manifest
Firefox has built-in consent for data collection. Extensions declare what they collect in browser_specific_settings.gecko.data_collection_permissions, and Firefox shows it to the user at install. It is supported in Firefox for desktop 140 and Firefox for Android 142 and later, and "from November 3, 2025, all new extensions must adopt the Firefox built-in data collection consent system" (Mozilla: built-in data consent).
The declaration has two lists:
required: data the extension cannot work without. The user accepts these to install.optional: data the user may turn on or off.
An extension that collects nothing declares the none required permission.
Analytics about how the extension is used falls under technicalAndInteraction, which Mozilla treats differently: it "cannot be required", and the user can turn it on or off during installation. So usage analytics always goes in optional:
json
{
"browser_specific_settings": {
"gecko": {
"id": "my-extension@example.com",
"strict_min_version": "140.0",
"data_collection_permissions": {
"required": ["none"],
"optional": ["technicalAndInteraction"]
}
}
}
}If your analytics also works out a location from the IP address, locationInfo belongs in the declaration too. Declaring it optional lets the user keep analytics on while declining location.
Set strict_min_version to 140.0 when you rely on the built-in consent, because older Firefox versions do not show it.
Respect the answer
Declaring the data is half of it; the extension must then behave as the user chose. Because technicalAndInteraction is always optional, some users will decline it, and your extension must work without sending analytics.
- Check before every send. The user can change the choice later in the add-on's permissions, not only at install. Read it before sending, not once at startup.
- Send nothing when it is off. No events, no identifier created, and no uninstall address that reports the removal.
- Do the same for location. If
locationInfois declined, do not work out a location.
For extensions that support Firefox 139 or earlier, Mozilla's policy asks instead for consent shown immediately after installation, in an interface the user cannot miss, before any personal data is sent.
The listing and the privacy policy
Describe what you collect in the listing as well. Mozilla's policies expect the data practice to be disclosed to users, and reviewers compare the listing, the manifest declaration and the code. Keep all three saying the same thing, and link a privacy policy that agrees with them.
A checklist before you submit
- No code loaded from outside the package.
- Source, lockfile and build steps uploaded if the code is bundled or minified.
data_collection_permissionsdeclared, withtechnicalAndInteractioninoptional.strict_min_versionof 140.0 or later if you rely on built-in consent.- The extension sends nothing when analytics is declined, and no location when location is declined.
- The listing, the manifest and the privacy policy agree.
Common questions
Can I make analytics required?
No. technicalAndInteraction cannot be required. If your extension cannot work without sending usage data, that is a sign the data is doing more than analytics, and it needs a different category and a clear reason.
What environment does the reviewer build in?
Mozilla's source submission guide describes its default reviewer environment: Ubuntu 24.04 LTS with Node 24.14.0 and npm 11.9.0, 10 GB of memory and 35 GB of disk. If your build needs something else, say so in your instructions, with exact versions.
Do I still need my own consent screen?
Not for Firefox 140 and later when you rely on the built-in consent: Firefox asks at install and lets the user change the answer. If you also support Firefox 139 or earlier, those versions need the consent screen Mozilla's policy describes, shown right after installation.
What if the reviewer finds code I did not declare?
Expect questions or a rejection. The usual cause is a library that sends data you did not know about, such as a crash reporter or a feature-flag service. Check what every dependency sends before you declare anything.
Does analytics sent from an options page or popup count?
Yes. The declaration covers everything the extension sends, wherever in the extension the code runs. Sending from the background is still the better design, because it is the one place that can queue events and check the user's choice consistently, but the obligation is the same for every page of the extension.
How AnalyticsTrend does it
AnalyticsTrend's extension SDK is an npm package bundled into your extension, so there is no remote code and the reviewer reads it with the rest of your source. It reads Firefox's built-in consent before every event and every send: with technicalAndInteraction declined it sends nothing, creates no identifier and clears the uninstall address, and with locationInfo declined it marks each batch so no country or region is worked out. The same checks honour Global Privacy Control and an on/off switch of your own.
The manifest block it needs, and the details, are in Install in a Firefox extension. What it collects is in What it collects. The free store disclosure helper gives the data_collection_permissions block for any extension, whatever analytics it uses. For the Chrome side, see What to declare on the Chrome Web Store privacy practices tab.
Checked against Mozilla's documentation on 7 October 2026.