diff --git a/docs/analytics/screen-tracking.md b/docs/analytics/screen-tracking.md index f64ede98d4..5b1681f609 100644 --- a/docs/analytics/screen-tracking.md +++ b/docs/analytics/screen-tracking.md @@ -13,7 +13,7 @@ therefore there is no "one fits all" solution to screen tracking. The [React Navigation](https://reactnavigation.org/) library allows for various navigation techniques such as Stack, Tab, Native or even custom navigation. The `NavigationController` component which the library exposes provides -access to the current navigation state when a screen changes, allowing you to use the [`setCurrentScreen`](/reference/analytics#setCurrentScreen) +access to the current navigation state when a screen changes, allowing you to use the [`logScreenView`](/reference/analytics#logScreenView) method the Analytics library provides: ```jsx @@ -22,12 +22,14 @@ import { NavigationContainer } from '@react-navigation/native'; { + onStateChange={async (state) => { const previousRouteName = routeNameRef.current; const currentRouteName = getActiveRouteName(state); if (previousRouteName !== currentRouteName) { - analytics().setCurrentScreen(currentRouteName, currentRouteName); + await analytics().logScreenView({ + screen_name: currentRouteName, + }); } ``` @@ -38,15 +40,18 @@ documentation on the React Navigation website. The [`wix/react-native-navigation`](https://github.com/wix/react-native-navigation) provides 100% native platform navigation for React Native apps. To manually track screens, you need to setup a `componentDidAppear` event listener and manually call the -[`setCurrentScreen`](/reference/analytics#setCurrentScreen) method the Analytics library provides: +[`logScreenView`](/reference/analytics#logScreenView) method the Analytics library provides: ```js import analytics from '@react-native-firebase/analytics'; import { Navigation } from 'react-native-navigation'; -Navigation.events().registerComponentDidAppearListener(({ componentName, componentType }) => { +Navigation.events().registerComponentDidAppearListener(async ({ componentName, componentType }) => { if (componentType === 'Component') { - analytics().setCurrentScreen(componentName, componentName); + await analytics().logScreenView({ + screen_name: componentName, + screen_class: componentName, + }); } }); ``` diff --git a/packages/analytics/__tests__/analytics.test.ts b/packages/analytics/__tests__/analytics.test.ts index 234374df8c..e991a6c413 100644 --- a/packages/analytics/__tests__/analytics.test.ts +++ b/packages/analytics/__tests__/analytics.test.ts @@ -46,20 +46,6 @@ describe('Analytics', () => { }); }); - it('errors if screenName not a string', () => { - // @ts-ignore test - expect(() => firebase.analytics().setCurrentScreen(666.1337)).toThrowError( - "'screenName' expected a string value", - ); - }); - - it('errors if screenClassOverride not a string', () => { - // @ts-ignore test - expect(() => firebase.analytics().setCurrentScreen('invertase screen', 666.1337)).toThrowError( - "'screenClassOverride' expected a string value", - ); - }); - it('errors if milliseconds not a number', () => { // @ts-ignore test expect(() => firebase.analytics().setMinimumSessionDuration('123')).toThrowError( @@ -186,6 +172,15 @@ describe('Analytics', () => { ); }); + describe('logScreenView()', () => { + it('errors if param is not an object', () => { + // @ts-ignore test + expect(() => firebase.analytics().logScreenView(123)).toThrowError( + 'firebase.analytics().logScreenView(*):', + ); + }); + }); + describe('logAddPaymentInfo()', () => { it('errors if param is not an object', () => { // @ts-ignore test diff --git a/packages/analytics/android/src/main/java/io/invertase/firebase/analytics/UniversalFirebaseAnalyticsModule.java b/packages/analytics/android/src/main/java/io/invertase/firebase/analytics/UniversalFirebaseAnalyticsModule.java index 70f597cef9..6bd845c0db 100644 --- a/packages/analytics/android/src/main/java/io/invertase/firebase/analytics/UniversalFirebaseAnalyticsModule.java +++ b/packages/analytics/android/src/main/java/io/invertase/firebase/analytics/UniversalFirebaseAnalyticsModule.java @@ -52,20 +52,6 @@ Task setAnalyticsCollectionEnabled(Boolean enabled) { }); } - Task setAnalyticsCollectionEnabled( - Activity currentActivity, - String screenName, - @Nullable String screenClassOverride - ) { - return Tasks.call(() -> { - if (currentActivity == null) return null; - FirebaseAnalytics - .getInstance(getContext()) - .setCurrentScreen(currentActivity, screenName, screenClassOverride); - return null; - }); - } - Task setMinimumSessionDuration(long milliseconds) { return Tasks.call(() -> { FirebaseAnalytics.getInstance(getContext()).setMinimumSessionDuration(milliseconds); diff --git a/packages/analytics/android/src/reactnative/java/io/invertase/firebase/analytics/ReactNativeFirebaseAnalyticsModule.java b/packages/analytics/android/src/reactnative/java/io/invertase/firebase/analytics/ReactNativeFirebaseAnalyticsModule.java index cb3b92b6da..f3ec094746 100644 --- a/packages/analytics/android/src/reactnative/java/io/invertase/firebase/analytics/ReactNativeFirebaseAnalyticsModule.java +++ b/packages/analytics/android/src/reactnative/java/io/invertase/firebase/analytics/ReactNativeFirebaseAnalyticsModule.java @@ -59,23 +59,6 @@ public void setAnalyticsCollectionEnabled(Boolean enabled, Promise promise) { }); } - @ReactMethod - public void setCurrentScreen( - String screenName, - @Nullable String screenClassOverride, - Promise promise - ) { - module - .setAnalyticsCollectionEnabled(getCurrentActivity(), screenName, screenClassOverride) - .addOnCompleteListener(task -> { - if (task.isSuccessful()) { - promise.resolve(task.getResult()); - } else { - rejectPromiseWithExceptionMap(promise, task.getException()); - } - }); - } - @ReactMethod public void setMinimumSessionDuration(double milliseconds, Promise promise) { module.setMinimumSessionDuration((long) milliseconds).addOnCompleteListener(task -> { diff --git a/packages/analytics/e2e/analytics.e2e.js b/packages/analytics/e2e/analytics.e2e.js index 67db9e84f6..e6a5dee900 100644 --- a/packages/analytics/e2e/analytics.e2e.js +++ b/packages/analytics/e2e/analytics.e2e.js @@ -116,6 +116,14 @@ describe('analytics()', () => { }); }); + describe('logScreenView()', () => { + it('calls logScreenView', async () => { + await firebase + .analytics() + .logScreenView({ screen_name: 'invertase screen', screen_class: 'invertase class' }); + }); + }); + describe('logAddPaymentInfo()', () => { it('calls logAddPaymentInfo', async () => { await firebase.analytics().logAddPaymentInfo({ diff --git a/packages/analytics/ios/RNFBAnalytics/RNFBAnalyticsModule.m b/packages/analytics/ios/RNFBAnalytics/RNFBAnalyticsModule.m index 88225c634c..0d42fedf3d 100644 --- a/packages/analytics/ios/RNFBAnalytics/RNFBAnalyticsModule.m +++ b/packages/analytics/ios/RNFBAnalytics/RNFBAnalyticsModule.m @@ -67,24 +67,6 @@ - (dispatch_queue_t)methodQueue { return resolve([NSNull null]); } - RCT_EXPORT_METHOD(setCurrentScreen: - (NSString *) screenName - screenClass: - (NSString *) screenClassOverview - resolver: - (RCTPromiseResolveBlock) resolve - rejecter: - (RCTPromiseRejectBlock) reject) { - RCTUnsafeExecuteOnMainQueueSync(^{ - @try { - [FIRAnalytics setScreenName:screenName screenClass:screenClassOverview]; - } @catch (NSException *exception) { - return [RNFBSharedUtils rejectPromiseWithExceptionDict:reject exception:exception]; - } - return resolve([NSNull null]); - }); - } - RCT_EXPORT_METHOD(setUserId: (NSString *) id resolver: diff --git a/packages/analytics/lib/index.d.ts b/packages/analytics/lib/index.d.ts index 1998923f2d..a0796b23b5 100644 --- a/packages/analytics/lib/index.d.ts +++ b/packages/analytics/lib/index.d.ts @@ -324,6 +324,17 @@ export namespace FirebaseAnalyticsTypes { transaction_id?: string; } + export interface ScreenViewParameters { + /** + * Screen name the user is currently viewing. + */ + screen_name?: string; + /** + * Current class associated with the view the user is currently viewing. + */ + screen_class?: string; + } + export interface RefundEventParameters { /** * A product affiliation to designate a supplying company or brick and mortar store location @@ -667,10 +678,10 @@ export namespace FirebaseAnalyticsTypes { * * @param screenName A screen name, e.g. Product. * @param screenClassOverride On Android, React Native runs in a single activity called - * 'MainActivity'. Setting this parameter overrides the default name shown on logs. + * 'MainActivity'. Setting this parameter overrides the default name shown on logs. + * @deprecated */ setCurrentScreen(screenName: string, screenClassOverride?: string): Promise; - /** * Sets the minimum engagement time required before starting a session. * @@ -783,6 +794,20 @@ export namespace FirebaseAnalyticsTypes { * ``` */ logPurchase(params: PurchaseEventParameters): Promise; + /** + * Sets or clears the screen name and class the user is currently viewing + * + * #### Example + * + * ```js + * await firebase.analytics().logScreenView({ + * screen_class: 'ProductScreen', + * screen_name: 'ProductScreen', + * }); + * ``` + * + */ + logScreenView(params: ScreenViewParameters): Promise; /** * Add Payment Info event. This event signifies that a user has submitted their payment information to your app. * diff --git a/packages/analytics/lib/index.js b/packages/analytics/lib/index.js index f81c798a12..25d0e0f028 100644 --- a/packages/analytics/lib/index.js +++ b/packages/analytics/lib/index.js @@ -103,19 +103,14 @@ class FirebaseAnalyticsModule extends FirebaseModule { } setCurrentScreen(screenName, screenClassOverride) { - if (!isString(screenName)) { - throw new Error( - "firebase.analytics().setCurrentScreen(*) 'screenName' expected a string value.", - ); - } - - if (!isUndefined(screenClassOverride) && !isString(screenClassOverride)) { - throw new Error( - "firebase.analytics().setCurrentScreen(_, *) 'screenClassOverride' expected a string value.", - ); - } - - return this.native.setCurrentScreen(screenName, screenClassOverride); + // eslint-disable-next-line no-console + console.warn( + 'firebase.analytics().setCurrentScreen(), is now deprecated. Please use firebase.analytics().logScreenView() instead', + ); + return this.logScreenView({ + screen_name: screenName, + screen_class: screenClassOverride, + }); } setMinimumSessionDuration(milliseconds = 10000) { @@ -214,6 +209,19 @@ class FirebaseAnalyticsModule extends FirebaseModule { ); } + logScreenView(object) { + if (!isObject(object)) { + throw new Error( + 'firebase.analytics().logScreenView(*): The supplied arg must be an object of key/values.', + ); + } + + return this.logEvent( + 'screen_view', + validateStruct(object, structs.ScreenView, 'firebase.analytics().logScreenView(*):'), + ); + } + logAddShippingInfo(object = {}) { if (!isObject(object)) { throw new Error( diff --git a/packages/analytics/lib/structs.js b/packages/analytics/lib/structs.js index eee5c41be4..87f7d54603 100644 --- a/packages/analytics/lib/structs.js +++ b/packages/analytics/lib/structs.js @@ -30,6 +30,11 @@ const Item = struct({ item_variant: 'string?', }); +export const ScreenView = struct({ + screen_class: 'string?', + screen_name: 'string?', +}); + export const AddPaymentInfo = struct({ items: struct.optional([Item]), value: 'number?', diff --git a/packages/analytics/type-test.ts b/packages/analytics/type-test.ts index f4fe2c9d38..7f37af3ed8 100644 --- a/packages/analytics/type-test.ts +++ b/packages/analytics/type-test.ts @@ -65,7 +65,7 @@ console.log(firebase.analytics().resetAnalyticsData); console.log(firebase.analytics().logViewCart); console.log(firebase.analytics().setAnalyticsCollectionEnabled); console.log(firebase.analytics().logSelectPromotion); -console.log(firebase.analytics().setCurrentScreen); +console.log(firebase.analytics().logScreenView); console.log(firebase.analytics().logViewPromotion); console.log(firebase.analytics().setMinimumSessionDuration); console.log(firebase.analytics().setSessionTimeoutDuration); @@ -108,7 +108,7 @@ console.log(analytics().resetAnalyticsData); console.log(analytics().logViewCart); console.log(analytics().setAnalyticsCollectionEnabled); console.log(analytics().logSelectPromotion); -console.log(analytics().setCurrentScreen); +console.log(analytics().logScreenView); console.log(analytics().logViewPromotion); console.log(analytics().setMinimumSessionDuration); console.log(analytics().setSessionTimeoutDuration);