From beead63d9de3e8caddd5f2a14cde8dc7436ed59d Mon Sep 17 00:00:00 2001 From: Andrew Rosiclair Date: Mon, 28 Oct 2024 12:15:25 -0400 Subject: [PATCH 01/16] track sign ups --- .../Navigators/OnboardingModalNavigator.tsx | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/libs/Navigation/AppNavigator/Navigators/OnboardingModalNavigator.tsx b/src/libs/Navigation/AppNavigator/Navigators/OnboardingModalNavigator.tsx index 4aae43987797..7707effe45ea 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/OnboardingModalNavigator.tsx +++ b/src/libs/Navigation/AppNavigator/Navigators/OnboardingModalNavigator.tsx @@ -1,11 +1,13 @@ import {createStackNavigator} from '@react-navigation/stack'; -import React, {useCallback} from 'react'; +import React, {useCallback, useEffect} from 'react'; import {View} from 'react-native'; +import {useOnyx} from 'react-native-onyx'; import NoDropZone from '@components/DragAndDrop/NoDropZone'; import FocusTrapForScreens from '@components/FocusTrap/FocusTrapForScreen'; import useKeyboardShortcut from '@hooks/useKeyboardShortcut'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useThemeStyles from '@hooks/useThemeStyles'; +import GoogleTagManager from '@libs/GoogleTagManager'; import OnboardingModalNavigatorScreenOptions from '@libs/Navigation/AppNavigator/OnboardingModalNavigatorScreenOptions'; import type {OnboardingModalNavigatorParamList} from '@libs/Navigation/types'; import OnboardingRefManager from '@libs/OnboardingRefManager'; @@ -14,6 +16,7 @@ import OnboardingEmployees from '@pages/OnboardingEmployees'; import OnboardingPersonalDetails from '@pages/OnboardingPersonalDetails'; import OnboardingPurpose from '@pages/OnboardingPurpose'; import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; import SCREENS from '@src/SCREENS'; import Overlay from './Overlay'; @@ -23,6 +26,17 @@ function OnboardingModalNavigator() { const styles = useThemeStyles(); const {onboardingIsMediumOrLargerScreenWidth} = useResponsiveLayout(); const outerViewRef = React.useRef(null); + const [accountID] = useOnyx(ONYXKEYS.SESSION, {selector: (session) => session?.accountID ?? 0}); + + // Publish a sign_up event when we start the onboarding flow. This should track basic sign ups + // as well as Google and Apple SSO. + useEffect(() => { + if (!accountID) { + return; + } + + GoogleTagManager.publishEvent('sign_up', accountID); + }, [accountID]); const handleOuterClick = useCallback(() => { OnboardingRefManager.handleOuterClick(); From a919b8f39f8bc674d3edbf21ce5c7f58c957b4a5 Mon Sep 17 00:00:00 2001 From: Andrew Rosiclair Date: Mon, 28 Oct 2024 12:25:55 -0400 Subject: [PATCH 02/16] track created workspaces --- src/libs/actions/Policy/Policy.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/libs/actions/Policy/Policy.ts b/src/libs/actions/Policy/Policy.ts index 7d4e10f08c4e..2bdf9a208353 100644 --- a/src/libs/actions/Policy/Policy.ts +++ b/src/libs/actions/Policy/Policy.ts @@ -60,6 +60,7 @@ import * as CurrencyUtils from '@libs/CurrencyUtils'; import DateUtils from '@libs/DateUtils'; import * as ErrorUtils from '@libs/ErrorUtils'; import getIsNarrowLayout from '@libs/getIsNarrowLayout'; +import GoogleTagManager from '@libs/GoogleTagManager'; import Log from '@libs/Log'; import * as NetworkStore from '@libs/Network/NetworkStore'; import * as NumberUtils from '@libs/NumberUtils'; @@ -1826,6 +1827,11 @@ function createWorkspace(policyOwnerEmail = '', makeMeAdmin = false, policyName const {optimisticData, failureData, successData, params} = buildPolicyData(policyOwnerEmail, makeMeAdmin, policyName, policyID, undefined, engagementChoice); API.write(WRITE_COMMANDS.CREATE_WORKSPACE, params, {optimisticData, successData, failureData}); + // Publish a workspace created event if this is their first policy + if (getAdminPolicies().length === 0) { + GoogleTagManager.publishEvent('workspace_created', sessionAccountID); + } + return params; } @@ -3731,6 +3737,10 @@ function setWorkspaceEReceiptsEnabled(policyID: string, eReceipts: boolean) { API.write(WRITE_COMMANDS.SET_WORKSPACE_ERECEIPTS_ENABLED, parameters, onyxData); } +function getAdminPolicies(): Policy[] { + return Object.values(allPolicies ?? {}).filter((policy): policy is Policy => !!policy && policy.role === CONST.POLICY.ROLE.ADMIN); +} + function getAdminPoliciesConnectedToSageIntacct(): Policy[] { return Object.values(allPolicies ?? {}).filter((policy): policy is Policy => !!policy && policy.role === CONST.POLICY.ROLE.ADMIN && !!policy?.connections?.intacct); } From b9b26e4b14d8cf1687d7a1969ab7f85b4d4a8301 Mon Sep 17 00:00:00 2001 From: Andrew Rosiclair Date: Mon, 28 Oct 2024 14:28:11 -0400 Subject: [PATCH 03/16] track created workspaces from the categorize tracked expense flow --- src/libs/actions/IOU.ts | 10 ++++++++++ src/pages/iou/request/step/IOURequestStepAmount.tsx | 1 + .../iou/request/step/IOURequestStepConfirmation.tsx | 3 +++ src/pages/iou/request/step/IOURequestStepDistance.tsx | 1 + .../request/step/IOURequestStepScan/index.native.tsx | 2 ++ .../iou/request/step/IOURequestStepScan/index.tsx | 2 ++ 6 files changed, 19 insertions(+) diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 7ce9b9dfb272..c2432f63787e 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -36,6 +36,7 @@ import DateUtils from '@libs/DateUtils'; import DistanceRequestUtils from '@libs/DistanceRequestUtils'; import * as ErrorUtils from '@libs/ErrorUtils'; import * as FileUtils from '@libs/fileDownload/FileUtils'; +import GoogleTagManager from '@libs/GoogleTagManager'; import * as IOUUtils from '@libs/IOUUtils'; import * as LocalePhoneNumber from '@libs/LocalePhoneNumber'; import * as Localize from '@libs/Localize'; @@ -3414,6 +3415,7 @@ function categorizeTrackedExpense( comment: string, merchant: string, created: string, + isDraftPolicy: boolean, category?: string, tag?: string, taxCode = '', @@ -3470,6 +3472,12 @@ function categorizeTrackedExpense( }; API.write(WRITE_COMMANDS.CATEGORIZE_TRACKED_EXPENSE, parameters, {optimisticData, successData, failureData}); + + // If a draft policy was used, then the CategorizeTrackedExpense command will create a real one + // so let's track that conversion here + if (isDraftPolicy) { + GoogleTagManager.publishEvent('workspace_created', userAccountID); + } } function shareTrackedExpense( @@ -3769,6 +3777,7 @@ function trackExpense( payeeAccountID: number, participant: Participant, comment: string, + isDraftPolicy: boolean, receipt?: Receipt, category?: string, tag?: string, @@ -3864,6 +3873,7 @@ function trackExpense( comment, merchant, created, + isDraftPolicy, category, tag, taxCode, diff --git a/src/pages/iou/request/step/IOURequestStepAmount.tsx b/src/pages/iou/request/step/IOURequestStepAmount.tsx index ce3d03138dde..f5424c67a1f7 100644 --- a/src/pages/iou/request/step/IOURequestStepAmount.tsx +++ b/src/pages/iou/request/step/IOURequestStepAmount.tsx @@ -249,6 +249,7 @@ function IOURequestStepAmount({ currentUserPersonalDetails.accountID, participants.at(0) ?? {}, '', + false, ); return; } diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index 942b472734a2..3398670a4a61 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -63,6 +63,7 @@ function IOURequestStepConfirmation({ const report = reportReal ?? reportDraft; const policy = policyReal ?? policyDraft; + const isDraftPolicy = policy === policyDraft; const policyCategories = policyCategoriesReal ?? policyCategoriesDraft; const styles = useThemeStyles(); @@ -287,6 +288,7 @@ function IOURequestStepConfirmation({ currentUserPersonalDetails.accountID, participant, trimmedComment, + isDraftPolicy, receiptObj, transaction.category, transaction.tag, @@ -317,6 +319,7 @@ function IOURequestStepConfirmation({ policyCategories, action, customUnitRateID, + isDraftPolicy, ], ); diff --git a/src/pages/iou/request/step/IOURequestStepDistance.tsx b/src/pages/iou/request/step/IOURequestStepDistance.tsx index 899f024de4be..dabe561aa7e4 100644 --- a/src/pages/iou/request/step/IOURequestStepDistance.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistance.tsx @@ -315,6 +315,7 @@ function IOURequestStepDistance({ currentUserPersonalDetails.accountID, participant, '', + false, {}, '', '', diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx index db7aac8268e6..7b6bcd3ac3da 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx @@ -246,6 +246,7 @@ function IOURequestStepScan({ currentUserPersonalDetails.accountID, participant, '', + false, receipt, ); } else { @@ -328,6 +329,7 @@ function IOURequestStepScan({ currentUserPersonalDetails.accountID, participant, '', + false, receipt, '', '', diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.tsx index 1f71f174dd23..1099a78d8dc9 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.tsx @@ -279,6 +279,7 @@ function IOURequestStepScan({ currentUserPersonalDetails.accountID, participant, '', + false, receipt, ); } else { @@ -362,6 +363,7 @@ function IOURequestStepScan({ currentUserPersonalDetails.accountID, participant, '', + false, receipt, '', '', From a633ea433407cc78751d89490d2ab2d7d266c0c8 Mon Sep 17 00:00:00 2001 From: Andrew Rosiclair Date: Mon, 28 Oct 2024 14:36:33 -0400 Subject: [PATCH 04/16] track paid adoption --- src/libs/actions/PaymentMethods.ts | 28 ++++++++++++------- .../Subscription/PaymentCard/index.tsx | 28 +++++++++++-------- .../settings/Wallet/AddDebitCardPage.tsx | 13 +++++++-- 3 files changed, 45 insertions(+), 24 deletions(-) diff --git a/src/libs/actions/PaymentMethods.ts b/src/libs/actions/PaymentMethods.ts index 893540e1dfac..509fd56024e7 100644 --- a/src/libs/actions/PaymentMethods.ts +++ b/src/libs/actions/PaymentMethods.ts @@ -16,6 +16,7 @@ import type { } from '@libs/API/parameters'; import {READ_COMMANDS, SIDE_EFFECT_REQUEST_COMMANDS, WRITE_COMMANDS} from '@libs/API/types'; import * as CardUtils from '@libs/CardUtils'; +import GoogleTagManager from '@libs/GoogleTagManager'; import Navigation from '@libs/Navigation/Navigation'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -159,7 +160,7 @@ function makeDefaultPaymentMethod(bankAccountID: number, fundID: number, previou * Calls the API to add a new card. * */ -function addPaymentCard(params: PaymentCardParams) { +function addPaymentCard(accountID: number, params: PaymentCardParams) { const cardMonth = CardUtils.getMonthFromExpirationDateString(params.expirationDate); const cardYear = CardUtils.getYearFromExpirationDateString(params.expirationDate); @@ -203,21 +204,26 @@ function addPaymentCard(params: PaymentCardParams) { successData, failureData, }); + + GoogleTagManager.publishEvent('paid_adoption', accountID); } /** * Calls the API to add a new card. * */ -function addSubscriptionPaymentCard(cardData: { - cardNumber: string; - cardYear: string; - cardMonth: string; - cardCVV: string; - addressName: string; - addressZip: string; - currency: ValueOf; -}) { +function addSubscriptionPaymentCard( + accountID: number, + cardData: { + cardNumber: string; + cardYear: string; + cardMonth: string; + cardCVV: string; + addressName: string; + addressZip: string; + currency: ValueOf; + }, +) { const {cardNumber, cardYear, cardMonth, cardCVV, addressName, addressZip, currency} = cardData; const parameters: AddPaymentCardParams = { @@ -265,6 +271,8 @@ function addSubscriptionPaymentCard(cardData: { failureData, }); } + + GoogleTagManager.publishEvent('paid_adoption', accountID); } /** diff --git a/src/pages/settings/Subscription/PaymentCard/index.tsx b/src/pages/settings/Subscription/PaymentCard/index.tsx index cdeb1ae0a580..da977f170a9b 100644 --- a/src/pages/settings/Subscription/PaymentCard/index.tsx +++ b/src/pages/settings/Subscription/PaymentCard/index.tsx @@ -27,6 +27,7 @@ function AddPaymentCard() { const styles = useThemeStyles(); const {translate} = useLocalize(); const [privateSubscription] = useOnyx(ONYXKEYS.NVP_PRIVATE_SUBSCRIPTION); + const [accountID] = useOnyx(ONYXKEYS.SESSION, {selector: (session) => session?.accountID ?? 0}); const subscriptionPlan = useSubscriptionPlan(); const subscriptionPrice = useSubscriptionPrice(); @@ -43,18 +44,21 @@ function AddPaymentCard() { }; }, []); - const addPaymentCard = useCallback((values: FormOnyxValues) => { - const cardData = { - cardNumber: CardUtils.getMCardNumberString(values.cardNumber), - cardMonth: CardUtils.getMonthFromExpirationDateString(values.expirationDate), - cardYear: CardUtils.getYearFromExpirationDateString(values.expirationDate), - cardCVV: values.securityCode, - addressName: values.nameOnCard, - addressZip: values.addressZipCode, - currency: values.currency ?? CONST.PAYMENT_CARD_CURRENCY.USD, - }; - PaymentMethods.addSubscriptionPaymentCard(cardData); - }, []); + const addPaymentCard = useCallback( + (values: FormOnyxValues) => { + const cardData = { + cardNumber: CardUtils.getMCardNumberString(values.cardNumber), + cardMonth: CardUtils.getMonthFromExpirationDateString(values.expirationDate), + cardYear: CardUtils.getYearFromExpirationDateString(values.expirationDate), + cardCVV: values.securityCode, + addressName: values.nameOnCard, + addressZip: values.addressZipCode, + currency: values.currency ?? CONST.PAYMENT_CARD_CURRENCY.USD, + }; + PaymentMethods.addSubscriptionPaymentCard(accountID ?? 0, cardData); + }, + [accountID], + ); const [formData] = useOnyx(ONYXKEYS.FORMS.ADD_PAYMENT_CARD_FORM); const prevFormDataSetupComplete = usePrevious(!!formData?.setupComplete); diff --git a/src/pages/settings/Wallet/AddDebitCardPage.tsx b/src/pages/settings/Wallet/AddDebitCardPage.tsx index d785df0ea324..042459f9ac72 100644 --- a/src/pages/settings/Wallet/AddDebitCardPage.tsx +++ b/src/pages/settings/Wallet/AddDebitCardPage.tsx @@ -1,4 +1,4 @@ -import React, {useEffect, useRef} from 'react'; +import React, {useCallback, useEffect, useRef} from 'react'; import {useOnyx} from 'react-native-onyx'; import PaymentCardForm from '@components/AddPaymentCard/PaymentCardForm'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; @@ -6,6 +6,7 @@ import type {AnimatedTextInputRef} from '@components/RNTextInput'; import ScreenWrapper from '@components/ScreenWrapper'; import useLocalize from '@hooks/useLocalize'; import usePrevious from '@hooks/usePrevious'; +import type {PaymentCardParams} from '@libs/API/parameters'; import Navigation from '@libs/Navigation/Navigation'; import NotFoundPage from '@pages/ErrorPage/NotFoundPage'; import * as PaymentMethods from '@userActions/PaymentMethods'; @@ -19,6 +20,7 @@ function DebitCardPage() { const [formData] = useOnyx(ONYXKEYS.FORMS.ADD_PAYMENT_CARD_FORM); const prevFormDataSetupComplete = usePrevious(!!formData?.setupComplete); const nameOnCardRef = useRef(null); + const [accountID] = useOnyx(ONYXKEYS.SESSION, {selector: (session) => session?.accountID ?? 0}); /** * Reset the form values on the mount and unmount so that old errors don't show when this form is displayed again. @@ -39,6 +41,13 @@ function DebitCardPage() { PaymentMethods.continueSetup(); }, [prevFormDataSetupComplete, formData?.setupComplete]); + const addPaymentCard = useCallback( + (params: PaymentCardParams) => { + PaymentMethods.addPaymentCard(accountID ?? 0, params); + }, + [accountID], + ); + return ( nameOnCardRef.current?.focus()} @@ -55,7 +64,7 @@ function DebitCardPage() { showAddressField isDebitCard showStateSelector - addPaymentCard={PaymentMethods.addPaymentCard} + addPaymentCard={addPaymentCard} submitButtonText={translate('common.save')} /> From 2ac76996bd6715544631a96de5ffbfde6f41bf19 Mon Sep 17 00:00:00 2001 From: Andrew Rosiclair Date: Mon, 28 Oct 2024 14:53:56 -0400 Subject: [PATCH 05/16] mock firebase analytics --- __mocks__/@react-native-firebase/analytics.ts | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 __mocks__/@react-native-firebase/analytics.ts diff --git a/__mocks__/@react-native-firebase/analytics.ts b/__mocks__/@react-native-firebase/analytics.ts new file mode 100644 index 000000000000..1cc35724c726 --- /dev/null +++ b/__mocks__/@react-native-firebase/analytics.ts @@ -0,0 +1,5 @@ +export default function analytics() { + return { + logEvent: jest.fn(), + }; +} From 13101ca104adf901ae75cc851d58ab53ddfa0075 Mon Sep 17 00:00:00 2001 From: Andrew Rosiclair Date: Mon, 28 Oct 2024 15:17:40 -0400 Subject: [PATCH 06/16] replace withOnyx with useOnyx --- .../iou/request/step/IOURequestStepAmount.tsx | 65 ++++--------------- 1 file changed, 11 insertions(+), 54 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepAmount.tsx b/src/pages/iou/request/step/IOURequestStepAmount.tsx index f5424c67a1f7..ea2b58931039 100644 --- a/src/pages/iou/request/step/IOURequestStepAmount.tsx +++ b/src/pages/iou/request/step/IOURequestStepAmount.tsx @@ -1,7 +1,7 @@ import {useFocusEffect} from '@react-navigation/native'; import React, {useCallback, useEffect, useMemo, useRef} from 'react'; import type {OnyxEntry} from 'react-native-onyx'; -import {useOnyx, withOnyx} from 'react-native-onyx'; +import {useOnyx} from 'react-native-onyx'; import type {BaseTextInputRef} from '@components/TextInput/BaseTextInput/types'; import withCurrentUserPersonalDetails from '@components/withCurrentUserPersonalDetails'; import type {WithCurrentUserPersonalDetailsProps} from '@components/withCurrentUserPersonalDetails'; @@ -32,25 +32,7 @@ type AmountParams = { paymentMethod?: PaymentMethodType; }; -type IOURequestStepAmountOnyxProps = { - /** The draft transaction that holds data to be persisted on the current transaction */ - splitDraftTransaction: OnyxEntry; - - /** Whether the confirmation step should be skipped */ - skipConfirmation: OnyxEntry; - - /** The draft transaction object being modified in Onyx */ - draftTransaction: OnyxEntry; - - /** Personal details of all users */ - personalDetails: OnyxEntry; - - /** The policy which the user has access to and which the report is tied to */ - policy: OnyxEntry; -}; - -type IOURequestStepAmountProps = IOURequestStepAmountOnyxProps & - WithCurrentUserPersonalDetailsProps & +type IOURequestStepAmountProps = WithCurrentUserPersonalDetailsProps & WithWritableReportOrNotFoundProps & { /** The transaction object being modified in Onyx */ transaction: OnyxEntry; @@ -62,15 +44,10 @@ type IOURequestStepAmountProps = IOURequestStepAmountOnyxProps & function IOURequestStepAmount({ report, route: { - params: {iouType, reportID, transactionID, backTo, pageIndex, action, currency: selectedCurrency = ''}, + params: {iouType, reportID, transactionID = '-1', backTo, pageIndex, action, currency: selectedCurrency = ''}, }, transaction, - policy, - personalDetails, currentUserPersonalDetails, - splitDraftTransaction, - skipConfirmation, - draftTransaction, shouldKeepUserInput = false, }: IOURequestStepAmountProps) { const {translate} = useLocalize(); @@ -78,7 +55,14 @@ function IOURequestStepAmount({ const focusTimeoutRef = useRef(null); const isSaveButtonPressed = useRef(false); const iouRequestType = getRequestType(transaction); + const policyID = report?.policyID ?? '-1'; + const [reportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report?.reportID ?? -1}`); + const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`); + const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST); + const [draftTransaction] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`); + const [splitDraftTransaction] = useOnyx(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transactionID}`); + const [skipConfirmation] = useOnyx(`${ONYXKEYS.COLLECTION.SKIP_CONFIRMATION}${transactionID}`); const isEditing = action === CONST.IOU.ACTION.EDIT; const isSplitBill = iouType === CONST.IOU.TYPE.SPLIT; @@ -333,34 +317,7 @@ function IOURequestStepAmount({ IOURequestStepAmount.displayName = 'IOURequestStepAmount'; -const IOURequestStepAmountWithOnyx = withOnyx({ - splitDraftTransaction: { - key: ({route}) => { - const transactionID = route.params.transactionID ?? -1; - return `${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transactionID}`; - }, - }, - draftTransaction: { - key: ({route}) => { - const transactionID = route.params.transactionID ?? 0; - return `${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`; - }, - }, - skipConfirmation: { - key: ({route}) => { - const transactionID = route.params.transactionID ?? -1; - return `${ONYXKEYS.COLLECTION.SKIP_CONFIRMATION}${transactionID}`; - }, - }, - personalDetails: { - key: ONYXKEYS.PERSONAL_DETAILS_LIST, - }, - policy: { - key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report ? report.policyID : '-1'}`, - }, -})(IOURequestStepAmount); - -const IOURequestStepAmountWithCurrentUserPersonalDetails = withCurrentUserPersonalDetails(IOURequestStepAmountWithOnyx); +const IOURequestStepAmountWithCurrentUserPersonalDetails = withCurrentUserPersonalDetails(IOURequestStepAmount); // eslint-disable-next-line rulesdir/no-negated-variables const IOURequestStepAmountWithWritableReportOrNotFound = withWritableReportOrNotFound(IOURequestStepAmountWithCurrentUserPersonalDetails, true); // eslint-disable-next-line rulesdir/no-negated-variables From 4d135d403560106c45d48a18981af387f7427cde Mon Sep 17 00:00:00 2001 From: Andrew Rosiclair Date: Mon, 28 Oct 2024 16:24:08 -0400 Subject: [PATCH 07/16] add sign_up test --- tests/unit/GoogleTagManagerTest.tsx | 46 +++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 tests/unit/GoogleTagManagerTest.tsx diff --git a/tests/unit/GoogleTagManagerTest.tsx b/tests/unit/GoogleTagManagerTest.tsx new file mode 100644 index 000000000000..90f2e74c84d4 --- /dev/null +++ b/tests/unit/GoogleTagManagerTest.tsx @@ -0,0 +1,46 @@ +import {NavigationContainer} from '@react-navigation/native'; +import {render} from '@testing-library/react-native'; +import Onyx from 'react-native-onyx'; +import GoogleTagManager from '@libs/GoogleTagManager'; +import OnboardingModalNavigator from '@libs/Navigation/AppNavigator/Navigators/OnboardingModalNavigator'; +import ONYXKEYS from '@src/ONYXKEYS'; + +jest.mock('@libs/GoogleTagManager'); + +// Mock the Overlay since it doesn't work in tests +jest.mock('@libs/Navigation/AppNavigator/Navigators/Overlay'); + +describe('GoogleTagManagerTest', () => { + beforeAll(() => { + Onyx.init({ + keys: ONYXKEYS, + }); + }); + + it('publishes a sign_up event during onboarding', async () => { + // Given a new signed in account + const accountID = 123456; + await Onyx.merge(ONYXKEYS.SESSION, {accountID}); + + // When we render the OnboardingModal a few times + const {rerender} = render( + + + , + ); + rerender( + + + , + ); + rerender( + + + , + ); + + // Then we publish the sign_up event only once + expect(GoogleTagManager.publishEvent).toBeCalledTimes(1); + expect(GoogleTagManager.publishEvent).toBeCalledWith('sign_up', accountID); + }); +}); From 9f1481294e23efe39e24a8a826b8b83a47fc1b53 Mon Sep 17 00:00:00 2001 From: Andrew Rosiclair Date: Wed, 30 Oct 2024 17:21:05 -0400 Subject: [PATCH 08/16] add createWorkspace test --- tests/unit/GoogleTagManagerTest.tsx | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tests/unit/GoogleTagManagerTest.tsx b/tests/unit/GoogleTagManagerTest.tsx index 90f2e74c84d4..9ae95276d54f 100644 --- a/tests/unit/GoogleTagManagerTest.tsx +++ b/tests/unit/GoogleTagManagerTest.tsx @@ -1,9 +1,11 @@ import {NavigationContainer} from '@react-navigation/native'; import {render} from '@testing-library/react-native'; import Onyx from 'react-native-onyx'; +import * as Policy from '@libs/actions/Policy/Policy'; import GoogleTagManager from '@libs/GoogleTagManager'; import OnboardingModalNavigator from '@libs/Navigation/AppNavigator/Navigators/OnboardingModalNavigator'; import ONYXKEYS from '@src/ONYXKEYS'; +import waitForBatchedUpdates from '../utils/waitForBatchedUpdates'; jest.mock('@libs/GoogleTagManager'); @@ -16,6 +18,10 @@ describe('GoogleTagManagerTest', () => { keys: ONYXKEYS, }); }); + beforeEach(() => { + jest.clearAllMocks(); + return Onyx.clear(); + }); it('publishes a sign_up event during onboarding', async () => { // Given a new signed in account @@ -43,4 +49,21 @@ describe('GoogleTagManagerTest', () => { expect(GoogleTagManager.publishEvent).toBeCalledTimes(1); expect(GoogleTagManager.publishEvent).toBeCalledWith('sign_up', accountID); }); + + it('publishes a workspace_created event when the user creates their first one', async () => { + // Given a new signed in account + const accountID = 123456; + await Onyx.merge(ONYXKEYS.SESSION, {accountID}); + + // When we run the createWorkspace action a few times + Policy.createWorkspace(); + await waitForBatchedUpdates(); + Policy.createWorkspace(); + await waitForBatchedUpdates(); + Policy.createWorkspace(); + + // Then we publish the sign_up event only once + expect(GoogleTagManager.publishEvent).toBeCalledTimes(1); + expect(GoogleTagManager.publishEvent).toBeCalledWith('workspace_created', accountID); + }); }); From 86a4dbee5b09b37a9721dad6c37f8301451070ca Mon Sep 17 00:00:00 2001 From: Andrew Rosiclair Date: Wed, 30 Oct 2024 17:39:57 -0400 Subject: [PATCH 09/16] add test for categorizing tracked expense --- tests/unit/GoogleTagManagerTest.tsx | 43 ++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/tests/unit/GoogleTagManagerTest.tsx b/tests/unit/GoogleTagManagerTest.tsx index 9ae95276d54f..ebfd1397acf2 100644 --- a/tests/unit/GoogleTagManagerTest.tsx +++ b/tests/unit/GoogleTagManagerTest.tsx @@ -1,9 +1,11 @@ import {NavigationContainer} from '@react-navigation/native'; import {render} from '@testing-library/react-native'; import Onyx from 'react-native-onyx'; +import * as IOU from '@libs/actions/IOU'; import * as Policy from '@libs/actions/Policy/Policy'; import GoogleTagManager from '@libs/GoogleTagManager'; import OnboardingModalNavigator from '@libs/Navigation/AppNavigator/Navigators/OnboardingModalNavigator'; +import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import waitForBatchedUpdates from '../utils/waitForBatchedUpdates'; @@ -62,7 +64,46 @@ describe('GoogleTagManagerTest', () => { await waitForBatchedUpdates(); Policy.createWorkspace(); - // Then we publish the sign_up event only once + // Then we publish a workspace_created event only once + expect(GoogleTagManager.publishEvent).toBeCalledTimes(1); + expect(GoogleTagManager.publishEvent).toBeCalledWith('workspace_created', accountID); + }); + + it('publishes a workspace_created event when tracking an expense on a draft policy', async () => { + // Given a new signed in account + const accountID = 123456; + await Onyx.merge(ONYXKEYS.SESSION, {accountID}); + + // When we categorize a tracked expense with a draft policy + IOU.trackExpense( + {reportID: '123'}, + 1000, + 'USD', + '2024-10-30', + 'merchant', + undefined, + 0, + {accountID}, + 'comment', + true, + undefined, + 'category', + 'tag', + 'taxCode', + 0, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + CONST.IOU.ACTION.CATEGORIZE, + 'actionableWhisperReportActionID', + {actionName: 'IOU', reportActionID: 'linkedTrackedExpenseReportAction', created: '2024-10-30'}, + 'linkedTrackedExpenseReportID', + ); + + // Then we publish a workspace_created event only once expect(GoogleTagManager.publishEvent).toBeCalledTimes(1); expect(GoogleTagManager.publishEvent).toBeCalledWith('workspace_created', accountID); }); From 45df579ce56d13cf7f2caf44b762b7e05eb5d0eb Mon Sep 17 00:00:00 2001 From: Andrew Rosiclair Date: Wed, 30 Oct 2024 17:52:07 -0400 Subject: [PATCH 10/16] add paid_adoption tests --- tests/unit/GoogleTagManagerTest.tsx | 41 +++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/tests/unit/GoogleTagManagerTest.tsx b/tests/unit/GoogleTagManagerTest.tsx index ebfd1397acf2..bd2cda89aeed 100644 --- a/tests/unit/GoogleTagManagerTest.tsx +++ b/tests/unit/GoogleTagManagerTest.tsx @@ -2,6 +2,7 @@ import {NavigationContainer} from '@react-navigation/native'; import {render} from '@testing-library/react-native'; import Onyx from 'react-native-onyx'; import * as IOU from '@libs/actions/IOU'; +import * as PaymentMethods from '@libs/actions/PaymentMethods'; import * as Policy from '@libs/actions/Policy/Policy'; import GoogleTagManager from '@libs/GoogleTagManager'; import OnboardingModalNavigator from '@libs/Navigation/AppNavigator/Navigators/OnboardingModalNavigator'; @@ -107,4 +108,44 @@ describe('GoogleTagManagerTest', () => { expect(GoogleTagManager.publishEvent).toBeCalledTimes(1); expect(GoogleTagManager.publishEvent).toBeCalledWith('workspace_created', accountID); }); + + it('publishes a paid_adoption event when a payment card is added', async () => { + // Given a new signed in account + const accountID = 123456; + await Onyx.merge(ONYXKEYS.SESSION, {accountID}); + + // When we add a payment card + PaymentMethods.addPaymentCard(accountID, { + expirationDate: '2077-10-30', + addressZipCode: 'addressZipCode', + cardNumber: 'cardNumber', + nameOnCard: 'nameOnCard', + securityCode: 'securityCode', + }); + + // Then we publish a paid_adoption event only once + expect(GoogleTagManager.publishEvent).toBeCalledTimes(1); + expect(GoogleTagManager.publishEvent).toBeCalledWith('paid_adoption', accountID); + }); + + it('publishes a paid_adoption event when a subscription payment card is added', async () => { + // Given a new signed in account + const accountID = 123456; + await Onyx.merge(ONYXKEYS.SESSION, {accountID}); + + // When we add a payment card + PaymentMethods.addSubscriptionPaymentCard(accountID, { + cardNumber: 'cardNumber', + cardYear: 'cardYear', + cardMonth: 'cardMonth', + cardCVV: 'cardCVV', + addressName: 'addressName', + addressZip: 'addressZip', + currency: 'USD', + }); + + // Then we publish a paid_adoption event only once + expect(GoogleTagManager.publishEvent).toBeCalledTimes(1); + expect(GoogleTagManager.publishEvent).toBeCalledWith('paid_adoption', accountID); + }); }); From c4727b0a184e4383afc7662719e1caa7f28199ff Mon Sep 17 00:00:00 2001 From: Andrew Rosiclair Date: Wed, 30 Oct 2024 17:54:58 -0400 Subject: [PATCH 11/16] simplify test names --- tests/unit/GoogleTagManagerTest.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/unit/GoogleTagManagerTest.tsx b/tests/unit/GoogleTagManagerTest.tsx index bd2cda89aeed..f00bb4a91f64 100644 --- a/tests/unit/GoogleTagManagerTest.tsx +++ b/tests/unit/GoogleTagManagerTest.tsx @@ -26,7 +26,7 @@ describe('GoogleTagManagerTest', () => { return Onyx.clear(); }); - it('publishes a sign_up event during onboarding', async () => { + test('sign_up', async () => { // Given a new signed in account const accountID = 123456; await Onyx.merge(ONYXKEYS.SESSION, {accountID}); @@ -53,7 +53,7 @@ describe('GoogleTagManagerTest', () => { expect(GoogleTagManager.publishEvent).toBeCalledWith('sign_up', accountID); }); - it('publishes a workspace_created event when the user creates their first one', async () => { + test('workspace_created', async () => { // Given a new signed in account const accountID = 123456; await Onyx.merge(ONYXKEYS.SESSION, {accountID}); @@ -70,7 +70,7 @@ describe('GoogleTagManagerTest', () => { expect(GoogleTagManager.publishEvent).toBeCalledWith('workspace_created', accountID); }); - it('publishes a workspace_created event when tracking an expense on a draft policy', async () => { + test('workspace_created - categorizeTrackedExpense', async () => { // Given a new signed in account const accountID = 123456; await Onyx.merge(ONYXKEYS.SESSION, {accountID}); @@ -109,7 +109,7 @@ describe('GoogleTagManagerTest', () => { expect(GoogleTagManager.publishEvent).toBeCalledWith('workspace_created', accountID); }); - it('publishes a paid_adoption event when a payment card is added', async () => { + test('paid_adoption - addPaymentCard', async () => { // Given a new signed in account const accountID = 123456; await Onyx.merge(ONYXKEYS.SESSION, {accountID}); @@ -128,7 +128,7 @@ describe('GoogleTagManagerTest', () => { expect(GoogleTagManager.publishEvent).toBeCalledWith('paid_adoption', accountID); }); - it('publishes a paid_adoption event when a subscription payment card is added', async () => { + test('paid_adoption - addSubscriptionPaymentCard', async () => { // Given a new signed in account const accountID = 123456; await Onyx.merge(ONYXKEYS.SESSION, {accountID}); From edada2d4cd132ae20481656aa6935aeb1a1f1575 Mon Sep 17 00:00:00 2001 From: Andrew Rosiclair Date: Wed, 30 Oct 2024 17:58:10 -0400 Subject: [PATCH 12/16] share onyx state across tests --- tests/unit/GoogleTagManagerTest.tsx | 34 ++++++++--------------------- 1 file changed, 9 insertions(+), 25 deletions(-) diff --git a/tests/unit/GoogleTagManagerTest.tsx b/tests/unit/GoogleTagManagerTest.tsx index f00bb4a91f64..4cccd3389cba 100644 --- a/tests/unit/GoogleTagManagerTest.tsx +++ b/tests/unit/GoogleTagManagerTest.tsx @@ -16,21 +16,21 @@ jest.mock('@libs/GoogleTagManager'); jest.mock('@libs/Navigation/AppNavigator/Navigators/Overlay'); describe('GoogleTagManagerTest', () => { + const accountID = 123456; + beforeAll(() => { Onyx.init({ keys: ONYXKEYS, + initialKeyStates: { + session: {accountID}, + }, }); }); beforeEach(() => { jest.clearAllMocks(); - return Onyx.clear(); }); - test('sign_up', async () => { - // Given a new signed in account - const accountID = 123456; - await Onyx.merge(ONYXKEYS.SESSION, {accountID}); - + test('sign_up', () => { // When we render the OnboardingModal a few times const {rerender} = render( @@ -54,10 +54,6 @@ describe('GoogleTagManagerTest', () => { }); test('workspace_created', async () => { - // Given a new signed in account - const accountID = 123456; - await Onyx.merge(ONYXKEYS.SESSION, {accountID}); - // When we run the createWorkspace action a few times Policy.createWorkspace(); await waitForBatchedUpdates(); @@ -70,11 +66,7 @@ describe('GoogleTagManagerTest', () => { expect(GoogleTagManager.publishEvent).toBeCalledWith('workspace_created', accountID); }); - test('workspace_created - categorizeTrackedExpense', async () => { - // Given a new signed in account - const accountID = 123456; - await Onyx.merge(ONYXKEYS.SESSION, {accountID}); - + test('workspace_created - categorizeTrackedExpense', () => { // When we categorize a tracked expense with a draft policy IOU.trackExpense( {reportID: '123'}, @@ -109,11 +101,7 @@ describe('GoogleTagManagerTest', () => { expect(GoogleTagManager.publishEvent).toBeCalledWith('workspace_created', accountID); }); - test('paid_adoption - addPaymentCard', async () => { - // Given a new signed in account - const accountID = 123456; - await Onyx.merge(ONYXKEYS.SESSION, {accountID}); - + test('paid_adoption - addPaymentCard', () => { // When we add a payment card PaymentMethods.addPaymentCard(accountID, { expirationDate: '2077-10-30', @@ -128,11 +116,7 @@ describe('GoogleTagManagerTest', () => { expect(GoogleTagManager.publishEvent).toBeCalledWith('paid_adoption', accountID); }); - test('paid_adoption - addSubscriptionPaymentCard', async () => { - // Given a new signed in account - const accountID = 123456; - await Onyx.merge(ONYXKEYS.SESSION, {accountID}); - + test('paid_adoption - addSubscriptionPaymentCard', () => { // When we add a payment card PaymentMethods.addSubscriptionPaymentCard(accountID, { cardNumber: 'cardNumber', From e6fc1f0273a3e8b44f3bf8f6f2dc3628c0d7e2a7 Mon Sep 17 00:00:00 2001 From: Andrew Rosiclair Date: Thu, 31 Oct 2024 12:55:12 -0400 Subject: [PATCH 13/16] filter out personal policies --- src/libs/actions/Policy/Policy.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/Policy/Policy.ts b/src/libs/actions/Policy/Policy.ts index 2bdf9a208353..62f3212cbca6 100644 --- a/src/libs/actions/Policy/Policy.ts +++ b/src/libs/actions/Policy/Policy.ts @@ -3738,7 +3738,7 @@ function setWorkspaceEReceiptsEnabled(policyID: string, eReceipts: boolean) { } function getAdminPolicies(): Policy[] { - return Object.values(allPolicies ?? {}).filter((policy): policy is Policy => !!policy && policy.role === CONST.POLICY.ROLE.ADMIN); + return Object.values(allPolicies ?? {}).filter((policy): policy is Policy => !!policy && policy.role === CONST.POLICY.ROLE.ADMIN && policy.type !== CONST.POLICY.TYPE.PERSONAL); } function getAdminPoliciesConnectedToSageIntacct(): Policy[] { From 117f6c009b5f70d4a2f12ede7a32ebb8eb03dd50 Mon Sep 17 00:00:00 2001 From: Andrew Rosiclair Date: Wed, 6 Nov 2024 16:49:12 -0500 Subject: [PATCH 14/16] load third party scripts in both staging and prod --- config/webpack/webpack.common.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/webpack/webpack.common.ts b/config/webpack/webpack.common.ts index ab5c304fcd1e..8aa8f5aa566c 100644 --- a/config/webpack/webpack.common.ts +++ b/config/webpack/webpack.common.ts @@ -84,7 +84,7 @@ const getCommonConfiguration = ({file = '.env', platform = 'web'}: Environment): isWeb: platform === 'web', isProduction: file === '.env.production', isStaging: file === '.env.staging', - useThirdPartyScripts: process.env.USE_THIRD_PARTY_SCRIPTS === 'true' || (platform === 'web' && file === '.env.production'), + useThirdPartyScripts: process.env.USE_THIRD_PARTY_SCRIPTS === 'true' || (platform === 'web' && ['.env.production', '.env.staging'].includes(file)), }), new PreloadWebpackPlugin({ rel: 'preload', From d4e4e904f5122a834bc6eac18c427b4162eab5cc Mon Sep 17 00:00:00 2001 From: Andrew Rosiclair Date: Thu, 7 Nov 2024 09:50:49 -0500 Subject: [PATCH 15/16] fix bad merge --- src/pages/iou/request/step/IOURequestStepAmount.tsx | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepAmount.tsx b/src/pages/iou/request/step/IOURequestStepAmount.tsx index 9abc22fedb3b..70a9c545dc8e 100644 --- a/src/pages/iou/request/step/IOURequestStepAmount.tsx +++ b/src/pages/iou/request/step/IOURequestStepAmount.tsx @@ -51,12 +51,6 @@ function IOURequestStepAmount({ currentUserPersonalDetails, shouldKeepUserInput = false, }: IOURequestStepAmountProps) { - const [splitDraftTransaction] = useOnyx(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transactionID ?? -1}`); - const [draftTransaction] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID ?? -1}`); - const [skipConfirmation] = useOnyx(`${ONYXKEYS.COLLECTION.SKIP_CONFIRMATION}${transactionID ?? -1}`); - const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST); - const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${report ? report.policyID : -1}`); - const {translate} = useLocalize(); const textInput = useRef(null); const focusTimeoutRef = useRef(null); From 447d06f30416f64b774bbd1dcd788df979330f4c Mon Sep 17 00:00:00 2001 From: Andrew Rosiclair Date: Thu, 7 Nov 2024 10:08:36 -0500 Subject: [PATCH 16/16] use consts for event names --- src/CONST.ts | 8 ++++++++ src/libs/GoogleTagManager/types.ts | 5 ++++- .../AppNavigator/Navigators/OnboardingModalNavigator.tsx | 2 +- src/libs/actions/IOU.ts | 2 +- src/libs/actions/PaymentMethods.ts | 4 ++-- src/libs/actions/Policy/Policy.ts | 2 +- tests/unit/GoogleTagManagerTest.tsx | 8 ++++---- 7 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index ad119874c461..284eb1cee0ee 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -6202,6 +6202,14 @@ const CONST = { HAS_VIOLATIONS: 'hasViolations', HAS_TRANSACTION_THREAD_VIOLATIONS: 'hasTransactionThreadViolations', }, + + ANALYTICS: { + EVENT: { + SIGN_UP: 'sign_up', + WORKSPACE_CREATED: 'workspace_created', + PAID_ADOPTION: 'paid_adoption', + }, + }, } as const; type Country = keyof typeof CONST.ALL_COUNTRIES; diff --git a/src/libs/GoogleTagManager/types.ts b/src/libs/GoogleTagManager/types.ts index a4af6aa00330..42e40099e93a 100644 --- a/src/libs/GoogleTagManager/types.ts +++ b/src/libs/GoogleTagManager/types.ts @@ -1,8 +1,11 @@ +import type {ValueOf} from 'type-fest'; +import type CONST from '@src/CONST'; + /** * An event that can be published to Google Tag Manager. New events must be configured in GTM before they can be used * in the app. */ -type GoogleTagManagerEvent = 'sign_up' | 'workspace_created' | 'paid_adoption'; +type GoogleTagManagerEvent = ValueOf; type GoogleTagManagerModule = { publishEvent: (event: GoogleTagManagerEvent, accountID: number) => void; diff --git a/src/libs/Navigation/AppNavigator/Navigators/OnboardingModalNavigator.tsx b/src/libs/Navigation/AppNavigator/Navigators/OnboardingModalNavigator.tsx index 7707effe45ea..401e6b6ec809 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/OnboardingModalNavigator.tsx +++ b/src/libs/Navigation/AppNavigator/Navigators/OnboardingModalNavigator.tsx @@ -35,7 +35,7 @@ function OnboardingModalNavigator() { return; } - GoogleTagManager.publishEvent('sign_up', accountID); + GoogleTagManager.publishEvent(CONST.ANALYTICS.EVENT.SIGN_UP, accountID); }, [accountID]); const handleOuterClick = useCallback(() => { diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 946cf241b758..06ca482e5f84 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -3477,7 +3477,7 @@ function categorizeTrackedExpense( // If a draft policy was used, then the CategorizeTrackedExpense command will create a real one // so let's track that conversion here if (isDraftPolicy) { - GoogleTagManager.publishEvent('workspace_created', userAccountID); + GoogleTagManager.publishEvent(CONST.ANALYTICS.EVENT.WORKSPACE_CREATED, userAccountID); } } diff --git a/src/libs/actions/PaymentMethods.ts b/src/libs/actions/PaymentMethods.ts index 509fd56024e7..e645267b32fd 100644 --- a/src/libs/actions/PaymentMethods.ts +++ b/src/libs/actions/PaymentMethods.ts @@ -205,7 +205,7 @@ function addPaymentCard(accountID: number, params: PaymentCardParams) { failureData, }); - GoogleTagManager.publishEvent('paid_adoption', accountID); + GoogleTagManager.publishEvent(CONST.ANALYTICS.EVENT.PAID_ADOPTION, accountID); } /** @@ -272,7 +272,7 @@ function addSubscriptionPaymentCard( }); } - GoogleTagManager.publishEvent('paid_adoption', accountID); + GoogleTagManager.publishEvent(CONST.ANALYTICS.EVENT.PAID_ADOPTION, accountID); } /** diff --git a/src/libs/actions/Policy/Policy.ts b/src/libs/actions/Policy/Policy.ts index 129e4c301e83..7e3e8e4c6d50 100644 --- a/src/libs/actions/Policy/Policy.ts +++ b/src/libs/actions/Policy/Policy.ts @@ -1841,7 +1841,7 @@ function createWorkspace(policyOwnerEmail = '', makeMeAdmin = false, policyName // Publish a workspace created event if this is their first policy if (getAdminPolicies().length === 0) { - GoogleTagManager.publishEvent('workspace_created', sessionAccountID); + GoogleTagManager.publishEvent(CONST.ANALYTICS.EVENT.WORKSPACE_CREATED, sessionAccountID); } return params; diff --git a/tests/unit/GoogleTagManagerTest.tsx b/tests/unit/GoogleTagManagerTest.tsx index 4cccd3389cba..dcb6bdea0eec 100644 --- a/tests/unit/GoogleTagManagerTest.tsx +++ b/tests/unit/GoogleTagManagerTest.tsx @@ -50,7 +50,7 @@ describe('GoogleTagManagerTest', () => { // Then we publish the sign_up event only once expect(GoogleTagManager.publishEvent).toBeCalledTimes(1); - expect(GoogleTagManager.publishEvent).toBeCalledWith('sign_up', accountID); + expect(GoogleTagManager.publishEvent).toBeCalledWith(CONST.ANALYTICS.EVENT.SIGN_UP, accountID); }); test('workspace_created', async () => { @@ -63,7 +63,7 @@ describe('GoogleTagManagerTest', () => { // Then we publish a workspace_created event only once expect(GoogleTagManager.publishEvent).toBeCalledTimes(1); - expect(GoogleTagManager.publishEvent).toBeCalledWith('workspace_created', accountID); + expect(GoogleTagManager.publishEvent).toBeCalledWith(CONST.ANALYTICS.EVENT.WORKSPACE_CREATED, accountID); }); test('workspace_created - categorizeTrackedExpense', () => { @@ -113,7 +113,7 @@ describe('GoogleTagManagerTest', () => { // Then we publish a paid_adoption event only once expect(GoogleTagManager.publishEvent).toBeCalledTimes(1); - expect(GoogleTagManager.publishEvent).toBeCalledWith('paid_adoption', accountID); + expect(GoogleTagManager.publishEvent).toBeCalledWith(CONST.ANALYTICS.EVENT.PAID_ADOPTION, accountID); }); test('paid_adoption - addSubscriptionPaymentCard', () => { @@ -130,6 +130,6 @@ describe('GoogleTagManagerTest', () => { // Then we publish a paid_adoption event only once expect(GoogleTagManager.publishEvent).toBeCalledTimes(1); - expect(GoogleTagManager.publishEvent).toBeCalledWith('paid_adoption', accountID); + expect(GoogleTagManager.publishEvent).toBeCalledWith(CONST.ANALYTICS.EVENT.PAID_ADOPTION, accountID); }); });