@react-native-firebase/analytics 18.8.0 → 19.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,18 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [19.0.0](https://github.com/invertase/react-native-firebase/compare/v18.9.0...v19.0.0) (2024-02-26)
7
+
8
+ ### Features
9
+
10
+ - **analytics, ios:** add Podfile toggle to optionally link AdSupport ([e4db9bb](https://github.com/invertase/react-native-firebase/commit/e4db9bbf0266de658ae3991568f5e04f1fcf7fc7))
11
+
12
+ ## [18.9.0](https://github.com/invertase/react-native-firebase/compare/v18.8.0...v18.9.0) (2024-02-21)
13
+
14
+ ### Features
15
+
16
+ - **analytics:** add setConsent implementation ([#7629](https://github.com/invertase/react-native-firebase/issues/7629)) ([7816985](https://github.com/invertase/react-native-firebase/commit/78169854f16a2715f5d2657ab08f54d5a4b05281))
17
+
6
18
  ## [18.8.0](https://github.com/invertase/react-native-firebase/compare/v18.7.3...v18.8.0) (2024-01-25)
7
19
 
8
20
  **Note:** Version bump only for package @react-native-firebase/analytics
@@ -52,6 +52,12 @@ Pod::Spec.new do |s|
52
52
  Pod::UI.puts "#{s.name}: You may set variable `$RNFirebaseAnalyticsWithoutAdIdSupport=true` in Podfile to use analytics without ad ids."
53
53
  end
54
54
  s.dependency 'Firebase/Analytics', firebase_sdk_version
55
+
56
+ # Special pod for on-device conversion
57
+ if defined?($RNFirebaseAnalyticsEnableAdSupport) && ($RNFirebaseAnalyticsEnableAdSupport == true)
58
+ Pod::UI.puts "#{s.name}: Adding Apple AdSupport.framework dependency for optional analytics features"
59
+ s.frameworks = 'AdSupport'
60
+ end
55
61
  end
56
62
 
57
63
  # Special pod for on-device conversion
@@ -66,6 +66,7 @@ describe('Analytics', function () {
66
66
  "'name' expected a string value",
67
67
  );
68
68
  });
69
+
69
70
  it('throws if value is invalid', function () {
70
71
  // @ts-ignore test
71
72
  expect(() => firebase.analytics().setUserProperty('invertase3', 33.3333)).toThrowError(
@@ -79,6 +80,7 @@ describe('Analytics', function () {
79
80
  "'properties' expected an object of key/value pairs",
80
81
  );
81
82
  });
83
+
82
84
  it('throws if property value is invalid', function () {
83
85
  const props = {
84
86
  test: '123',
@@ -91,6 +93,7 @@ describe('Analytics', function () {
91
93
  "'properties' value for parameter 'foo' is invalid",
92
94
  );
93
95
  });
96
+
94
97
  it('throws if value is a number', function () {
95
98
  // @ts-ignore test
96
99
  expect(() => firebase.analytics().setUserProperties({ invertase1: 123 })).toThrowError(
@@ -98,6 +101,33 @@ describe('Analytics', function () {
98
101
  );
99
102
  });
100
103
 
104
+ it('throws if consentSettings is not an object', function () {
105
+ // @ts-ignore test
106
+ expect(() => firebase.analytics().setConsent(1337)).toThrowError(
107
+ 'The supplied arg must be an object of key/values.',
108
+ );
109
+ });
110
+
111
+ it('throws if consentSettings is invalid', function () {
112
+ const consentSettings = {
113
+ ad_storage: true,
114
+ foo: {
115
+ bar: 'baz',
116
+ },
117
+ };
118
+ // @ts-ignore test
119
+ expect(() => firebase.analytics().setConsent(consentSettings)).toThrowError(
120
+ "'consentSettings' value for parameter 'foo' is invalid, expected a boolean.",
121
+ );
122
+ });
123
+
124
+ it('throws if one value of consentSettings is a number', function () {
125
+ // @ts-ignore test
126
+ expect(() => firebase.analytics().setConsent({ ad_storage: 123 })).toThrowError(
127
+ "'consentSettings' value for parameter 'ad_storage' is invalid, expected a boolean.",
128
+ );
129
+ });
130
+
101
131
  it('errors when no parameters are set', function () {
102
132
  // @ts-ignore test
103
133
  expect(() => firebase.analytics().logSearch()).toThrowError(
@@ -139,6 +169,7 @@ describe('Analytics', function () {
139
169
  'firebase.analytics().logScreenView(*):',
140
170
  );
141
171
  });
172
+
142
173
  it('accepts arbitrary custom event parameters while rejecting defined parameters with wrong types', function () {
143
174
  expect(() => firebase.analytics().logScreenView({ foo: 'bar' })).not.toThrow();
144
175
  expect(() =>
@@ -155,6 +186,7 @@ describe('Analytics', function () {
155
186
  'firebase.analytics().logAddPaymentInfo(*):',
156
187
  );
157
188
  });
189
+
158
190
  it('errors when compound values are not set', function () {
159
191
  expect(() =>
160
192
  firebase.analytics().logAddPaymentInfo({
@@ -181,6 +213,7 @@ describe('Analytics', function () {
181
213
  'firebase.analytics().logAddToCart(*):',
182
214
  );
183
215
  });
216
+
184
217
  it('errors when compound values are not set', function () {
185
218
  expect(() =>
186
219
  firebase.analytics().logAddToCart({
@@ -197,6 +230,7 @@ describe('Analytics', function () {
197
230
  'firebase.analytics().logAddShippingInfo(*):',
198
231
  );
199
232
  });
233
+
200
234
  it('errors when compound values are not set', function () {
201
235
  expect(() =>
202
236
  firebase.analytics().logAddShippingInfo({
@@ -213,6 +247,7 @@ describe('Analytics', function () {
213
247
  'firebase.analytics().logAddToWishlist(*):',
214
248
  );
215
249
  });
250
+
216
251
  it('errors when compound values are not set', function () {
217
252
  expect(() =>
218
253
  firebase.analytics().logAddToWishlist({
@@ -229,6 +264,7 @@ describe('Analytics', function () {
229
264
  'firebase.analytics().logBeginCheckout(*):',
230
265
  );
231
266
  });
267
+
232
268
  it('errors when compound values are not set', function () {
233
269
  expect(() =>
234
270
  firebase.analytics().logBeginCheckout({
@@ -245,6 +281,7 @@ describe('Analytics', function () {
245
281
  'firebase.analytics().logGenerateLead(*):',
246
282
  );
247
283
  });
284
+
248
285
  it('errors when compound values are not set', function () {
249
286
  expect(() =>
250
287
  firebase.analytics().logGenerateLead({
@@ -414,6 +451,7 @@ describe('Analytics', function () {
414
451
  'firebase.analytics().logPurchase(*):',
415
452
  );
416
453
  });
454
+
417
455
  it('errors when compound values are not set', function () {
418
456
  expect(() =>
419
457
  firebase.analytics().logPurchase({
@@ -447,6 +485,7 @@ describe('Analytics', function () {
447
485
  'firebase.analytics().logViewCart(*):',
448
486
  );
449
487
  });
488
+
450
489
  it('errors when compound values are not set', function () {
451
490
  expect(() =>
452
491
  firebase.analytics().logViewCart({
@@ -463,6 +502,7 @@ describe('Analytics', function () {
463
502
  'firebase.analytics().logViewItem(*):',
464
503
  );
465
504
  });
505
+
466
506
  it('errors when compound values are not set', function () {
467
507
  expect(() =>
468
508
  firebase.analytics().logViewItem({
@@ -488,6 +528,7 @@ describe('Analytics', function () {
488
528
  'firebase.analytics().logRemoveFromCart(*):',
489
529
  );
490
530
  });
531
+
491
532
  it('errors when compound values are not set', function () {
492
533
  expect(() =>
493
534
  firebase.analytics().logRemoveFromCart({
@@ -65,8 +65,11 @@ apply from: file('./../../app/android/firebase-json.gradle')
65
65
  String collectionDeactivated = 'false'
66
66
  String adidEnabled = 'true'
67
67
  String ssaidEnabled = 'true'
68
- String personalizationEnabled = 'true'
69
68
  String automaticScreenReportingEnabled = 'true'
69
+ String analyticsStorageEnabled = 'true'
70
+ String adStorageEnabled = 'true'
71
+ String adUserDataEnabled = 'true'
72
+ String personalizationEnabled = 'true'
70
73
 
71
74
  // If nothing is defined, data collection defaults to true
72
75
  String dataCollectionEnabled = 'true'
@@ -96,12 +99,21 @@ if (rootProject.ext && rootProject.ext.firebaseJson) {
96
99
  if (rnfbConfig.isFlagEnabled('google_analytics_ssaid_collection_enabled', true) == false) {
97
100
  ssaidEnabled = 'false'
98
101
  }
99
- if (rnfbConfig.isFlagEnabled('analytics_default_allow_ad_personalization_signals', true) == false) {
100
- personalizationEnabled = 'false'
101
- }
102
102
  if (rnfbConfig.isFlagEnabled('google_analytics_automatic_screen_reporting_enabled', true) == false) {
103
103
  automaticScreenReportingEnabled = 'false'
104
104
  }
105
+ if (rnfbConfig.isFlagEnabled('analytics_default_allow_analytics_storage', true) == false) {
106
+ analyticsStorageEnabled = 'false'
107
+ }
108
+ if (rnfbConfig.isFlagEnabled('analytics_default_allow_ad_storage', true) == false) {
109
+ adStorageEnabled = 'false'
110
+ }
111
+ if (rnfbConfig.isFlagEnabled('analytics_default_allow_ad_user_data', true) == false) {
112
+ adUserDataEnabled = 'false'
113
+ }
114
+ if (rnfbConfig.isFlagEnabled('analytics_default_allow_ad_personalization_signals', true) == false) {
115
+ personalizationEnabled = 'false'
116
+ }
105
117
  }
106
118
 
107
119
  android {
@@ -117,8 +129,11 @@ android {
117
129
  firebaseJsonCollectionDeactivated: collectionDeactivated,
118
130
  firebaseJsonAdidEnabled: adidEnabled,
119
131
  firebaseJsonSsaidEnabled: ssaidEnabled,
120
- firebaseJsonPersonalizationEnabled: personalizationEnabled,
121
- firebaseJsonAutomaticScreenReportingEnabled: automaticScreenReportingEnabled
132
+ firebaseJsonAutomaticScreenReportingEnabled: automaticScreenReportingEnabled,
133
+ firebaseJsonAnalyticsStorageEnabled: analyticsStorageEnabled,
134
+ firebaseJsonAdStorageEnabled: adStorageEnabled,
135
+ firebaseJsonAdUserDataEnabled: adUserDataEnabled,
136
+ firebaseJsonPersonalizationEnabled: personalizationEnabled
122
137
  ]
123
138
  }
124
139
 
@@ -11,7 +11,11 @@
11
11
  <meta-data android:name="firebase_analytics_collection_deactivated" android:value="${firebaseJsonCollectionDeactivated}" />
12
12
  <meta-data android:name="google_analytics_adid_collection_enabled" android:value="${firebaseJsonAdidEnabled}" />
13
13
  <meta-data android:name="google_analytics_ssaid_collection_enabled" android:value="${firebaseJsonSsaidEnabled}" />
14
- <meta-data android:name="google_analytics_default_allow_ad_personalization_signals" android:value="${firebaseJsonPersonalizationEnabled}" />
15
14
  <meta-data android:name="google_analytics_automatic_screen_reporting_enabled" android:value="${firebaseJsonAutomaticScreenReportingEnabled}" />
15
+ <meta-data android:name="google_analytics_default_allow_analytics_storage" android:value="${firebaseJsonAnalyticsStorageEnabled}" />
16
+ <meta-data android:name="google_analytics_default_allow_ad_storage" android:value="${firebaseJsonAdStorageEnabled}" />
17
+ <meta-data android:name="google_analytics_default_allow_ad_user_data" android:value="${firebaseJsonAdUserDataEnabled}" />
18
+ <meta-data android:name="google_analytics_default_allow_ad_personalization_signals" android:value="${firebaseJsonPersonalizationEnabled}" />
19
+
16
20
  </application>
17
21
  </manifest>
@@ -22,7 +22,11 @@ import android.os.Bundle;
22
22
  import com.google.android.gms.tasks.Task;
23
23
  import com.google.android.gms.tasks.Tasks;
24
24
  import com.google.firebase.analytics.FirebaseAnalytics;
25
+ import com.google.firebase.analytics.FirebaseAnalytics.ConsentStatus;
26
+ import com.google.firebase.analytics.FirebaseAnalytics.ConsentType;
25
27
  import io.invertase.firebase.common.UniversalFirebaseModule;
28
+ import java.util.EnumMap;
29
+ import java.util.Map;
26
30
  import java.util.Set;
27
31
 
28
32
  @SuppressWarnings("WeakerAccess")
@@ -109,4 +113,29 @@ public class UniversalFirebaseAnalyticsModule extends UniversalFirebaseModule {
109
113
  return null;
110
114
  });
111
115
  }
116
+
117
+ Task<Void> setConsent(Bundle consentSettings) {
118
+ return Tasks.call(
119
+ () -> {
120
+ boolean analyticsStorage = consentSettings.getBoolean("analytics_storage");
121
+ boolean adStorage = consentSettings.getBoolean("ad_storage");
122
+ boolean adUserData = consentSettings.getBoolean("ad_user_data");
123
+ boolean adPersonalization = consentSettings.getBoolean("ad_personalization");
124
+
125
+ Map<ConsentType, ConsentStatus> consentMap = new EnumMap<>(ConsentType.class);
126
+ consentMap.put(
127
+ ConsentType.ANALYTICS_STORAGE,
128
+ analyticsStorage ? ConsentStatus.GRANTED : ConsentStatus.DENIED);
129
+ consentMap.put(
130
+ ConsentType.AD_STORAGE, adStorage ? ConsentStatus.GRANTED : ConsentStatus.DENIED);
131
+ consentMap.put(
132
+ ConsentType.AD_USER_DATA, adUserData ? ConsentStatus.GRANTED : ConsentStatus.DENIED);
133
+ consentMap.put(
134
+ ConsentType.AD_PERSONALIZATION,
135
+ adPersonalization ? ConsentStatus.GRANTED : ConsentStatus.DENIED);
136
+
137
+ FirebaseAnalytics.getInstance(getContext()).setConsent(consentMap);
138
+ return null;
139
+ });
140
+ }
112
141
  }
@@ -178,6 +178,20 @@ public class ReactNativeFirebaseAnalyticsModule extends ReactNativeFirebaseModul
178
178
  });
179
179
  }
180
180
 
181
+ @ReactMethod
182
+ public void setConsent(ReadableMap consentSettings, Promise promise) {
183
+ module
184
+ .setConsent(Arguments.toBundle(consentSettings))
185
+ .addOnCompleteListener(
186
+ task -> {
187
+ if (task.isSuccessful()) {
188
+ promise.resolve(task.getResult());
189
+ } else {
190
+ rejectPromiseWithExceptionMap(promise, task.getException());
191
+ }
192
+ });
193
+ }
194
+
181
195
  private Bundle toBundle(ReadableMap readableMap) {
182
196
  Bundle bundle = Arguments.toBundle(readableMap);
183
197
  if (bundle == null) {
@@ -177,6 +177,29 @@ RCT_EXPORT_METHOD(initiateOnDeviceConversionMeasurementWithPhoneNumber
177
177
  return resolve([NSNull null]);
178
178
  }
179
179
 
180
+ RCT_EXPORT_METHOD(setConsent
181
+ : (NSDictionary *)consentSettings resolver
182
+ : (RCTPromiseResolveBlock)resolve rejecter
183
+ : (RCTPromiseRejectBlock)reject) {
184
+ @try {
185
+ BOOL analyticsStorage = [consentSettings[@"analytics_storage"] boolValue];
186
+ BOOL adStorage = [consentSettings[@"ad_storage"] boolValue];
187
+ BOOL adUserData = [consentSettings[@"ad_user_data"] boolValue];
188
+ BOOL adPersonalization = [consentSettings[@"ad_personalization"] boolValue];
189
+ [FIRAnalytics setConsent:@{
190
+ FIRConsentTypeAnalyticsStorage : analyticsStorage ? FIRConsentStatusGranted
191
+ : FIRConsentStatusDenied,
192
+ FIRConsentTypeAdStorage : adStorage ? FIRConsentStatusGranted : FIRConsentStatusDenied,
193
+ FIRConsentTypeAdUserData : adUserData ? FIRConsentStatusGranted : FIRConsentStatusDenied,
194
+ FIRConsentTypeAdPersonalization : adPersonalization ? FIRConsentStatusGranted
195
+ : FIRConsentStatusDenied,
196
+ }];
197
+ } @catch (NSException *exception) {
198
+ return [RNFBSharedUtils rejectPromiseWithExceptionDict:reject exception:exception];
199
+ }
200
+ return resolve([NSNull null]);
201
+ }
202
+
180
203
  #pragma mark -
181
204
  #pragma mark Private methods
182
205
 
package/lib/index.d.ts CHANGED
@@ -774,15 +774,19 @@ export namespace FirebaseAnalyticsTypes {
774
774
  */
775
775
  export interface ConsentSettings {
776
776
  /** Enables storage, such as cookies, related to advertising */
777
- ad_storage?: ConsentStatusString;
777
+ ad_storage?: boolean;
778
+ /** Sets consent for sending user data to Google for online advertising purposes */
779
+ ad_user_data?: boolean;
780
+ /** Sets consent for personalized advertising */
781
+ ad_personalization?: boolean;
778
782
  /** Enables storage, such as cookies, related to analytics (for example, visit duration) */
779
- analytics_storage?: ConsentStatusString;
783
+ analytics_storage?: boolean;
780
784
  /**
781
785
  * Enables storage that supports the functionality of the website or app such as language settings
782
786
  */
783
- functionality_storage?: ConsentStatusString;
787
+ functionality_storage?: boolean;
784
788
  /** Enables storage related to personalization such as video recommendations */
785
- personalization_storage?: ConsentStatusString;
789
+ personalization_storage?: boolean;
786
790
  /**
787
791
  * Enables storage related to security such as authentication functionality, fraud prevention,
788
792
  * and other user protection.
@@ -1727,6 +1731,28 @@ export namespace FirebaseAnalyticsTypes {
1727
1731
  * @param phoneNumber phone number in E.164 format - that is a leading + sign, then up to 15 digits, no dashes or spaces.
1728
1732
  */
1729
1733
  initiateOnDeviceConversionMeasurementWithPhoneNumber(phoneNumber: string): Promise<void>;
1734
+
1735
+ /**
1736
+ * For Consent Mode!
1737
+ *
1738
+ * #### Example
1739
+ *
1740
+ * ```js
1741
+ * // Disable consent
1742
+ * await firebase.analytics().setConsent({
1743
+ * ad_personalization: false,
1744
+ * analytics_storage: false,
1745
+ * ad_storage: false,
1746
+ * ad_user_data: false,
1747
+ * });
1748
+ * ```
1749
+ *
1750
+ * Sets the applicable end user consent state (e.g., for device identifiers) for this app on this device.
1751
+ * Use the consent map to specify individual consent type values.
1752
+ * Settings are persisted across app sessions.
1753
+ * @param consentSettings Consent status settings for each consent type.
1754
+ */
1755
+ setConsent(consentSettings: ConsentSettings): Promise<void>;
1730
1756
  }
1731
1757
 
1732
1758
  /**
package/lib/index.js CHANGED
@@ -87,6 +87,7 @@ export {
87
87
  setDefaultEventParameters,
88
88
  initiateOnDeviceConversionMeasurementWithEmailAddress,
89
89
  initiateOnDeviceConversionMeasurementWithPhoneNumber,
90
+ setConsent,
90
91
  } from './modular/index';
91
92
 
92
93
  const ReservedEventNames = [
@@ -261,6 +262,26 @@ class FirebaseAnalyticsModule extends FirebaseModule {
261
262
  return this.native.resetAnalyticsData();
262
263
  }
263
264
 
265
+ setConsent(consentSettings) {
266
+ if (!isObject(consentSettings)) {
267
+ throw new Error(
268
+ 'firebase.analytics().setConsent(*): The supplied arg must be an object of key/values.',
269
+ );
270
+ }
271
+
272
+ const entries = Object.entries(consentSettings);
273
+ for (let i = 0; i < entries.length; i++) {
274
+ const [key, value] = entries[i];
275
+ if (!isBoolean(value)) {
276
+ throw new Error(
277
+ `firebase.analytics().setConsent(*) 'consentSettings' value for parameter '${key}' is invalid, expected a boolean.`,
278
+ );
279
+ }
280
+ }
281
+
282
+ return this.native.setConsent(consentSettings);
283
+ }
284
+
264
285
  /** -------------------
265
286
  * EVENTS
266
287
  * -------------------- */
@@ -1189,16 +1189,16 @@ export function initiateOnDeviceConversionMeasurementWithPhoneNumber(
1189
1189
  export function isSupported(): Promise<boolean>;
1190
1190
 
1191
1191
  /**
1192
- * Sets the applicable end user consent state for this web app across all gtag
1193
- * references once Firebase Analytics is initialized. Web only.
1192
+ * Sets the applicable end user consent state for this app.
1193
+ * references once Firebase Analytics is initialized.
1194
1194
  * @param analytics Analytics instance.
1195
1195
  * @param consentSettings See {@link analytics.ConsentSettings}.
1196
- * @returns {void}
1196
+ * @returns {Promise<void>}
1197
1197
  */
1198
1198
  export function setConsent(
1199
1199
  analytics: Analytics,
1200
1200
  consentSettings: FirebaseAnalyticsTypes.ConsentSettings,
1201
- ): void;
1201
+ ): Promise<void>;
1202
1202
 
1203
1203
  /**
1204
1204
  * Configures Firebase Analytics to use custom gtag or dataLayer names.
@@ -648,15 +648,15 @@ export function isSupported() {
648
648
  }
649
649
 
650
650
  /**
651
- * Sets the applicable end user consent state for this web app across all gtag
652
- * references once Firebase Analytics is initialized. Web only.
651
+ * Sets the applicable end user consent state for this app.
652
+ * references once Firebase Analytics is initialized.
653
653
  * @param analytics Analytics instance.
654
654
  * @param consentSettings See {@link analytics.ConsentSettings}.
655
- * @returns {void}
655
+ * @returns {Promise<void>}
656
656
  */
657
657
  // eslint-disable-next-line
658
- export function setConsent(consentSettings) {
659
- // Returns nothing until Web implemented.
658
+ export function setConsent(analytics, consentSettings) {
659
+ return analytics.setConsent(consentSettings);
660
660
  }
661
661
 
662
662
  /**
package/lib/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // Generated by genversion.
2
- module.exports = '18.8.0';
2
+ module.exports = '19.0.0';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-native-firebase/analytics",
3
- "version": "18.8.0",
3
+ "version": "19.0.0",
4
4
  "author": "Invertase <oss@invertase.io> (http://invertase.io)",
5
5
  "description": "React Native Firebase - The analytics module provides out of the box support with Google Analytics for Firebase. Integration with the Android & iOS allows for in-depth analytical insight reporting, such as device information, location, user actions and more.",
6
6
  "main": "lib/index.js",
@@ -22,10 +22,10 @@
22
22
  "analytics"
23
23
  ],
24
24
  "peerDependencies": {
25
- "@react-native-firebase/app": "18.8.0"
25
+ "@react-native-firebase/app": "19.0.0"
26
26
  },
27
27
  "publishConfig": {
28
28
  "access": "public"
29
29
  },
30
- "gitHead": "970756d733e1c4642b53d91c5b1b8f58a8f5dbc0"
30
+ "gitHead": "53b687b7230c73248cfd92ce2b80871ca69480e8"
31
31
  }