diff --git a/app/components/UI/OptinMetrics/index.test.tsx b/app/components/UI/OptinMetrics/index.test.tsx index f40b25cf32c..a8c5373eadc 100644 --- a/app/components/UI/OptinMetrics/index.test.tsx +++ b/app/components/UI/OptinMetrics/index.test.tsx @@ -146,6 +146,16 @@ describe('OptinMetrics', () => { await waitFor(() => { expect(mockAnalytics.trackEvent).toHaveBeenNthCalledWith( 1, + expect.objectContaining({ + name: MetaMetricsEvents.METRICS_OPT_IN.category, + properties: expect.objectContaining({ + location: 'onboarding_metametrics', + updated_after_onboarding: false, + }), + }), + ); + expect(mockAnalytics.trackEvent).toHaveBeenNthCalledWith( + 2, expect.objectContaining({ name: 'Analytics Preference Selected', properties: expect.objectContaining({ @@ -177,6 +187,16 @@ describe('OptinMetrics', () => { await waitFor(() => { expect(mockAnalytics.trackEvent).toHaveBeenNthCalledWith( 1, + expect.objectContaining({ + name: MetaMetricsEvents.METRICS_OPT_IN.category, + properties: expect.objectContaining({ + location: 'onboarding_metametrics', + updated_after_onboarding: false, + }), + }), + ); + expect(mockAnalytics.trackEvent).toHaveBeenNthCalledWith( + 2, expect.objectContaining({ name: 'Analytics Preference Selected', properties: expect.objectContaining({ @@ -212,6 +232,16 @@ describe('OptinMetrics', () => { ); await waitFor(() => { + expect(mockAnalytics.trackEvent).toHaveBeenCalledWith( + expect.objectContaining({ + name: MetaMetricsEvents.METRICS_OPT_IN.category, + properties: expect.objectContaining({ + location: 'onboarding_metametrics', + updated_after_onboarding: false, + account_type: AccountType.Imported, + }), + }), + ); expect(mockAnalytics.trackEvent).toHaveBeenCalledWith( expect.objectContaining({ name: 'Analytics Preference Selected', diff --git a/app/components/UI/OptinMetrics/index.tsx b/app/components/UI/OptinMetrics/index.tsx index 63871a546da..7485dff5b08 100644 --- a/app/components/UI/OptinMetrics/index.tsx +++ b/app/components/UI/OptinMetrics/index.tsx @@ -168,19 +168,21 @@ const OptinMetrics = () => { dispatch(setDataCollectionForMarketing(isMarketingChecked)); - // Track opt-out event if user opted out of metrics - if (!isBasicUsageChecked) { - metrics.trackEvent( - metrics - .createEventBuilder(MetaMetricsEvents.METRICS_OPT_OUT) - .addProperties({ - updated_after_onboarding: false, - location: 'onboarding_metametrics', - ...(accountType && { account_type: accountType }), - }) - .build(), - ); - } + // Track opt-in / opt-out for metrics + metrics.trackEvent( + metrics + .createEventBuilder( + isBasicUsageChecked + ? MetaMetricsEvents.METRICS_OPT_IN + : MetaMetricsEvents.METRICS_OPT_OUT, + ) + .addProperties({ + updated_after_onboarding: false, + location: 'onboarding_metametrics', + ...(accountType && { account_type: accountType }), + }) + .build(), + ); metrics.trackEvent( metrics diff --git a/app/components/Views/Onboarding/index.test.tsx b/app/components/Views/Onboarding/index.test.tsx index 4608707035d..771c308e15b 100644 --- a/app/components/Views/Onboarding/index.test.tsx +++ b/app/components/Views/Onboarding/index.test.tsx @@ -75,6 +75,7 @@ import { captureException } from '@sentry/react-native'; import Logger from '../../../util/Logger'; import { MIGRATION_ERROR_HAPPENED } from '../../../constants/storage'; import { AccountType } from '../../../constants/onboarding'; +import { MetaMetricsEvents } from '../../../core/Analytics'; // Mock netinfo - using existing mock jest.mock('@react-native-community/netinfo'); @@ -1990,6 +1991,13 @@ describe('Onboarding', () => { await waitFor(() => { expect(mockAnalytics.optIn).toHaveBeenCalled(); + expect( + mockCreateEventBuilder.mock.calls.some( + (call) => + (call[0] as { category: string }).category === + MetaMetricsEvents.METRICS_OPT_IN.category, + ), + ).toBe(true); }); }); }); diff --git a/app/components/Views/Onboarding/index.tsx b/app/components/Views/Onboarding/index.tsx index 353227bd74e..f2d715f0a34 100644 --- a/app/components/Views/Onboarding/index.tsx +++ b/app/components/Views/Onboarding/index.tsx @@ -733,6 +733,18 @@ const Onboarding = () => { discardBufferedTraces(); await setupSentry(); + const accountType = getSocialAccountType(provider, !createWallet); + metrics.trackEvent( + metrics + .createEventBuilder(MetaMetricsEvents.METRICS_OPT_IN) + .addProperties({ + updated_after_onboarding: false, + location: 'onboarding_social_login', + account_type: accountType, + }) + .build(), + ); + // use new trace instead of buffered trace for social login onboardingTraceCtx.current = trace({ name: TraceName.OnboardingJourneyOverall, @@ -740,7 +752,6 @@ const Onboarding = () => { tags: getTraceTags(store.getState()), }); - const accountType = getSocialAccountType(provider, !createWallet); if (createWallet) { track(MetaMetricsEvents.WALLET_SETUP_STARTED, { account_type: accountType, diff --git a/app/components/Views/Settings/SecuritySettings/Sections/MetaMetricsAndDataCollectionSection/MetaMetricsAndDataCollectionSection.test.tsx b/app/components/Views/Settings/SecuritySettings/Sections/MetaMetricsAndDataCollectionSection/MetaMetricsAndDataCollectionSection.test.tsx index c5ebee60e6d..545f466e354 100644 --- a/app/components/Views/Settings/SecuritySettings/Sections/MetaMetricsAndDataCollectionSection/MetaMetricsAndDataCollectionSection.test.tsx +++ b/app/components/Views/Settings/SecuritySettings/Sections/MetaMetricsAndDataCollectionSection/MetaMetricsAndDataCollectionSection.test.tsx @@ -377,7 +377,18 @@ describe('MetaMetricsAndDataCollectionSection', () => { deviceProp: 'Device value', userProp: 'User value', }); - expect(mockAnalytics.trackEvent).toHaveBeenCalledWith( + expect(mockAnalytics.trackEvent).toHaveBeenNthCalledWith( + 1, + expect.objectContaining({ + name: MetaMetricsEvents.METRICS_OPT_IN.category, + properties: expect.objectContaining({ + updated_after_onboarding: true, + location: 'settings', + }), + }), + ); + expect(mockAnalytics.trackEvent).toHaveBeenNthCalledWith( + 2, expect.objectContaining({ name: MetaMetricsEvents.ANALYTICS_PREFERENCE_SELECTED.category, properties: expect.objectContaining({ @@ -407,7 +418,18 @@ describe('MetaMetricsAndDataCollectionSection', () => { fireEvent(metaMetricsSwitch, 'valueChange', true); await waitFor(() => { - expect(mockAnalytics.trackEvent).toHaveBeenCalledWith( + expect(mockAnalytics.trackEvent).toHaveBeenNthCalledWith( + 1, + expect.objectContaining({ + name: MetaMetricsEvents.METRICS_OPT_IN.category, + properties: expect.objectContaining({ + updated_after_onboarding: true, + location: 'onboarding_default_settings', + }), + }), + ); + expect(mockAnalytics.trackEvent).toHaveBeenNthCalledWith( + 2, expect.objectContaining({ name: MetaMetricsEvents.ANALYTICS_PREFERENCE_SELECTED.category, properties: expect.objectContaining({ @@ -467,6 +489,16 @@ describe('MetaMetricsAndDataCollectionSection', () => { fireEvent(metaMetricsSwitch, 'valueChange', true); await waitFor(() => { + expect(mockAnalytics.trackEvent).toHaveBeenCalledWith( + expect.objectContaining({ + name: MetaMetricsEvents.METRICS_OPT_IN.category, + properties: expect.objectContaining({ + updated_after_onboarding: true, + location: 'settings', + account_type: AccountType.MetamaskGoogle, + }), + }), + ); expect(mockAnalytics.trackEvent).toHaveBeenCalledWith( expect.objectContaining({ name: MetaMetricsEvents.ANALYTICS_PREFERENCE_SELECTED.category, @@ -808,6 +840,16 @@ describe('MetaMetricsAndDataCollectionSection', () => { }); expect(mockAnalytics.trackEvent).toHaveBeenNthCalledWith( 1, + expect.objectContaining({ + name: MetaMetricsEvents.METRICS_OPT_IN.category, + properties: expect.objectContaining({ + location: 'settings', + updated_after_onboarding: true, + }), + }), + ); + expect(mockAnalytics.trackEvent).toHaveBeenNthCalledWith( + 2, expect.objectContaining({ name: MetaMetricsEvents.ANALYTICS_PREFERENCE_SELECTED.category, properties: expect.objectContaining({ @@ -827,8 +869,8 @@ describe('MetaMetricsAndDataCollectionSection', () => { }, ); expect(mockAnalytics.trackEvent).toHaveBeenNthCalledWith( - // if MetaMetrics is initially disabled, trackEvent is called twice and this is 2nd call - !metaMetricsInitiallyEnabled ? 2 : 1, + // if MetaMetrics is initially disabled, marketing consent is the 3rd trackEvent + !metaMetricsInitiallyEnabled ? 3 : 1, expect.objectContaining({ name: MetaMetricsEvents.ANALYTICS_PREFERENCE_SELECTED.category, properties: expect.objectContaining({ diff --git a/app/components/Views/Settings/SecuritySettings/Sections/MetaMetricsAndDataCollectionSection/MetaMetricsAndDataCollectionSection.tsx b/app/components/Views/Settings/SecuritySettings/Sections/MetaMetricsAndDataCollectionSection/MetaMetricsAndDataCollectionSection.tsx index c2940f9408b..59debfafdfb 100644 --- a/app/components/Views/Settings/SecuritySettings/Sections/MetaMetricsAndDataCollectionSection/MetaMetricsAndDataCollectionSection.tsx +++ b/app/components/Views/Settings/SecuritySettings/Sections/MetaMetricsAndDataCollectionSection/MetaMetricsAndDataCollectionSection.tsx @@ -114,6 +114,17 @@ const MetaMetricsAndDataCollectionSection: React.FC< setAnalyticsEnabled(true); analytics.identify(consolidatedTraits); + analytics.trackEvent( + AnalyticsEventBuilder.createEventBuilder( + MetaMetricsEvents.METRICS_OPT_IN, + ) + .addProperties({ + updated_after_onboarding: true, + location: analyticsLocation, + ...(accountType && { account_type: accountType }), + }) + .build(), + ); analytics.trackEvent( AnalyticsEventBuilder.createEventBuilder( MetaMetricsEvents.ANALYTICS_PREFERENCE_SELECTED, diff --git a/app/core/Analytics/MetaMetrics.events.ts b/app/core/Analytics/MetaMetrics.events.ts index 063eb7bc621..3e0d1d23446 100644 --- a/app/core/Analytics/MetaMetrics.events.ts +++ b/app/core/Analytics/MetaMetrics.events.ts @@ -124,6 +124,7 @@ enum EVENT_NAME { // Analytics ANALYTICS_PREFERENCE_SELECTED = 'Analytics Preference Selected', + METRICS_OPT_IN = 'Metrics Opt In', METRICS_OPT_OUT = 'Metrics Opt Out', ANALYTICS_REQUEST_DATA_DELETION = 'Delete MetaMetrics Data Request Submitted', EXPERIMENT_VIEWED = 'Experiment Viewed', @@ -829,6 +830,7 @@ const events = { ANALYTICS_PREFERENCE_SELECTED: generateOpt( EVENT_NAME.ANALYTICS_PREFERENCE_SELECTED, ), + METRICS_OPT_IN: generateOpt(EVENT_NAME.METRICS_OPT_IN), METRICS_OPT_OUT: generateOpt(EVENT_NAME.METRICS_OPT_OUT), ANALYTICS_REQUEST_DATA_DELETION: generateOpt( EVENT_NAME.ANALYTICS_REQUEST_DATA_DELETION,