Skip to content

Commit

Permalink
feat(ios): add initiateOnDeviceConversionMeasurementWithPhoneNumber
Browse files Browse the repository at this point in the history
Note: this implies transitive requirement of firebase-ios-sdk 10.13.0,
if you override your firebase-ios-sdk version locally you must increase
the local override version to at least 10.13.0 to adopt this version.
  • Loading branch information
mikehardy committed Sep 20, 2023
1 parent 21531f2 commit 80ac07e
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 0 deletions.
47 changes: 47 additions & 0 deletions packages/analytics/e2e/analytics.e2e.js
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,28 @@ describe('analytics() modular', function () {
});
});

// Test this last so it does not stop delivery to DebugView
describe('on-device conversion measurement with phone', function () {
it('calls native API successfully', async function () {
await firebase
.analytics()
.initiateOnDeviceConversionMeasurementWithPhoneNumber('+14155551212');
});
it('handles mal-formatted phone number', async function () {
try {
await firebase
.analytics()
.initiateOnDeviceConversionMeasurementWithPhoneNumber('+notaphonenumber');
fail('Should have returned an error for malformatted phone number');
} catch (e) {
// coerce the error message to a string and verify
if (!(e + '').includes('expected a string value in E.164 format')) {
fail('Should have returned an error for malformatted phone number');
}
}
});
});

// Test this last so it does not stop delivery to DebugView
describe('setAnalyticsCollectionEnabled()', function () {
it('false', async function () {
Expand Down Expand Up @@ -1008,6 +1030,31 @@ describe('analytics() modular', function () {
});
});

// Test this last so it does not stop delivery to DebugView
describe('on-device conversion measurement with phone', function () {
it('calls native API successfully', async function () {
const { getAnalytics, initiateOnDeviceConversionMeasurementWithPhoneNumber } =
analyticsModular;
await initiateOnDeviceConversionMeasurementWithPhoneNumber(getAnalytics(), '+14155551212');
});
it('handles mal-formatted phone number', async function () {
try {
const { getAnalytics, initiateOnDeviceConversionMeasurementWithPhoneNumber } =
analyticsModular;
await initiateOnDeviceConversionMeasurementWithPhoneNumber(
getAnalytics(),
'+notaphonenumber',
);
fail('Should have returned an error for malformatted phone number');
} catch (e) {
// coerce the error message to a string and verify
if (!(e + '').includes('expected a string value in E.164 format')) {
fail('Should have returned an error for malformatted phone number');
}
}
});
});

// Test this last so it does not stop delivery to DebugView
describe('setAnalyticsCollectionEnabled()', function () {
it('false', async function () {
Expand Down
13 changes: 13 additions & 0 deletions packages/analytics/ios/RNFBAnalytics/RNFBAnalyticsModule.m
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,19 @@ - (dispatch_queue_t)methodQueue {
return resolve([NSNull null]);
}

RCT_EXPORT_METHOD(initiateOnDeviceConversionMeasurementWithPhoneNumber
: (NSString *)phoneNumber resolver
: (RCTPromiseResolveBlock)resolve rejecter
: (RCTPromiseRejectBlock)reject) {
@try {
[FIRAnalytics initiateOnDeviceConversionMeasurementWithPhoneNumber:phoneNumber];
} @catch (NSException *exception) {
return [RNFBSharedUtils rejectPromiseWithExceptionDict:reject exception:exception];
}

return resolve([NSNull null]);
}

#pragma mark -
#pragma mark Private methods

Expand Down
9 changes: 9 additions & 0 deletions packages/analytics/lib/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1718,6 +1718,15 @@ export namespace FirebaseAnalyticsTypes {
* @param emailAddress email address, properly formatted complete with domain name e.g, 'user@example.com'
*/
initiateOnDeviceConversionMeasurementWithEmailAddress(emailAddress: string): Promise<void>;

/**
* 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 phoneNumber phone number in E.164 format - that is a leading + sign, then up to 15 digits, no dashes or spaces.
*/
initiateOnDeviceConversionMeasurementWithPhoneNumber(phoneNumber: string): Promise<void>;
}

/**
Expand Down
16 changes: 16 additions & 0 deletions packages/analytics/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import {
isAlphaNumericUnderscore,
isE164PhoneNumber,
isIOS,
isNull,
isNumber,
Expand Down Expand Up @@ -85,6 +86,7 @@ export {
logViewSearchResults,
setDefaultEventParameters,
initiateOnDeviceConversionMeasurementWithEmailAddress,
initiateOnDeviceConversionMeasurementWithPhoneNumber,
} from './modular/index';

const ReservedEventNames = [
Expand Down Expand Up @@ -769,6 +771,20 @@ class FirebaseAnalyticsModule extends FirebaseModule {

return this.native.initiateOnDeviceConversionMeasurementWithEmailAddress(emailAddress);
}

initiateOnDeviceConversionMeasurementWithPhoneNumber(phoneNumber) {
if (!isE164PhoneNumber(phoneNumber)) {
throw new Error(
"firebase.analytics().initiateOnDeviceConversionMeasurementWithPhoneNumber(*) 'phoneNumber' expected a string value in E.164 format.",
);
}

if (!isIOS) {
return;
}

return this.native.initiateOnDeviceConversionMeasurementWithPhoneNumber(phoneNumber);
}
}

// import { SDK_VERSION } from '@react-native-firebase/analytics';
Expand Down
13 changes: 13 additions & 0 deletions packages/analytics/lib/modular/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1164,6 +1164,19 @@ export function initiateOnDeviceConversionMeasurementWithEmailAddress(
emailAddress: string,
): Promise<void>;

/**
* 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 analytics Analytics instance.
* @param phoneNumber phone number in E.164 format - that is a leading + sign, then up to 15 digits, no dashes or spaces.
*/
export function initiateOnDeviceConversionMeasurementWithPhoneNumber(
analytics: Analytics,
phoneNumber: string,
): Promise<void>;

/**
* Checks four different things.
* 1. Checks if it's not a browser extension environment.
Expand Down
12 changes: 12 additions & 0 deletions packages/analytics/lib/modular/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,18 @@ export function initiateOnDeviceConversionMeasurementWithEmailAddress(analytics,
return analytics.initiateOnDeviceConversionMeasurementWithEmailAddress(emailAddress);
}

/**
* 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 analytics Analytics instance.
* @param phoneNumber phone number in E.164 format - that is a leading + sign, then up to 15 digits, no dashes or spaces.
*/
export function initiateOnDeviceConversionMeasurementWithPhoneNumber(analytics, phoneNumber) {
return analytics.initiateOnDeviceConversionMeasurementWithPhoneNumber(phoneNumber);
}

/**
* Checks four different things.
* 1. Checks if it's not a browser extension environment.
Expand Down
10 changes: 10 additions & 0 deletions packages/app/lib/common/validate.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,16 @@ export function isNumber(value) {
return typeof value === 'number';
}

/**
* Simple is phone number check for E.164 format
* @param value
* @return {boolean}
*/
export function isE164PhoneNumber(value) {
const PHONE_NUMBER = /^\+[1-9]\d{1,14}$/; // E.164
return PHONE_NUMBER.test(value);
}

/**
* Simple finite check
* @param value
Expand Down

1 comment on commit 80ac07e

@vercel
Copy link

@vercel vercel bot commented on 80ac07e Sep 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.