diff --git a/package.json b/package.json index bb9de93ad4..a2098fa530 100644 --- a/package.json +++ b/package.json @@ -75,6 +75,7 @@ "jest": "^28.1.1", "lerna": "5.1.4", "prettier": "^2.7.1", + "regenerator-transform": "^0.15.0", "rimraf": "^3.0.2", "shelljs": "^0.8.5", "ts-jest": "^28.0.5", diff --git a/packages/analytics/RNFBAnalytics.podspec b/packages/analytics/RNFBAnalytics.podspec index 1484b1fd11..283df778b0 100644 --- a/packages/analytics/RNFBAnalytics.podspec +++ b/packages/analytics/RNFBAnalytics.podspec @@ -49,6 +49,18 @@ Pod::Spec.new do |s| s.dependency 'Firebase/Analytics', firebase_sdk_version end + # Special pod for on-device conversion + if defined?($RNFirebaseAnalyticsGoogleAppMeasurementOnDeviceConversion) && ($RNFirebaseAnalyticsGoogleAppMeasurementOnDeviceConversion == true) + Pod::UI.puts "#{s.name}: GoogleAppMeasurementOnDeviceConversion pod added" + + # Releasing as non-breaking change as it is optional but it raises minimum requirements, validate just in case + if (Gem::Version.new(firebase_sdk_version) < Gem::Version.new("9.0.0")) + raise "GoogleAppMeasurementOnDeviceConversion requires firebase-ios-sdk 9.0.0 or greater." + end + + s.dependency 'GoogleAppMeasurementOnDeviceConversion', firebase_sdk_version + end + if defined?($RNFirebaseAsStaticFramework) Pod::UI.puts "#{s.name}: Using overridden static_framework value of '#{$RNFirebaseAsStaticFramework}'" s.static_framework = $RNFirebaseAsStaticFramework diff --git a/packages/analytics/__tests__/analytics.test.ts b/packages/analytics/__tests__/analytics.test.ts index 7e87430fed..e751f99a2f 100644 --- a/packages/analytics/__tests__/analytics.test.ts +++ b/packages/analytics/__tests__/analytics.test.ts @@ -521,4 +521,15 @@ describe('Analytics', function () { ); }); }); + + describe('initiateOnDeviceConversionMeasurementWithEmailAddress()', function () { + it('throws if not a string', function () { + expect(() => + // @ts-ignore + firebase.analytics().initiateOnDeviceConversionMeasurementWithEmailAddress(true), + ).toThrowError( + "firebase.analytics().initiateOnDeviceConversionMeasurementWithEmailAddress(*) 'emailAddress' expected a string value.", + ); + }); + }); }); diff --git a/packages/analytics/e2e/analytics.e2e.js b/packages/analytics/e2e/analytics.e2e.js index 393a879e2b..be56e14368 100644 --- a/packages/analytics/e2e/analytics.e2e.js +++ b/packages/analytics/e2e/analytics.e2e.js @@ -425,6 +425,15 @@ describe('analytics()', function () { }); }); + // Test this last so it does not stop delivery to DebugView + describe('initiateOnDeviceConversionMeasurementWithEmailAddress()', function () { + it('calls native API successfully', async function () { + await firebase + .analytics() + .initiateOnDeviceConversionMeasurementWithEmailAddress('conversionTest@example.com'); + }); + }); + // Test this last so it does not stop delivery to DebugView describe('setAnalyticsCollectionEnabled()', function () { it('false', async function () { diff --git a/packages/analytics/ios/RNFBAnalytics/RNFBAnalyticsModule.m b/packages/analytics/ios/RNFBAnalytics/RNFBAnalyticsModule.m index 9fa508849b..83862ee53a 100644 --- a/packages/analytics/ios/RNFBAnalytics/RNFBAnalyticsModule.m +++ b/packages/analytics/ios/RNFBAnalytics/RNFBAnalyticsModule.m @@ -138,6 +138,19 @@ - (dispatch_queue_t)methodQueue { return resolve([NSNull null]); } +RCT_EXPORT_METHOD(initiateOnDeviceConversionMeasurementWithEmailAddress + : (NSString *)emailAddress resolver + : (RCTPromiseResolveBlock)resolve rejecter + : (RCTPromiseRejectBlock)reject) { + @try { + [FIRAnalytics initiateOnDeviceConversionMeasurementWithEmailAddress:emailAddress]; + } @catch (NSException *exception) { + return [RNFBSharedUtils rejectPromiseWithExceptionDict:reject exception:exception]; + } + + return resolve([NSNull null]); +} + #pragma mark - #pragma mark Private methods diff --git a/packages/analytics/lib/index.d.ts b/packages/analytics/lib/index.d.ts index 2d5162ae7d..b6f29e3f6b 100644 --- a/packages/analytics/lib/index.d.ts +++ b/packages/analytics/lib/index.d.ts @@ -1502,6 +1502,15 @@ export namespace FirebaseAnalyticsTypes { * will clear all parameters. */ setDefaultEventParameters(params?: { [key: string]: any }): Promise; + + /** + * start privacy-sensitive on-device conversion management. + * This is iOS-only. + * This is a no-op if you do not include '#RNFirebaseAnalyticsGoogleAppMeasurementOnDeviceConversion = true' in your Podfile + * + * @param emailAddress email address, properly formatted complete with domain name e.g, 'user@example.com' + */ + initiateOnDeviceConversionMeasurementWithEmailAddress(emailAddress: string): Promise; } } diff --git a/packages/analytics/lib/index.js b/packages/analytics/lib/index.js index 697160d9ec..e800f6cad0 100644 --- a/packages/analytics/lib/index.js +++ b/packages/analytics/lib/index.js @@ -17,6 +17,7 @@ import { isAlphaNumericUnderscore, + isIOS, isNull, isNumber, isObject, @@ -676,6 +677,20 @@ class FirebaseAnalyticsModule extends FirebaseModule { return this.native.setDefaultEventParameters(params); } + + initiateOnDeviceConversionMeasurementWithEmailAddress(emailAddress) { + if (!isString(emailAddress)) { + throw new Error( + "firebase.analytics().initiateOnDeviceConversionMeasurementWithEmailAddress(*) 'emailAddress' expected a string value.", + ); + } + + if (!isIOS) { + return; + } + + return this.native.initiateOnDeviceConversionMeasurementWithEmailAddress(emailAddress); + } } // import { SDK_VERSION } from '@react-native-firebase/analytics'; diff --git a/tests/ios/Podfile b/tests/ios/Podfile index 3eb0e9d6a0..2d90563928 100644 --- a/tests/ios/Podfile +++ b/tests/ios/Podfile @@ -11,6 +11,9 @@ $RNFirebaseAsStaticFramework = true # toggle this to true (and set 'use_framewor # See: https://firebase.google.com/support/release-notes/ios#analytics - requires firebase-ios-sdk 7.11.0+ #$RNFirebaseAnalyticsWithoutAdIdSupport = true # toggle this to true for the no-ad-tracking Analytics subspec +# Toggle this to true if you want to include support for on device conversion measurement APIs +$RNFirebaseAnalyticsGoogleAppMeasurementOnDeviceConversion = true + # Versions used below, for quick reference / outdated+upgrade checks $iOSMinimumDeployVersion = '11.0'