Repository: mozilla-mobile/firefox-ios
Pull request #25569: Add undo toast telemetry
Author: login: Cramsden
Created: 2025-03-26T12:50:23Z | Merged: 2025-03-31T14:11:50Z

## :scroll: Tickets
[Jira ticket](https://mozilla-hub.atlassian.net/browse/FXIOS-11714)
[Github issue](https://github.com/mozilla-mobile/firefox-ios/issues/25534)

## :bulb: Description
<!--- Describe your changes so the reviewer can understand the context and decisions made for your work -->
Add telemetry for undo after tab deletion. Since undo is a toast we will namespace it under toasts and add `ToastTelemetry` to hold toast glean calls.

## :pencil: Checklist
You have to check all boxes before merging
- [ ] Filled in the above information (tickets numbers and description of your work)
- [ ] Updated the PR name to follow our [PR naming guidelines](https://github.com/mozilla-mobile/firefox-ios/wiki/Pull-Request-Naming-Guide)
- [ ] Wrote unit tests and/or ensured the tests suite is passing
- [ ] When working on UI, I checked and implemented accessibility (minimum Dynamic Text and VoiceOver)
- [ ] If needed, I updated documentation / comments for complex code and public methods
- [ ] If needed, added a backport comment (example `@Mergifyio backport release/v120`)




Diff:
diff --git a/firefox-ios/Client.xcodeproj/project.pbxproj b/firefox-ios/Client.xcodeproj/project.pbxproj
index 6e8e522a2ee33..c4f1a423d3706 100644
--- a/firefox-ios/Client.xcodeproj/project.pbxproj
+++ b/firefox-ios/Client.xcodeproj/project.pbxproj
@@ -668,6 +668,8 @@
 		612194E32CE507CF001664BB /* WallpaperBackgroundView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 612194E22CE507CF001664BB /* WallpaperBackgroundView.swift */; };
 		612194E62CE50A93001664BB /* WallpaperAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 612194E52CE50A93001664BB /* WallpaperAction.swift */; };
 		612194E82CE50A9B001664BB /* WallpaperState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 612194E72CE50A9B001664BB /* WallpaperState.swift */; };
+		613489A32D942A020009AF01 /* ToastTelemetry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 613489A22D942A020009AF01 /* ToastTelemetry.swift */; };
+		613489A52D9443610009AF01 /* ToastTelemetryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 613489A42D9443610009AF01 /* ToastTelemetryTests.swift */; };
 		615532D42D7AA5F30046347F /* ScreenshotHelperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 615532D32D7AA5F30046347F /* ScreenshotHelperTests.swift */; };
 		619FE8932CE6595B004F83E2 /* WallpaperMiddleware.swift in Sources */ = {isa = PBXBuildFile; fileRef = 619FE8922CE6595B004F83E2 /* WallpaperMiddleware.swift */; };
 		61A164492CE7BE84001D6058 /* WallpaperStateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61A164452CE7BE1A001D6058 /* WallpaperStateTests.swift */; };
@@ -7682,6 +7684,8 @@
 		612194E22CE507CF001664BB /* WallpaperBackgroundView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WallpaperBackgroundView.swift; sourceTree = "<group>"; };
 		612194E52CE50A93001664BB /* WallpaperAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WallpaperAction.swift; sourceTree = "<group>"; };
 		612194E72CE50A9B001664BB /* WallpaperState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WallpaperState.swift; sourceTree = "<group>"; };
+		613489A22D942A020009AF01 /* ToastTelemetry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToastTelemetry.swift; sourceTree = "<group>"; };
+		613489A42D9443610009AF01 /* ToastTelemetryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToastTelemetryTests.swift; sourceTree = "<group>"; };
 		615532D32D7AA5F30046347F /* ScreenshotHelperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenshotHelperTests.swift; sourceTree = "<group>"; };
 		619FE8922CE6595B004F83E2 /* WallpaperMiddleware.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WallpaperMiddleware.swift; sourceTree = "<group>"; };
 		61A164452CE7BE1A001D6058 /* WallpaperStateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WallpaperStateTests.swift; sourceTree = "<group>"; };
@@ -12802,6 +12806,7 @@
 				0ABCD45C2D356006005D704A /* TermsOfServiceTelemetryTests.swift */,
 				8AC225642B6D3FA400CDA7FD /* HomepageTelemetryTests.swift */,
 				0A686B3B2CDB70DC0090E146 /* MainMenuTelemetryTests.swift */,
+				613489A42D9443610009AF01 /* ToastTelemetryTests.swift */,
 			);
 			path = Telemetry;
 			sourceTree = "<group>";
@@ -14882,6 +14887,7 @@
 				1DD4B26D2CA4D09100B51945 /* TabErrorTelemetryHelper.swift */,
 				8A0727452B4890B50071BB9F /* WebviewTelemetry.swift */,
 				8A359EF42A1FD4CF004A5BB7 /* Wrapper */,
+				613489A22D942A020009AF01 /* ToastTelemetry.swift */,
 			);
 			path = Telemetry;
 			sourceTree = "<group>";
@@ -17822,6 +17828,7 @@
 				C4E3984C1D21F2FD004E89BA /* TabTrayButtonExtensions.swift in Sources */,
 				ED07C0E62CCACD7E006C0627 /* Locale+possibilitiesForLanguageIdentifier.swift in Sources */,
 				437A857827E43FE100E42764 /* FxAWebViewTelemetry.swift in Sources */,
+				613489A32D942A020009AF01 /* ToastTelemetry.swift in Sources */,
 				E13E9AB42AAB0FB5001A0E9D /* FakespotCoordinator.swift in Sources */,
 				E1442FD1294782D9003680B0 /* UIModalPresentationStyle+Photon.swift in Sources */,
 				21EEAA1D2D4005DE00595119 /* NativeErrorPageFeatureFlag.swift in Sources */,
@@ -18321,6 +18328,7 @@
 				0B7B05432D64C08F007FD7AC /* MockURLProtocol.swift in Sources */,
 				8ADAFAC628AEBF6300FFEBE3 /* HomeLogoHeaderViewModelTests.swift in Sources */,
 				E1EAA5EF2D49182700D3039C /* NavigationBarStateTests.swift in Sources */,
+				613489A52D9443610009AF01 /* ToastTelemetryTests.swift in Sources */,
 				8A75F1B828B558E20054E34D /* MessageCardDataAdaptorImplementationTests.swift in Sources */,
 				E14BF33E2950B1230039758D /* MailProvidersTests.swift in Sources */,
 				C889D7CE2858C4B500121E1D /* ContextMenuHelperTests.swift in Sources */,
diff --git a/firefox-ios/Client/Frontend/Browser/Tabs/Middleware/TabManagerMiddleware.swift b/firefox-ios/Client/Frontend/Browser/Tabs/Middleware/TabManagerMiddleware.swift
index ac894f3453386..128ae5bc0b5a4 100644
--- a/firefox-ios/Client/Frontend/Browser/Tabs/Middleware/TabManagerMiddleware.swift
+++ b/firefox-ios/Client/Frontend/Browser/Tabs/Middleware/TabManagerMiddleware.swift
@@ -15,6 +15,7 @@ class TabManagerMiddleware: BookmarksRefactorFeatureFlagProvider,
     private let logger: Logger
     private let inactiveTabTelemetry = InactiveTabsTelemetry()
     private let bookmarksSaver: BookmarksSaver
+    private let toastTelemetry: ToastTelemetry
 
     private var isTabTrayUIExperimentsEnabled: Bool {
         return featureFlags.isFeatureEnabled(.tabTrayUIExperiments, checking: .buildOnly)
@@ -23,11 +24,13 @@ class TabManagerMiddleware: BookmarksRefactorFeatureFlagProvider,
 
     init(profile: Profile = AppContainer.shared.resolve(),
          logger: Logger = DefaultLogger.shared,
-         bookmarksSaver: BookmarksSaver? = nil
+         bookmarksSaver: BookmarksSaver? = nil,
+         gleanWrapper: GleanWrapper = DefaultGleanWrapper()
     ) {
         self.profile = profile
         self.logger = logger
         self.bookmarksSaver = bookmarksSaver ?? DefaultBookmarksSaver(profile: profile)
+        self.toastTelemetry = ToastTelemetry(gleanWrapper: gleanWrapper)
     }
 
     lazy var tabsPanelProvider: Middleware<AppState> = { state, action in
@@ -458,6 +461,7 @@ class TabManagerMiddleware: BookmarksRefactorFeatureFlagProvider,
 
     /// Handles undoing the close tab action, gets the backup tab from `TabManager`
     private func undoCloseTab(state: AppState, uuid: WindowUUID) {
+        toastTelemetry.undoClosedSingleTab()
         let tabManager = tabManager(for: uuid)
         guard let tabsState = state.screenState(TabsPanelState.self, for: .tabsPanel, window: uuid),
               tabManager.backupCloseTab != nil
@@ -531,6 +535,7 @@ class TabManagerMiddleware: BookmarksRefactorFeatureFlagProvider,
     }
 
     private func undoCloseAllTabs(uuid: WindowUUID) {
+        toastTelemetry.undoClosedAllTabs()
         let tabManager = tabManager(for: uuid)
         tabManager.undoCloseAllTabs()
 
diff --git a/firefox-ios/Client/Telemetry/ToastTelemetry.swift b/firefox-ios/Client/Telemetry/ToastTelemetry.swift
new file mode 100644
index 0000000000000..2b2e7a5f649a0
--- /dev/null
+++ b/firefox-ios/Client/Telemetry/ToastTelemetry.swift
@@ -0,0 +1,22 @@
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/
+
+import Foundation
+import Glean
+
+struct ToastTelemetry {
+    private let gleanWrapper: GleanWrapper
+
+    init(gleanWrapper: GleanWrapper = DefaultGleanWrapper()) {
+        self.gleanWrapper = gleanWrapper
+    }
+
+    func undoClosedSingleTab() {
+        gleanWrapper.recordEvent(for: GleanMetrics.ToastsCloseSingleTab.undoTapped)
+    }
+
+    func undoClosedAllTabs() {
+        gleanWrapper.recordEvent(for: GleanMetrics.ToastsCloseAllTabs.undoTapped)
+    }
+}
diff --git a/firefox-ios/Client/metrics.yaml b/firefox-ios/Client/metrics.yaml
index 3c35affbfb119..4e40e6ec78669 100755
--- a/firefox-ios/Client/metrics.yaml
+++ b/firefox-ios/Client/metrics.yaml
@@ -4387,6 +4387,41 @@ tabs:
       - fx-ios-data-stewards@mozilla.com
     expires: never
 
+# Toasts
+toasts.close_single_tab:
+  undo_tapped:
+    type: event
+    description: | 
+      Records when the user selects undo after closing a tab.
+    bugs:
+      - https://mozilla-hub.atlassian.net/browse/FXIOS-11714
+    data_reviews:
+      - https://github.com/mozilla-mobile/firefox-ios/pull/25569
+    notification_emails:
+      - fx-ios-data-stewards@mozilla.com
+    expires: "2025-06-01"
+    metadata:
+      tags:
+        - Toasts
+        - TabsPanel
+
+toasts.close_all_tabs:
+  undo_tapped:
+    type: event
+    description: | 
+      Records when the user selects undo after closing all tabs.
+    bugs:
+      - https://mozilla-hub.atlassian.net/browse/FXIOS-11714
+    data_reviews:
+      - https://github.com/mozilla-mobile/firefox-ios/pull/25569
+    notification_emails:
+      - fx-ios-data-stewards@mozilla.com
+    expires: "2025-06-01"
+    metadata:
+      tags:
+        - Toasts
+        - TabsPanel
+  
 # Enhanced Tracking Protection metrics
 tracking_protection:
   enabled:
diff --git a/firefox-ios/Client/tags.yaml b/firefox-ios/Client/tags.yaml
index d0699babccdab..65b9ec007428f 100644
--- a/firefox-ios/Client/tags.yaml
+++ b/firefox-ios/Client/tags.yaml
@@ -20,3 +20,10 @@ Settings:
 TopSites:
   description: Corresponds to the [Feature:TopSites](https://mozilla-hub.atlassian.net/browse/FXIOS-3464)
     label on GitHub.
+  
+TabsPanel:
+  description: Corresponds to all things related to the tab panel.
+
+Toasts:
+  description: Corresponds to any events around toasts in the app. Toasts are the shortlived banners that 
+    appear when an action is taken.
diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Telemetry/ToastTelemetryTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Telemetry/ToastTelemetryTests.swift
new file mode 100644
index 0000000000000..72be153fc8f2e
--- /dev/null
+++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Telemetry/ToastTelemetryTests.swift
@@ -0,0 +1,56 @@
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/
+
+import Foundation
+import Glean
+import XCTest
+
+@testable import Client
+
+final class ToastTelemetryTests: XCTestCase {
+    var mockGleanWrapper: MockGleanWrapper!
+    override func setUp() {
+        super.setUp()
+
+        mockGleanWrapper = MockGleanWrapper()
+    }
+
+    func testClosedSingleTabToastUndoSelected_callsGlean() throws {
+        let event = GleanMetrics.ToastsCloseSingleTab.undoTapped
+        let expectedMetricType = type(of: event)
+        let subject = createSubject()
+
+        subject.undoClosedSingleTab()
+
+        let savedMetric = try XCTUnwrap(
+            mockGleanWrapper.savedEvents?.first as? EventMetricType<NoExtras>
+        )
+        let resultMetricType = type(of: savedMetric)
+        let debugMessage = TelemetryDebugMessage(expectedMetric: expectedMetricType, resultMetric: resultMetricType)
+
+        XCTAssertEqual(mockGleanWrapper.recordEventNoExtraCalled, 1)
+        XCTAssert(resultMetricType == expectedMetricType, debugMessage.text)
+    }
+
+    func testClosedAllTabsToastUndoSelected_callsGlean() throws {
+        let event = GleanMetrics.ToastsCloseAllTabs.undoTapped
+        let expectedMetricType = type(of: event)
+        let subject = createSubject()
+
+        subject.undoClosedAllTabs()
+
+        let savedMetric = try XCTUnwrap(
+            mockGleanWrapper.savedEvents?.first as? EventMetricType<NoExtras>
+        )
+        let resultMetricType = type(of: savedMetric)
+        let debugMessage = TelemetryDebugMessage(expectedMetric: expectedMetricType, resultMetric: resultMetricType)
+
+        XCTAssertEqual(mockGleanWrapper.recordEventNoExtraCalled, 1)
+        XCTAssert(resultMetricType == expectedMetricType, debugMessage.text)
+    }
+
+    func createSubject() -> ToastTelemetry {
+        return ToastTelemetry(gleanWrapper: mockGleanWrapper)
+    }
+}


Reviews:
user: login: adudenamedruby
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-27T13:07:53Z
user: login: ih-codes
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-27T16:32:20Z
user: login: ih-codes
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-27T16:48:08Z
user: login: ih-codes
body: Approving so I don't hold you up!
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-03-27T21:42:52Z
user: login: dataports
body: LGTM 🚢 
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-27T22:25:22Z

Review comments:
diff_hunk: @@ -4387,6 +4387,41 @@ tabs:
       - fx-ios-data-stewards@mozilla.com
     expires: never
 
+# Toasts
+toasts.close_single_tab:
path: firefox-ios/Client/metrics.yaml
user: login: adudenamedruby
body: I've not seen this format before in our `metrics.yaml` file. @ih-codes Given that you're taking on telemetry, is this a format we want to move towards? I'm fine either way, I just want consistency. :D
created_at: 2025-03-27T13:07:52Z
author_association: CONTRIBUTOR
diff_hunk: @@ -4387,6 +4387,41 @@ tabs:
       - fx-ios-data-stewards@mozilla.com
     expires: never
 
+# Toasts
+toasts.close_single_tab:
path: firefox-ios/Client/metrics.yaml
user: login: ih-codes
body: Yes, we are looking to have more specific namespacing. I was working with @Cramsden on this yesterday. I will have a naming proposal document ready for the team by next week that goes into this more. (The glean team suggested this was the only way we could add more dots to our probe names from a technical point of view).
created_at: 2025-03-27T16:32:20Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,22 @@
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/
+
+import Foundation
+import Glean
+
+struct ToastTelemetry {
+    private let gleanWrapper: GleanWrapper
+
+    init(gleanWrapper: GleanWrapper = DefaultGleanWrapper()) {
+        self.gleanWrapper = gleanWrapper
+    }
+
+    func closedSingleTabToastUndoSelected() {
path: firefox-ios/Client/Telemetry/ToastTelemetry.swift
user: login: ih-codes
body: Hm, I think the function naming in this file could be a little simpler e.g. `toastTelemetry.undoClosedSingleTab()` vs. referencing the probe namespace. As in, "undoClosedSingleTab" is the user action for which we record 1+ events as needed. What do you think? 🤔 (this is a nit though since I know this will be very temporary telemetry) 
created_at: 2025-03-27T16:39:46Z
author_association: COLLABORATOR
diff_hunk: @@ -4387,6 +4387,41 @@ tabs:
       - fx-ios-data-stewards@mozilla.com
     expires: never
 
+# Toasts
+toasts.close_single_tab:
+  undo_selected:
path: firefox-ios/Client/metrics.yaml
user: login: ih-codes
body: Still working on the naming proposal, which I'll be going over with Andy later today. We may want to tweak the `selected` terminology, but I'm not sure yet. We'll want to define when we use "tapped" vs. "selected". DM me if you have any thoughts here... 🤔 
created_at: 2025-03-27T16:43:58Z
author_association: COLLABORATOR
diff_hunk: @@ -20,3 +20,10 @@ Settings:
 TopSites:
   description: Corresponds to the [Feature:TopSites](https://mozilla-hub.atlassian.net/browse/FXIOS-3464)
     label on GitHub.
+  
+TabPanel:
path: firefox-ios/Client/tags.yaml
user: login: ih-codes
body: After talking to Andy, we both decided we should pluralize Tabs here, e.g. `TabsPanel` tag and `tabs_panel` namespace, to be consistent with other probes. Sorry for swapping on you lol.
```suggestion
TabsPanel:
```
created_at: 2025-03-27T16:45:45Z
author_association: COLLABORATOR
diff_hunk: @@ -20,3 +20,10 @@ Settings:
 TopSites:
   description: Corresponds to the [Feature:TopSites](https://mozilla-hub.atlassian.net/browse/FXIOS-3464)
     label on GitHub.
+  
+TabPanel:
+  description: Corresponds to all things related to all things related to the tab panel.
path: firefox-ios/Client/tags.yaml
user: login: ih-codes
body: ```suggestion
  description: Corresponds to all things related to the tabs panel.
```
created_at: 2025-03-27T16:46:40Z
author_association: COLLABORATOR
diff_hunk: @@ -20,3 +20,10 @@ Settings:
 TopSites:
   description: Corresponds to the [Feature:TopSites](https://mozilla-hub.atlassian.net/browse/FXIOS-3464)
     label on GitHub.
+  
+TabPanel:
+  description: Corresponds to all things related to all things related to the tab panel.
+
+Toasts:
+  description: Corresponds to any events around toasts in the app. Toasts are the shortlived banners that 
+    appear when an action is taken.
path: firefox-ios/Client/tags.yaml
user: login: ih-codes
body: Perfectly clear description 💯  Thanks!!
created_at: 2025-03-27T16:47:06Z
author_association: COLLABORATOR

PR comments:
user: login: mobiletest-ci-bot
created_at: 2025-03-26T13:00:45Z
body: 
<!--
  0 failure: 
  0 warning: 
  3 messages
  1 markdown notices
  DangerID: danger-id-Danger;
-->



<table>
  <thead>
    <tr>
      <th width="50"></th>
      <th width="100%" data-danger-table="true">Messages</th>
    </tr>
  </thead>
  <tbody><tr>
      <td>:book:</td>
      <td>Project coverage: 36.65%</td>
    </tr>
  
<tr>
      <td>:book:</td>
      <td>Edited 4 files</td>
    </tr>
  
<tr>
      <td>:book:</td>
      <td>Created 2 files</td>
    </tr>
  </tbody>
</table>

## Client.app: Coverage: 34.83
| File | Coverage ||
| --- | --- | --- |
TabManagerMiddleware.swift | 15.06% | ⚠️
ToastTelemetry.swift | 100.0% | ✅

<p align="right">
  Generated by :no_entry_sign: <a href="https://danger.systems/swift">Danger Swift</a> against 49e5f723de69f8e1b4e7f29ad7c2d7dcc3136779
</p>

author_association: NONE
user: login: Cramsden
created_at: 2025-03-26T14:13:27Z
body: # Request for data collection review form

**All questions are mandatory. You must receive review from a data steward peer on your responses to these questions before shipping new data collection.**

1) What questions will you answer with this data?

We want to know if users are actually using the undo feature after they have closed a tab. 

2) Why does Mozilla need to answer these questions?  Are there benefits for users? Do we need this information to address product or business requirements? Some example responses:

We will learn whether or not users are using this feature. If they are not, we can remove it and invest resources in other parts of the app. If they are, we can double down on fixing bugs in this code.

3) What alternative methods did you consider to answer these questions? Why were they not sufficient?

We looked at other browser options available and most do not provide an undo option. Since we don't get much feedback or reports from users on this feature we assume that it is not often used but this is just an assumption. We would like to be sure.

4) Can current instrumentation answer these questions?

No.

5) List all proposed measurements and indicate the category of data collection for each measurement, using the [Firefox data collection categories](https://wiki.mozilla.org/Data_Collection) found on the Mozilla wiki.   

**Note that the data steward reviewing your request will characterize your data collection based on the highest (and most sensitive) category.**

<table>
  <tr>
    <td>Measurement Description</td>
    <td>Data Collection Category</td>
    <td>Tracking Bug #</td>
  </tr>
  <tr>
    <td>toasts.close_single_tab.undo_selected</td>
    <td>2</td>
    <td>[FXIOS-11714](https://mozilla-hub.atlassian.net/browse/FXIOS-11714)</td>
  </tr>
  <tr>
    <td>toasts.close_all_tabs.undo_selected</td>
    <td>2</td>
    <td>F[FXIOS-11714](https://mozilla-hub.atlassian.net/browse/FXIOS-11714)</td>
  </tr>
</table>

6) Please provide a link to the documentation for this data collection which describes the ultimate data set in a public, complete, and accurate way.

This collection is documented in the Glean Dictionary at https://dictionary.telemetry.mozilla.org/

7) How long will this data be collected?  Choose one of the following:

We want to monitor this data for 2 months (@afurlan-firefox to confirm this is long enough)

8) What populations will you measure?

New users and existing users

9) If this data collection is default on, what is the opt-out mechanism for users?

User has the general option of disable telemetry or/and studies.

10) Please provide a general description of how you will analyze this data.

We will analyze aggregated information. We care about number of users closing a tab or all tabs compared to number of users then undoing a closed tab(s).

11) Where do you intend to share the results of your analysis?

Mozilla Internal (Product and Dev Team).

12) Is there a third-party tool (i.e. not Glean or Telemetry) that you are proposing to use for this data collection? If so:

No. We will collect the info using Glean. We will analyze the data with the traditional Looker/SQL database that Mozilla uses for all other telemetry.


[FXIOS-11714]: https://mozilla-hub.atlassian.net/browse/FXIOS-11714?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
author_association: CONTRIBUTOR
user: login: adudenamedruby
created_at: 2025-03-27T13:08:50Z
body: r+
# Data Review Form

_1) Is there or will there be **documentation** that describes the schema for the ultimate data set in a public, complete, and accurate way?_ 

Yes, telemetry is documented at https://dictionary.telemetry.mozilla.org/apps/firefox_ios

_2) Is there a control mechanism that allows the user to turn the data collection on and off?_ 

Yes, Firefox iOS provides data controls in the app settings

_3) If the request is for permanent data collection, is there someone who will monitor the data over time?_

This will be reviewed by a data-steward on the Firefox iOS team (@adudenamedruby) every 6 months

_4) Using the **[category system of data types](https://wiki.mozilla.org/Firefox/Data_Collection)** on the Mozilla wiki, what collection type of data do the requested measurements fall under?_

Type 2

_5) Is the data collection request for default-on or default-off?_

Default on

_6) Does the instrumentation include the addition of **any *new* identifiers** (whether anonymous or otherwise; e.g., username, random IDs, etc.  See the appendix for more details)?_

No

_7) Is the data collection covered by the existing Firefox privacy notice?_ 

Yes

_8) Does the data collection use a third-party collection tool?_ 

No
author_association: CONTRIBUTOR
user: login: mergify[bot]
created_at: 2025-03-27T15:27:50Z
body: This pull request has conflicts when rebasing. Could you fix it @Cramsden? 🙏
author_association: CONTRIBUTOR
user: login: Cramsden
created_at: 2025-04-11T18:27:03Z
body: @Mergifyio backport release/v137
author_association: CONTRIBUTOR
user: login: mergify[bot]
created_at: 2025-04-11T18:27:11Z
body: > backport release/v137

#### ✅ Backports have been created

<details>

* [#26051 Add undo toast telemetry (backport #25569)](https://github.com/mozilla-mobile/firefox-ios/pull/26051) has been created for branch `release/v137` but encountered conflicts

</details>


<!---
DO NOT EDIT
-*- Mergify Payload -*-
{"command": "backport release/v137", "conclusion": "success", "action_is_running": true}
-*- Mergify Payload End -*-
-->
author_association: CONTRIBUTOR
user: login: Cramsden
created_at: 2025-04-14T19:39:00Z
body: @Mergifyio backport release/v138
author_association: CONTRIBUTOR
user: login: mergify[bot]
created_at: 2025-04-14T19:39:09Z
body: > backport release/v138

#### ✅ Backports have been created

<details>

* [#26093 Add undo toast telemetry (backport #25569)](https://github.com/mozilla-mobile/firefox-ios/pull/26093) has been created for branch `release/v138` but encountered conflicts

</details>


<!---
DO NOT EDIT
-*- Mergify Payload -*-
{"command": "backport release/v138", "conclusion": "success", "action_is_running": true}
-*- Mergify Payload End -*-
-->
author_association: CONTRIBUTOR