diff --git a/packages/react-native-analytics/package.json b/packages/react-native-analytics/package.json index 0db5a6e..319db02 100644 --- a/packages/react-native-analytics/package.json +++ b/packages/react-native-analytics/package.json @@ -14,8 +14,8 @@ "@castleio/react-native-castle": "^1.1.5", "@farfetch/blackout-core": "^1.58.2", "@react-native-async-storage/async-storage": "^1.16.0", - "@react-native-firebase/analytics": "^14.11.0", - "@react-native-firebase/app": "^14.11.0", + "@react-native-firebase/analytics": "^18.9.0", + "@react-native-firebase/app": "^18.9.0", "axios": "^0.21.4", "react": "^16.8.1", "react-native": "^0.62.3", @@ -25,7 +25,7 @@ "@castleio/react-native-castle": "^1.1.5", "@farfetch/blackout-core": "^1.58.2", "@react-native-async-storage/async-storage": "^1.6.1", - "@react-native-firebase/analytics": "^14.11.0", + "@react-native-firebase/analytics": "^18.9.0", "react-native": "^0.62.3", "react-native-device-info": "^5.5.8", "react-native-forter": "^0.1.10" diff --git a/packages/react-native-analytics/src/integrations/firebaseAnalytics/FirebaseAnalytics.js b/packages/react-native-analytics/src/integrations/firebaseAnalytics/FirebaseAnalytics.js index 826b16f..b7572ec 100644 --- a/packages/react-native-analytics/src/integrations/firebaseAnalytics/FirebaseAnalytics.js +++ b/packages/react-native-analytics/src/integrations/firebaseAnalytics/FirebaseAnalytics.js @@ -9,6 +9,7 @@ import { OPTION_ON_SET_USER_HANDLER, OPTION_SCREEN_VIEWS_MAPPER, OPTION_SET_CUSTOM_USER_ID_PROPERTY, + OPTION_GOOGLE_CONSENT_CONFIG, } from './constants'; import { defaultEventsMapper, @@ -49,13 +50,14 @@ class FirebaseAnalytics extends Integration { * @param {object} options - User configured options. * @param {object} loadData - Analytics' load event data. */ - constructor(options, loadData) { + constructor(options = {}, loadData) { super(options, loadData); checkRNFirebaseAnalyticsInstalled(); this.initialize(options); this.onSetUser(loadData, options); + this.googleConsentConfig = options[OPTION_GOOGLE_CONSENT_CONFIG]; } /** @@ -363,6 +365,43 @@ class FirebaseAnalytics extends Integration { await firebaseAnalytics().logEvent(firebaseEvent, properties); } } + + /** + * Overrides super.setConsent to update the consent values + * on the native side (via react-native-firebase) by matching + * the consent config with the user's given consent. + * + * @param {object} consentData - Consent object containing the user consent. + */ + async setConsent(consentData) { + if (this.googleConsentConfig) { + // Dealing with null or undefined consent values + const safeConsent = consentData || {}; + + // Fill consent value into consent element, using analytics consent categories + const consentValues = Object.keys(this.googleConsentConfig).reduce( + (result, consentKey) => { + let consentValue = false; + + const consent = this.googleConsentConfig[consentKey]; + + if (consent && consent.categories) { + consentValue = consent.categories.every( + consentCategory => safeConsent[consentCategory], + ); + } + + return { + ...result, + [consentKey]: consentValue, + }; + }, + {}, + ); + + await firebaseAnalytics().setConsent(consentValues); + } + } } export default FirebaseAnalytics; diff --git a/packages/react-native-analytics/src/integrations/firebaseAnalytics/__tests__/FirebaseAnalytics.test.js b/packages/react-native-analytics/src/integrations/firebaseAnalytics/__tests__/FirebaseAnalytics.test.js index 8231a2c..0e7440c 100644 --- a/packages/react-native-analytics/src/integrations/firebaseAnalytics/__tests__/FirebaseAnalytics.test.js +++ b/packages/react-native-analytics/src/integrations/firebaseAnalytics/__tests__/FirebaseAnalytics.test.js @@ -20,6 +20,7 @@ import screenTypes from '../../../screenTypes'; import { MAX_PRODUCT_CATEGORIES, OPTION_EVENTS_MAPPER, + OPTION_GOOGLE_CONSENT_CONFIG, OPTION_SCREEN_VIEWS_MAPPER, OPTION_SET_CUSTOM_USER_ID_PROPERTY, } from '../constants'; @@ -31,6 +32,7 @@ const mockFirebaseAnalyticsReturn = { setUserProperties: jest.fn(), logEvent: jest.fn(), logSelectItem: jest.fn(), + setConsent: jest.fn(), }; jest.mock('@react-native-firebase/analytics', () => { @@ -375,9 +377,9 @@ describe('FirebaseAnalyticsIntegration instance', () => { }, }; - createInstance(null, loadData); + createInstance(undefined, loadData); - expect(spy).toHaveBeenCalledWith(loadData, null); + expect(spy).toHaveBeenCalledWith(loadData, {}); }); it('Should call custom `onSetUser` function if passed via the integration options', () => { @@ -982,4 +984,37 @@ describe('FirebaseAnalyticsIntegration instance', () => { }); }); }); + + describe('Consent', () => { + it('Should update the user consent on the native side when setConsent is called', async () => { + const instance = createInstance({ + [OPTION_GOOGLE_CONSENT_CONFIG]: { + ad_user_data: { categories: ['marketing'] }, + ad_personalization: { categories: ['marketing'] }, + analytics_storage: { categories: ['marketing'] }, + ad_storage: { categories: ['marketing'] }, + }, + }); + + await instance.setConsent({ marketing: true }); + + expect(firebaseAnalytics().setConsent).toHaveBeenCalledWith({ + ad_personalization: true, + ad_storage: true, + ad_user_data: true, + analytics_storage: true, + }); + + jest.clearAllMocks(); + + await instance.setConsent({ marketing: false }); + + expect(firebaseAnalytics().setConsent).toHaveBeenCalledWith({ + ad_personalization: false, + ad_storage: false, + ad_user_data: false, + analytics_storage: false, + }); + }); + }); }); diff --git a/packages/react-native-analytics/src/integrations/firebaseAnalytics/constants.js b/packages/react-native-analytics/src/integrations/firebaseAnalytics/constants.js index baeda6d..5042651 100644 --- a/packages/react-native-analytics/src/integrations/firebaseAnalytics/constants.js +++ b/packages/react-native-analytics/src/integrations/firebaseAnalytics/constants.js @@ -4,5 +4,6 @@ export const OPTION_EVENTS_MAPPER = 'eventsMapper'; export const OPTION_SCREEN_VIEWS_MAPPER = 'screenViewsMapper'; export const OPTION_ON_SET_USER_HANDLER = 'onSetUser'; export const OPTION_SET_CUSTOM_USER_ID_PROPERTY = 'setCustomUserIdProperty'; +export const OPTION_GOOGLE_CONSENT_CONFIG = 'googleConsentConfig'; export const MESSAGE_PREFIX = '[FirebaseAnalytics]';