From 71971493c544ce1125336d6559f9f5914b2dd463 Mon Sep 17 00:00:00 2001 From: Valerie Pomerleau Date: Wed, 10 Jul 2024 14:32:32 -0700 Subject: [PATCH] feat(glean): Add frontend account deletion metrics Because: * We want metrics about account deletions This commit: * Add metrics for settings page view (account_pref_view) and account deletion (frontend) funnel (delete_account_settings_submit, delete_account_view, delete_account_engage, delete_account_submit, delete_account_password_view, delete_account_password_submit) * Implement metrics in fxa-settings and include metrics tests Closes #FXA-10031, FXA-10032, FXA-10033, FXA-10034, FXA-10035, FXA-10036 --- packages/fxa-settings/package.json | 4 +- .../src/components/App/index.test.tsx | 6 +- .../Settings/PageDeleteAccount/index.test.tsx | 125 ++++++++++++++---- .../Settings/PageDeleteAccount/index.tsx | 16 ++- .../Settings/PageSettings/index.test.tsx | 61 +++++++-- .../Settings/PageSettings/index.tsx | 8 +- .../fxa-settings/src/lib/glean/index.test.ts | 75 +++++++++++ packages/fxa-settings/src/lib/glean/index.ts | 23 ++++ .../src/pages/Signin/index.test.tsx | 1 - .../metrics/glean/fxa-ui-metrics.yaml | 120 +++++++++++++++++ .../metrics/glean/web/accountPref.ts | 16 +++ .../metrics/glean/web/deleteAccount.ts | 103 +++++++++++++++ .../fxa-shared/metrics/glean/web/index.ts | 10 ++ 13 files changed, 524 insertions(+), 44 deletions(-) create mode 100644 packages/fxa-shared/metrics/glean/web/deleteAccount.ts diff --git a/packages/fxa-settings/package.json b/packages/fxa-settings/package.json index 0a94b230ea3..636facc2364 100644 --- a/packages/fxa-settings/package.json +++ b/packages/fxa-settings/package.json @@ -257,7 +257,9 @@ "webpack": "^5.84.1" }, "nx": { - "implicitDependencies": ["crypto-relier"], + "implicitDependencies": [ + "crypto-relier" + ], "tags": [ "scope:frontend", "type:core" diff --git a/packages/fxa-settings/src/components/App/index.test.tsx b/packages/fxa-settings/src/components/App/index.test.tsx index a0b215cb7b2..de8ef7644e0 100644 --- a/packages/fxa-settings/src/components/App/index.test.tsx +++ b/packages/fxa-settings/src/components/App/index.test.tsx @@ -49,7 +49,11 @@ jest.mock('../Settings/ScrollToTop', () => ({ jest.mock('../../lib/glean', () => ({ __esModule: true, - default: { initialize: jest.fn(), getEnabled: jest.fn() }, + default: { + initialize: jest.fn(), + getEnabled: jest.fn(), + accountPref: { view: jest.fn() }, + }, })); const mockMetricsQueryAccountAmplitude = { diff --git a/packages/fxa-settings/src/components/Settings/PageDeleteAccount/index.test.tsx b/packages/fxa-settings/src/components/Settings/PageDeleteAccount/index.test.tsx index 4bd93777583..6f5443fab44 100644 --- a/packages/fxa-settings/src/components/Settings/PageDeleteAccount/index.test.tsx +++ b/packages/fxa-settings/src/components/Settings/PageDeleteAccount/index.test.tsx @@ -5,6 +5,7 @@ import React from 'react'; import 'mutationobserver-shim'; import { screen, fireEvent, act, within } from '@testing-library/react'; +import { userEvent } from '@testing-library/user-event'; import { mockAppContext, mockSession, @@ -13,34 +14,57 @@ import { import { PageDeleteAccount } from '.'; import { typeByTestIdFn } from '../../../lib/test-utils'; import { Account, AppContext } from '../../../models'; -import { logViewEvent, usePageViewEvent } from '../../../lib/metrics'; +import { logViewEvent } from '../../../lib/metrics'; +import { MOCK_EMAIL } from '../../../pages/mocks'; +import GleanMetrics from '../../../lib/glean'; jest.mock('../../../lib/metrics', () => ({ logViewEvent: jest.fn(), usePageViewEvent: jest.fn(), })); +jest.mock('../../../lib/glean', () => ({ + __esModule: true, + default: { + deleteAccount: { + view: jest.fn(), + engage: jest.fn(), + submit: jest.fn(), + passwordView: jest.fn(), + passwordSubmit: jest.fn(), + }, + }, +})); + const account = { primaryEmail: { - email: 'rfeeley@mozilla.com', + email: MOCK_EMAIL, }, uid: '0123456789abcdef', metricsEnabled: true, hasPassword: true, } as unknown as Account; +const pwdlessAccount = { + primaryEmail: { + email: MOCK_EMAIL, + }, + uid: '0123456789abcdef', + metricsEnabled: true, + hasPassword: false, + destroy: jest.fn().mockResolvedValue({}), +} as unknown as Account; + const session = mockSession(true, false); window.URL.createObjectURL = jest.fn(); console.error = jest.fn(); -const advanceStep = async () => { - await act(async () => { - const inputs = screen.getAllByTestId('checkbox-input'); - inputs.forEach((el) => fireEvent.click(el)); - const continueBtn = await screen.findByTestId('continue-button'); - fireEvent.click(continueBtn); - }); +const advanceStep = () => { + const inputs = screen.getAllByTestId('checkbox-input'); + inputs.forEach((el) => fireEvent.click(el)); + const continueBtn = screen.getByTestId('continue-button'); + fireEvent.click(continueBtn); }; describe('PageDeleteAccount', () => { @@ -129,7 +153,7 @@ describe('PageDeleteAccount', () => { expect(screen.getByTestId('delete-account-button')).toBeEnabled(); }); - it('Gets valid response on submit and emits metrics events', async () => { + it('gets valid response on submit', async () => { renderWithRouter( @@ -139,13 +163,6 @@ describe('PageDeleteAccount', () => { await advanceStep(); await typeByTestIdFn('delete-account-confirm-input-field')('hunter67'); - // TODO: more extensive metrics tests - expect(usePageViewEvent).toHaveBeenCalledWith('settings.delete-account'); - expect(logViewEvent).toHaveBeenCalledWith( - 'flow.settings.account-delete', - 'terms-checked.success' - ); - const deleteAccountButton = screen.getByTestId('delete-account-button'); expect(deleteAccountButton).toBeEnabled(); @@ -153,16 +170,6 @@ describe('PageDeleteAccount', () => { }); it('deletes account if no password set', async () => { - const pwdlessAccount = { - primaryEmail: { - email: 'rfeeley@mozilla.com', - }, - uid: '0123456789abcdef', - metricsEnabled: true, - hasPassword: false, - destroy: jest.fn().mockResolvedValue({}), - } as unknown as Account; - renderWithRouter( { 'confirm-password.success' ); }); + + describe('glean metrics', () => { + it('emits expect event on first step view', () => { + renderWithRouter( + + + + ); + + expect(GleanMetrics.deleteAccount.view).toHaveBeenCalled(); + }); + + describe('account with password set', () => { + it('emits expected metrics during account deletion flow', async () => { + renderWithRouter( + + + + ); + + const inputs = screen.getAllByTestId('checkbox-input'); + await Promise.all( + inputs.map(async (el) => { + await userEvent.click(el); + }) + ); + expect(GleanMetrics.deleteAccount.engage).toHaveBeenCalled(); + await userEvent.click(screen.getByRole('button', { name: 'Continue' })); + expect(GleanMetrics.deleteAccount.submit).toHaveBeenCalled(); + + // password confirmation step + expect(GleanMetrics.deleteAccount.passwordView).toHaveBeenCalled(); + await userEvent.type( + screen.getByLabelText('Enter password'), + 'hunter67' + ); + await userEvent.click(screen.getByRole('button', { name: 'Delete' })); + expect(GleanMetrics.deleteAccount.passwordSubmit).toHaveBeenCalled(); + }); + }); + + describe('account without password set', () => { + it('emits expected metrics during account deletion flow', async () => { + renderWithRouter( + + + + ); + + const inputs = screen.getAllByTestId('checkbox-input'); + await Promise.all( + inputs.map(async (el) => { + await userEvent.click(el); + }) + ); + expect(GleanMetrics.deleteAccount.engage).toHaveBeenCalled(); + await userEvent.click(screen.getByRole('button', { name: 'Continue' })); + expect(GleanMetrics.deleteAccount.submit).toHaveBeenCalled(); + expect(GleanMetrics.deleteAccount.passwordView).not.toHaveBeenCalled(); + }); + }); + }); }); diff --git a/packages/fxa-settings/src/components/Settings/PageDeleteAccount/index.tsx b/packages/fxa-settings/src/components/Settings/PageDeleteAccount/index.tsx index 6b8453dc7c7..93a20caa66a 100644 --- a/packages/fxa-settings/src/components/Settings/PageDeleteAccount/index.tsx +++ b/packages/fxa-settings/src/components/Settings/PageDeleteAccount/index.tsx @@ -30,6 +30,7 @@ import { AuthUiErrors } from '../../../lib/auth-errors/auth-errors'; import { hardNavigate } from 'fxa-react/lib/utils'; import LinkExternal from 'fxa-react/components/LinkExternal'; import { getErrorFtlId } from '../../../lib/error-utils'; +import GleanMetrics from '../../../lib/glean'; type FormData = { password: string; @@ -107,6 +108,7 @@ export const PageDeleteAccount = (_: RouteComponentProps) => { const [subtitleText, setSubtitleText] = useState( l10n.getString('delete-account-step-1-2', null, 'Step 1 of 2') ); + const [hasEngagedWithForm, setHasEngagedWithForm] = useState(false); const [checkedBoxes, setCheckedBoxes] = useState([]); const allBoxesChecked = Object.keys(checkboxLabels).every((element) => checkedBoxes.includes(element) @@ -117,6 +119,10 @@ export const PageDeleteAccount = (_: RouteComponentProps) => { const account = useAccount(); + useEffect(() => { + GleanMetrics.deleteAccount.view(); + }, []); + useEffect(() => { if (!account.hasPassword) { setSubtitleText(''); @@ -124,6 +130,7 @@ export const PageDeleteAccount = (_: RouteComponentProps) => { }, [account.hasPassword]); const advanceStep = () => { + GleanMetrics.deleteAccount.submit(); // Accounts that do not have a password set, will delete immediately if (!account.hasPassword) { deleteAccount(''); @@ -132,7 +139,7 @@ export const PageDeleteAccount = (_: RouteComponentProps) => { l10n.getString('delete-account-step-2-2', null, 'Step 2 of 2') ); setConfirmed(true); - + GleanMetrics.deleteAccount.passwordView(); logViewEvent('flow.settings.account-delete', 'terms-checked.success'); } }; @@ -169,6 +176,10 @@ export const PageDeleteAccount = (_: RouteComponentProps) => { event.persist(); setCheckedBoxes((existing) => { if (event.target.checked) { + if (!hasEngagedWithForm) { + GleanMetrics.deleteAccount.engage(); + setHasEngagedWithForm(true); + } return [...existing, labelText]; } else { return [...existing.filter((text) => text !== labelText)]; @@ -319,6 +330,9 @@ export const PageDeleteAccount = (_: RouteComponentProps) => { className="cta-caution py-2 mx-2 px-4 tablet:px-10" data-testid="delete-account-button" disabled={disabled} + onClick={() => { + GleanMetrics.deleteAccount.passwordSubmit(); + }} > Delete diff --git a/packages/fxa-settings/src/components/Settings/PageSettings/index.test.tsx b/packages/fxa-settings/src/components/Settings/PageSettings/index.test.tsx index d0a167b0939..a90969db63a 100644 --- a/packages/fxa-settings/src/components/Settings/PageSettings/index.test.tsx +++ b/packages/fxa-settings/src/components/Settings/PageSettings/index.test.tsx @@ -4,12 +4,28 @@ import React from 'react'; import { screen } from '@testing-library/react'; +import { userEvent } from '@testing-library/user-event'; import PageSettings from '.'; import { renderWithRouter } from '../../../models/mocks'; import * as Metrics from '../../../lib/metrics'; +import GleanMetrics from '../../../lib/glean'; -jest.spyOn(Metrics, 'setProperties'); -jest.spyOn(Metrics, 'usePageViewEvent'); +jest.mock('../../../lib/metrics', () => ({ + setProperties: jest.fn(), + usePageViewEvent: jest.fn(), +})); + +jest.mock('../../../lib/glean', () => ({ + __esModule: true, + default: { + accountPref: { + view: jest.fn(), + }, + deleteAccount: { + settingsSubmit: jest.fn(), + }, + }, +})); beforeEach(() => { const mockIntersectionObserver = jest.fn(); @@ -20,15 +36,36 @@ beforeEach(() => { window.IntersectionObserver = mockIntersectionObserver; }); -it('renders without imploding', async () => { - renderWithRouter(); - expect(screen.getByTestId('settings-profile')).toBeInTheDocument(); - expect(screen.getByTestId('settings-security')).toBeInTheDocument(); - expect(screen.getByTestId('settings-connected-services')).toBeInTheDocument(); - expect(screen.getByTestId('settings-delete-account')).toBeInTheDocument(); - expect(screen.queryByTestId('settings-data-collection')).toBeInTheDocument(); - expect(Metrics.setProperties).toHaveBeenCalledWith({ - uid: 'abc123', +describe('PageSettings', () => { + it('renders without imploding', async () => { + renderWithRouter(); + expect(screen.getByTestId('settings-profile')).toBeInTheDocument(); + expect(screen.getByTestId('settings-security')).toBeInTheDocument(); + expect( + screen.getByTestId('settings-connected-services') + ).toBeInTheDocument(); + expect(screen.getByTestId('settings-delete-account')).toBeInTheDocument(); + expect( + screen.queryByTestId('settings-data-collection') + ).toBeInTheDocument(); + expect(Metrics.setProperties).toHaveBeenCalledWith({ + lang: null, + uid: 'abc123', + }); + }); + + describe('glean metrics', () => { + it('emits the expected event on render', async () => { + renderWithRouter(); + expect(GleanMetrics.accountPref.view).toHaveBeenCalled(); + }); + + it('emits the expected event on click of Delete account button', async () => { + renderWithRouter(); + await userEvent.click( + screen.getByRole('link', { name: 'Delete account' }) + ); + expect(GleanMetrics.deleteAccount.settingsSubmit).toHaveBeenCalled(); + }); }); - expect(Metrics.usePageViewEvent).toHaveBeenCalledWith('settings'); }); diff --git a/packages/fxa-settings/src/components/Settings/PageSettings/index.tsx b/packages/fxa-settings/src/components/Settings/PageSettings/index.tsx index ec3da7511d6..30526e07f70 100644 --- a/packages/fxa-settings/src/components/Settings/PageSettings/index.tsx +++ b/packages/fxa-settings/src/components/Settings/PageSettings/index.tsx @@ -2,7 +2,7 @@ * 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 React, { useRef } from 'react'; +import React, { useEffect, useRef } from 'react'; import { Link, RouteComponentProps } from '@reach/router'; import Nav from '../Nav'; import Security from '../Security'; @@ -15,6 +15,7 @@ import { useAccount } from '../../../models'; import { DeleteAccountPath } from 'fxa-settings/src/constants'; import { Localized } from '@fluent/react'; import DataCollection from '../DataCollection'; +import GleanMetrics from '../../../lib/glean'; export const PageSettings = (_: RouteComponentProps) => { const { uid } = useAccount(); @@ -25,6 +26,10 @@ export const PageSettings = (_: RouteComponentProps) => { }); Metrics.usePageViewEvent(Metrics.settingsViewName); + useEffect(() => { + GleanMetrics.accountPref.view(); + }, []); + // Scroll to effect const profileRef = useRef(null); const securityRef = useRef(null); @@ -57,6 +62,7 @@ export const PageSettings = (_: RouteComponentProps) => { data-testid="settings-delete-account" className="cta-caution text-sm transition-standard mt-12 py-2 px-5 mobileLandscape:py-1" to={DeleteAccountPath} + onClick={() => GleanMetrics.deleteAccount.settingsSubmit()} > Delete account diff --git a/packages/fxa-settings/src/lib/glean/index.test.ts b/packages/fxa-settings/src/lib/glean/index.test.ts index d3c87e32698..e6211f26c79 100644 --- a/packages/fxa-settings/src/lib/glean/index.test.ts +++ b/packages/fxa-settings/src/lib/glean/index.test.ts @@ -12,6 +12,7 @@ import * as event from 'fxa-shared/metrics/glean/web/event'; import * as reg from 'fxa-shared/metrics/glean/web/reg'; import * as login from 'fxa-shared/metrics/glean/web/login'; import * as accountPref from 'fxa-shared/metrics/glean/web/accountPref'; +import * as deleteAccount from 'fxa-shared/metrics/glean/web/deleteAccount'; import { userIdSha256 } from 'fxa-shared/metrics/glean/web/account'; import { oauthClientId, @@ -556,6 +557,15 @@ describe('lib/glean', () => { }); describe('accountPref', () => { + it('submits a ping with the account_pref_view event name', async () => { + GleanMetrics.accountPref.view(); + const spy = sandbox.spy(accountPref.view, 'record'); + await GleanMetrics.isDone(); + sinon.assert.calledOnce(setEventNameStub); + sinon.assert.calledWith(setEventNameStub, 'account_pref_view'); + sinon.assert.calledOnce(spy); + }); + it('submits a ping with the account_pref_recovery_key_submit event name', async () => { GleanMetrics.accountPref.recoveryKeySubmit(); const spy = sandbox.spy(accountPref.recoveryKeySubmit, 'record'); @@ -568,6 +578,71 @@ describe('lib/glean', () => { sinon.assert.calledOnce(spy); }); }); + + describe('deleteAccount', () => { + it('submits a ping with the delete_account_settings_submit event name', async () => { + GleanMetrics.deleteAccount.settingsSubmit(); + const spy = sandbox.spy(deleteAccount.settingsSubmit, 'record'); + await GleanMetrics.isDone(); + sinon.assert.calledOnce(setEventNameStub); + sinon.assert.calledWith( + setEventNameStub, + 'delete_account_settings_submit' + ); + sinon.assert.calledOnce(spy); + }); + + it('submits a ping with the delete_account_view event name', async () => { + GleanMetrics.deleteAccount.view(); + const spy = sandbox.spy(deleteAccount.view, 'record'); + await GleanMetrics.isDone(); + sinon.assert.calledOnce(setEventNameStub); + sinon.assert.calledWith(setEventNameStub, 'delete_account_view'); + sinon.assert.calledOnce(spy); + }); + + it('submits a ping with the delete_account_engage event name', async () => { + GleanMetrics.deleteAccount.engage(); + const spy = sandbox.spy(deleteAccount.engage, 'record'); + await GleanMetrics.isDone(); + sinon.assert.calledOnce(setEventNameStub); + sinon.assert.calledWith(setEventNameStub, 'delete_account_engage'); + sinon.assert.calledOnce(spy); + }); + + it('submits a ping with the delete_account_submit event name', async () => { + GleanMetrics.deleteAccount.submit(); + const spy = sandbox.spy(deleteAccount.submit, 'record'); + await GleanMetrics.isDone(); + sinon.assert.calledOnce(setEventNameStub); + sinon.assert.calledWith(setEventNameStub, 'delete_account_submit'); + sinon.assert.calledOnce(spy); + }); + + it('submits a ping with the delete_account_password_view event name', async () => { + GleanMetrics.deleteAccount.passwordView(); + const spy = sandbox.spy(deleteAccount.passwordView, 'record'); + await GleanMetrics.isDone(); + sinon.assert.calledOnce(setEventNameStub); + sinon.assert.calledWith( + setEventNameStub, + 'delete_account_password_view' + ); + sinon.assert.calledOnce(spy); + }); + + it('submits a ping with the delete_account_password_password_submit event name', async () => { + GleanMetrics.deleteAccount.passwordSubmit(); + const spy = sandbox.spy(deleteAccount.passwordSubmit, 'record'); + await GleanMetrics.isDone(); + sinon.assert.calledOnce(setEventNameStub); + sinon.assert.calledWith( + setEventNameStub, + 'delete_account_password_submit' + ); + sinon.assert.calledOnce(spy); + }); + }); }); describe('toggle enabled state', () => { diff --git a/packages/fxa-settings/src/lib/glean/index.ts b/packages/fxa-settings/src/lib/glean/index.ts index 302de4f2e8f..2af9af18c84 100644 --- a/packages/fxa-settings/src/lib/glean/index.ts +++ b/packages/fxa-settings/src/lib/glean/index.ts @@ -26,6 +26,7 @@ import * as cadApproveDevice from 'fxa-shared/metrics/glean/web/cadApproveDevice import * as cadMobilePair from 'fxa-shared/metrics/glean/web/cadMobilePair'; import * as cadMobilePairUseApp from 'fxa-shared/metrics/glean/web/cadMobilePairUseApp'; import * as accountPref from 'fxa-shared/metrics/glean/web/accountPref'; +import * as deleteAccount from 'fxa-shared/metrics/glean/web/deleteAccount'; import { userIdSha256 } from 'fxa-shared/metrics/glean/web/account'; import { oauthClientId, @@ -351,8 +352,30 @@ const recordEventMetric = ( case 'cad_mobile_pair_use_app_view': cadMobilePairUseApp.view.record(); break; + case 'account_pref_view': + accountPref.view.record(); + break; case 'account_pref_recovery_key_submit': accountPref.recoveryKeySubmit.record(); + break; + case 'delete_account_settings_submit': + deleteAccount.settingsSubmit.record(); + break; + case 'delete_account_view': + deleteAccount.view.record(); + break; + case 'delete_account_engage': + deleteAccount.engage.record(); + break; + case 'delete_account_submit': + deleteAccount.submit.record(); + break; + case 'delete_account_password_view': + deleteAccount.passwordView.record(); + break; + case 'delete_account_password_submit': + deleteAccount.passwordSubmit.record(); + break; } }; diff --git a/packages/fxa-settings/src/pages/Signin/index.test.tsx b/packages/fxa-settings/src/pages/Signin/index.test.tsx index 9bd27098826..26eb8ae3e5b 100644 --- a/packages/fxa-settings/src/pages/Signin/index.test.tsx +++ b/packages/fxa-settings/src/pages/Signin/index.test.tsx @@ -37,7 +37,6 @@ import { } from '../../models/integrations/client-matching'; import firefox from '../../lib/channels/firefox'; import { navigate } from '@reach/router'; -import { text } from 'stream/consumers'; // import { getFtlBundle, testAllL10n } from 'fxa-react/lib/test-utils'; // import { FluentBundle } from '@fluent/bundle'; diff --git a/packages/fxa-shared/metrics/glean/fxa-ui-metrics.yaml b/packages/fxa-shared/metrics/glean/fxa-ui-metrics.yaml index 9b46a291691..52d44d92876 100644 --- a/packages/fxa-shared/metrics/glean/fxa-ui-metrics.yaml +++ b/packages/fxa-shared/metrics/glean/fxa-ui-metrics.yaml @@ -1808,6 +1808,23 @@ third_party_auth_set_password: - interaction account_pref: + view: + type: event + description: | + View of the account settings page + send_in_pings: + - events + notification_emails: + - vzare@mozilla.com + - fxa-staff@mozilla.com + bugs: + - https://mozilla-hub.atlassian.net/browse/FXA-10031 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1830504 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1844121 + expires: never + data_sensitivity: + - interaction recovery_key_submit: type: event description: | @@ -1825,3 +1842,106 @@ account_pref: expires: never data_sensitivity: - interaction +delete_account: + settings_submit: + type: event + description: | + Click on the "Delete Account" button on account settings page + send_in_pings: + - events + notification_emails: + - vzare@mozilla.com + - fxa-staff@mozilla.com + bugs: + - https://mozilla-hub.atlassian.net/browse/FXA-10032 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1830504 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1844121 + expires: never + data_sensitivity: + - interaction + view: + type: event + description: | + View of step 1 of the account deletion funnel page + send_in_pings: + - events + notification_emails: + - vzare@mozilla.com + - fxa-staff@mozilla.com + bugs: + - https://mozilla-hub.atlassian.net/browse/FXA-10033 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1830504 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1844121 + expires: never + data_sensitivity: + - interaction + engage: + type: event + description: | + Engagement with checkboxes on step 1 of account deletion funnel page + send_in_pings: + - events + notification_emails: + - vzare@mozilla.com + - fxa-staff@mozilla.com + bugs: + - https://mozilla-hub.atlassian.net/browse/FXA-10034 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1830504 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1844121 + expires: never + data_sensitivity: + - interaction + submit: + type: event + description: | + Click on the "Continue" button on step 1 of the delete account funnel + send_in_pings: + - events + notification_emails: + - vzare@mozilla.com + - fxa-staff@mozilla.com + bugs: + - https://mozilla-hub.atlassian.net/browse/FXA-10035 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1830504 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1844121 + expires: never + data_sensitivity: + - interaction + password_view: + type: event + description: | + View of step 2 of the account deletion funnel (view of password form) + send_in_pings: + - events + notification_emails: + - vzare@mozilla.com + - fxa-staff@mozilla.com + bugs: + - https://mozilla-hub.atlassian.net/browse/FXA-10036 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1830504 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1844121 + expires: never + data_sensitivity: + - interaction + password_submit: + type: event + description: | + Click on the submit button of step 2 of the account deletion funnel + send_in_pings: + - events + notification_emails: + - vzare@mozilla.com + - fxa-staff@mozilla.com + bugs: + - https://mozilla-hub.atlassian.net/browse/FXA-10036 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1830504 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1844121 + expires: never + data_sensitivity: + - interaction diff --git a/packages/fxa-shared/metrics/glean/web/accountPref.ts b/packages/fxa-shared/metrics/glean/web/accountPref.ts index dd593d69c91..b41bfaca069 100644 --- a/packages/fxa-shared/metrics/glean/web/accountPref.ts +++ b/packages/fxa-shared/metrics/glean/web/accountPref.ts @@ -22,3 +22,19 @@ export const recoveryKeySubmit = new EventMetricType( }, [] ); + +/** + * View of the account settings page + * + * Generated from `account_pref.view`. + */ +export const view = new EventMetricType( + { + category: 'account_pref', + name: 'view', + sendInPings: ['events'], + lifetime: 'ping', + disabled: false, + }, + [] +); diff --git a/packages/fxa-shared/metrics/glean/web/deleteAccount.ts b/packages/fxa-shared/metrics/glean/web/deleteAccount.ts new file mode 100644 index 00000000000..8cdd0890281 --- /dev/null +++ b/packages/fxa-shared/metrics/glean/web/deleteAccount.ts @@ -0,0 +1,103 @@ +/* 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/. */ + +// AUTOGENERATED BY glean_parser v14.1.2. DO NOT EDIT. DO NOT COMMIT. + +import EventMetricType from '@mozilla/glean/private/metrics/event'; + +/** + * Engagement with checkboxes on step 1 of account deletion funnel page + * + * Generated from `delete_account.engage`. + */ +export const engage = new EventMetricType( + { + category: 'delete_account', + name: 'engage', + sendInPings: ['events'], + lifetime: 'ping', + disabled: false, + }, + [] +); + +/** + * Click on the submit button of step 2 of the account deletion funnel + * + * Generated from `delete_account.password_submit`. + */ +export const passwordSubmit = new EventMetricType( + { + category: 'delete_account', + name: 'password_submit', + sendInPings: ['events'], + lifetime: 'ping', + disabled: false, + }, + [] +); + +/** + * View of step 2 of the account deletion funnel (view of password form) + * + * Generated from `delete_account.password_view`. + */ +export const passwordView = new EventMetricType( + { + category: 'delete_account', + name: 'password_view', + sendInPings: ['events'], + lifetime: 'ping', + disabled: false, + }, + [] +); + +/** + * Click on the "Delete Account" button on account settings page + * + * Generated from `delete_account.settings_submit`. + */ +export const settingsSubmit = new EventMetricType( + { + category: 'delete_account', + name: 'settings_submit', + sendInPings: ['events'], + lifetime: 'ping', + disabled: false, + }, + [] +); + +/** + * Click on the "Continue" button on step 1 of the delete account funnel + * + * Generated from `delete_account.submit`. + */ +export const submit = new EventMetricType( + { + category: 'delete_account', + name: 'submit', + sendInPings: ['events'], + lifetime: 'ping', + disabled: false, + }, + [] +); + +/** + * View of step 1 of the account deletion funnel page + * + * Generated from `delete_account.view`. + */ +export const view = new EventMetricType( + { + category: 'delete_account', + name: 'view', + sendInPings: ['events'], + lifetime: 'ping', + disabled: false, + }, + [] +); diff --git a/packages/fxa-shared/metrics/glean/web/index.ts b/packages/fxa-shared/metrics/glean/web/index.ts index 280778e3913..9004e1f4ed8 100644 --- a/packages/fxa-shared/metrics/glean/web/index.ts +++ b/packages/fxa-shared/metrics/glean/web/index.ts @@ -147,6 +147,16 @@ export const eventsMap = { }, accountPref: { + view: 'account_pref_view', recoveryKeySubmit: 'account_pref_recovery_key_submit', }, + + deleteAccount: { + settingsSubmit: 'delete_account_settings_submit', + view: 'delete_account_view', + engage: 'delete_account_engage', + submit: 'delete_account_submit', + passwordView: 'delete_account_password_view', + passwordSubmit: 'delete_account_password_submit', + }, } as const;