@react-native-firebase/analytics 23.6.0 → 23.8.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.
Files changed (132) hide show
  1. package/dist/commonjs/index.js +38 -0
  2. package/dist/commonjs/index.js.map +1 -0
  3. package/dist/commonjs/modular.js +613 -0
  4. package/dist/commonjs/modular.js.map +1 -0
  5. package/dist/commonjs/namespaced.js +441 -0
  6. package/dist/commonjs/namespaced.js.map +1 -0
  7. package/dist/commonjs/package.json +1 -0
  8. package/dist/commonjs/struct.js +54 -0
  9. package/dist/commonjs/struct.js.map +1 -0
  10. package/dist/commonjs/structs.js +214 -0
  11. package/dist/commonjs/structs.js.map +1 -0
  12. package/dist/commonjs/types/analytics.js +79 -0
  13. package/dist/commonjs/types/analytics.js.map +1 -0
  14. package/dist/commonjs/types/web.js +2 -0
  15. package/dist/commonjs/types/web.js.map +1 -0
  16. package/dist/commonjs/version.js +9 -0
  17. package/dist/commonjs/version.js.map +1 -0
  18. package/dist/commonjs/web/RNFBAnalyticsModule.android.js +9 -0
  19. package/dist/commonjs/web/RNFBAnalyticsModule.android.js.map +1 -0
  20. package/dist/commonjs/web/RNFBAnalyticsModule.ios.js +9 -0
  21. package/dist/commonjs/web/RNFBAnalyticsModule.ios.js.map +1 -0
  22. package/dist/commonjs/web/RNFBAnalyticsModule.js +119 -0
  23. package/dist/commonjs/web/RNFBAnalyticsModule.js.map +1 -0
  24. package/dist/commonjs/web/api.js +294 -0
  25. package/dist/commonjs/web/api.js.map +1 -0
  26. package/{ios/RNFBAnalytics/RNFBAnalyticsModule.h → dist/module/index.js} +10 -6
  27. package/dist/module/index.js.map +1 -0
  28. package/{lib/modular/index.js → dist/module/modular.js} +43 -161
  29. package/dist/module/modular.js.map +1 -0
  30. package/dist/module/namespaced.js +438 -0
  31. package/dist/module/namespaced.js.map +1 -0
  32. package/dist/module/package.json +1 -0
  33. package/{lib → dist/module}/struct.js +12 -14
  34. package/dist/module/struct.js.map +1 -0
  35. package/dist/module/structs.js +210 -0
  36. package/dist/module/structs.js.map +1 -0
  37. package/dist/module/types/analytics.js +75 -0
  38. package/dist/module/types/analytics.js.map +1 -0
  39. package/dist/module/types/web.js +2 -0
  40. package/dist/module/types/web.js.map +1 -0
  41. package/dist/module/version.js +5 -0
  42. package/dist/module/version.js.map +1 -0
  43. package/dist/module/web/RNFBAnalyticsModule.android.js +6 -0
  44. package/dist/module/web/RNFBAnalyticsModule.android.js.map +1 -0
  45. package/dist/module/web/RNFBAnalyticsModule.ios.js +6 -0
  46. package/dist/module/web/RNFBAnalyticsModule.ios.js.map +1 -0
  47. package/{lib → dist/module}/web/RNFBAnalyticsModule.js +17 -21
  48. package/dist/module/web/RNFBAnalyticsModule.js.map +1 -0
  49. package/{lib → dist/module}/web/api.js +34 -77
  50. package/dist/module/web/api.js.map +1 -0
  51. package/dist/typescript/commonjs/lib/index.d.ts +5 -0
  52. package/dist/typescript/commonjs/lib/index.d.ts.map +1 -0
  53. package/dist/typescript/commonjs/lib/modular.d.ts +476 -0
  54. package/dist/typescript/commonjs/lib/modular.d.ts.map +1 -0
  55. package/dist/typescript/commonjs/lib/namespaced.d.ts +12 -0
  56. package/dist/typescript/commonjs/lib/namespaced.d.ts.map +1 -0
  57. package/dist/typescript/commonjs/lib/struct.d.ts +3 -0
  58. package/dist/typescript/commonjs/lib/struct.d.ts.map +1 -0
  59. package/dist/typescript/commonjs/lib/structs.d.ts +1155 -0
  60. package/dist/typescript/commonjs/lib/structs.d.ts.map +1 -0
  61. package/dist/typescript/commonjs/lib/types/analytics.d.ts +944 -0
  62. package/dist/typescript/commonjs/lib/types/analytics.d.ts.map +1 -0
  63. package/dist/typescript/commonjs/lib/types/web.d.ts +36 -0
  64. package/dist/typescript/commonjs/lib/types/web.d.ts.map +1 -0
  65. package/dist/typescript/commonjs/lib/version.d.ts +2 -0
  66. package/dist/typescript/commonjs/lib/version.d.ts.map +1 -0
  67. package/dist/typescript/commonjs/lib/web/RNFBAnalyticsModule.android.d.ts +3 -0
  68. package/dist/typescript/commonjs/lib/web/RNFBAnalyticsModule.android.d.ts.map +1 -0
  69. package/dist/typescript/commonjs/lib/web/RNFBAnalyticsModule.d.ts +9 -0
  70. package/dist/typescript/commonjs/lib/web/RNFBAnalyticsModule.d.ts.map +1 -0
  71. package/dist/typescript/commonjs/lib/web/RNFBAnalyticsModule.ios.d.ts +3 -0
  72. package/dist/typescript/commonjs/lib/web/RNFBAnalyticsModule.ios.d.ts.map +1 -0
  73. package/dist/typescript/commonjs/lib/web/api.d.ts +37 -0
  74. package/dist/typescript/commonjs/lib/web/api.d.ts.map +1 -0
  75. package/dist/typescript/commonjs/package.json +1 -0
  76. package/dist/typescript/module/lib/index.d.ts +5 -0
  77. package/dist/typescript/module/lib/index.d.ts.map +1 -0
  78. package/dist/typescript/module/lib/modular.d.ts +476 -0
  79. package/dist/typescript/module/lib/modular.d.ts.map +1 -0
  80. package/dist/typescript/module/lib/namespaced.d.ts +12 -0
  81. package/dist/typescript/module/lib/namespaced.d.ts.map +1 -0
  82. package/dist/typescript/module/lib/struct.d.ts +3 -0
  83. package/dist/typescript/module/lib/struct.d.ts.map +1 -0
  84. package/dist/typescript/module/lib/structs.d.ts +1155 -0
  85. package/dist/typescript/module/lib/structs.d.ts.map +1 -0
  86. package/dist/typescript/module/lib/types/analytics.d.ts +944 -0
  87. package/dist/typescript/module/lib/types/analytics.d.ts.map +1 -0
  88. package/dist/typescript/module/lib/types/web.d.ts +36 -0
  89. package/dist/typescript/module/lib/types/web.d.ts.map +1 -0
  90. package/dist/typescript/module/lib/version.d.ts +2 -0
  91. package/dist/typescript/module/lib/version.d.ts.map +1 -0
  92. package/dist/typescript/module/lib/web/RNFBAnalyticsModule.android.d.ts +3 -0
  93. package/dist/typescript/module/lib/web/RNFBAnalyticsModule.android.d.ts.map +1 -0
  94. package/dist/typescript/module/lib/web/RNFBAnalyticsModule.d.ts +9 -0
  95. package/dist/typescript/module/lib/web/RNFBAnalyticsModule.d.ts.map +1 -0
  96. package/dist/typescript/module/lib/web/RNFBAnalyticsModule.ios.d.ts +3 -0
  97. package/dist/typescript/module/lib/web/RNFBAnalyticsModule.ios.d.ts.map +1 -0
  98. package/dist/typescript/module/lib/web/api.d.ts +37 -0
  99. package/dist/typescript/module/lib/web/api.d.ts.map +1 -0
  100. package/dist/typescript/module/package.json +1 -0
  101. package/lib/index.ts +73 -0
  102. package/lib/modular.ts +1026 -0
  103. package/lib/{index.js → namespaced.ts} +145 -72
  104. package/lib/struct.ts +61 -0
  105. package/lib/{structs.js → structs.ts} +3 -3
  106. package/lib/types/analytics.ts +1078 -0
  107. package/lib/types/web.ts +56 -0
  108. package/lib/version.ts +2 -0
  109. package/lib/web/RNFBAnalyticsModule.android.ts +3 -0
  110. package/lib/web/RNFBAnalyticsModule.ios.ts +3 -0
  111. package/lib/web/RNFBAnalyticsModule.ts +135 -0
  112. package/lib/web/api.ts +366 -0
  113. package/package.json +61 -7
  114. package/CHANGELOG.md +0 -1081
  115. package/RNFBAnalytics.podspec +0 -71
  116. package/android/.editorconfig +0 -10
  117. package/android/build.gradle +0 -177
  118. package/android/lint.xml +0 -5
  119. package/android/settings.gradle +0 -1
  120. package/android/src/main/AndroidManifest.xml +0 -21
  121. package/android/src/main/java/io/invertase/firebase/analytics/UniversalFirebaseAnalyticsModule.java +0 -141
  122. package/android/src/reactnative/AndroidManifest.xml +0 -2
  123. package/android/src/reactnative/java/io/invertase/firebase/analytics/ReactNativeFirebaseAnalyticsModule.java +0 -213
  124. package/android/src/reactnative/java/io/invertase/firebase/analytics/ReactNativeFirebaseAnalyticsPackage.java +0 -41
  125. package/ios/RNFBAnalytics/RNFBAnalyticsModule.m +0 -268
  126. package/ios/RNFBAnalytics.xcodeproj/project.pbxproj +0 -349
  127. package/ios/RNFBAnalytics.xcodeproj/xcshareddata/IDETemplateMacros.plist +0 -24
  128. package/lib/index.d.ts +0 -1903
  129. package/lib/modular/index.d.ts +0 -1267
  130. package/lib/version.js +0 -2
  131. package/lib/web/RNFBAnalyticsModule.android.js +0 -2
  132. package/lib/web/RNFBAnalyticsModule.ios.js +0 -2
@@ -0,0 +1,56 @@
1
+ /*
2
+ * Copyright (c) 2016-present Invertase Limited & Contributors
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this library except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+ export interface AnalyticsEventParameters {
19
+ [key: string]: string | number | boolean | undefined | null;
20
+ }
21
+
22
+ export interface AnalyticsUserProperties {
23
+ [key: string]: string | number | boolean | undefined | null;
24
+ }
25
+
26
+ export interface AnalyticsConsent {
27
+ ad_personalization?: boolean;
28
+ [key: string]: boolean | undefined;
29
+ }
30
+
31
+ export interface AnalyticsApi {
32
+ logEvent(name: string, params?: AnalyticsEventParameters): void;
33
+ setUserId(userId: string | null): void;
34
+ setUserProperty(key: string, value: string | null): void;
35
+ setUserProperties(properties: AnalyticsUserProperties): void;
36
+ setDefaultEventParameters(params: AnalyticsEventParameters | null): void;
37
+ setConsent(consent: AnalyticsConsent): void;
38
+ setAnalyticsCollectionEnabled(enabled: boolean): void;
39
+ setDebug(enabled: boolean): void;
40
+ setCurrentScreen(screenName: string | null): void;
41
+ _getCid(): Promise<string>;
42
+ }
43
+
44
+ export interface RNFBAnalyticsModule {
45
+ logEvent(name: string, params?: AnalyticsEventParameters): Promise<null>;
46
+ setUserId(userId: string | null): Promise<null>;
47
+ setUserProperty(key: string, value: string | null): Promise<null>;
48
+ setUserProperties(properties: AnalyticsUserProperties): Promise<null>;
49
+ setDefaultEventParameters(params: AnalyticsEventParameters | null): Promise<null>;
50
+ setConsent(consent: AnalyticsConsent): Promise<null>;
51
+ setAnalyticsCollectionEnabled(enabled: boolean): Promise<null>;
52
+ resetAnalyticsData(): Promise<null>;
53
+ setSessionTimeoutDuration(): Promise<null>;
54
+ getAppInstanceId(): Promise<string | null>;
55
+ getSessionId(): Promise<null>;
56
+ }
package/lib/version.ts ADDED
@@ -0,0 +1,2 @@
1
+ // Generated by genversion.
2
+ export const version = '23.8.0';
@@ -0,0 +1,3 @@
1
+ // No-op for android.
2
+ const RNFBAnalyticsModule = {};
3
+ export { RNFBAnalyticsModule };
@@ -0,0 +1,3 @@
1
+ // No-op for ios.
2
+ const RNFBAnalyticsModule = {};
3
+ export { RNFBAnalyticsModule };
@@ -0,0 +1,135 @@
1
+ import { getApp } from '@react-native-firebase/app/lib/internal/web/firebaseApp';
2
+ import { guard } from '@react-native-firebase/app/lib/internal/web/utils';
3
+
4
+ import { AnalyticsApi } from './api';
5
+ import type {
6
+ AnalyticsEventParameters,
7
+ AnalyticsUserProperties,
8
+ AnalyticsConsent,
9
+ RNFBAnalyticsModule as RNFBAnalyticsModuleType,
10
+ } from '../types/web';
11
+
12
+ interface AnalyticsInstances {
13
+ [measurementId: string]: AnalyticsApi;
14
+ }
15
+
16
+ let analyticsInstances: AnalyticsInstances = {};
17
+
18
+ function getAnalyticsApi(appName: string): AnalyticsApi {
19
+ const app = getApp(appName);
20
+ const measurementId = app.options.measurementId;
21
+ if (!measurementId) {
22
+ // eslint-disable-next-line no-console
23
+ console.warn(
24
+ 'No measurement id (`FirebaseOptions.measurementId`) found for Firebase Analytics. Analytics will be unavailable.',
25
+ );
26
+ // Return a default instance with empty measurementId for cases where it's not configured
27
+ const defaultKey = 'default';
28
+ if (!analyticsInstances[defaultKey]) {
29
+ analyticsInstances[defaultKey] = new AnalyticsApi('[DEFAULT]', '');
30
+ }
31
+ return analyticsInstances[defaultKey];
32
+ }
33
+ if (!analyticsInstances[measurementId]) {
34
+ analyticsInstances[measurementId] = new AnalyticsApi('[DEFAULT]', measurementId);
35
+ if ((globalThis as any).RNFBDebug) {
36
+ analyticsInstances[measurementId].setDebug(true);
37
+ }
38
+ }
39
+ return analyticsInstances[measurementId];
40
+ }
41
+
42
+ /**
43
+ * This is a 'NativeModule' for the web platform.
44
+ * Methods here are identical to the ones found in
45
+ * the native android/ios modules e.g. `@ReactMethod` annotated
46
+ * java methods on Android.
47
+ */
48
+ export const RNFBAnalyticsModule: RNFBAnalyticsModuleType = {
49
+ logEvent(name: string, params?: AnalyticsEventParameters): Promise<null> {
50
+ return guard(async () => {
51
+ const api = getAnalyticsApi('[DEFAULT]');
52
+ api.logEvent(name, params);
53
+ return null;
54
+ });
55
+ },
56
+
57
+ setUserId(userId: string | null): Promise<null> {
58
+ return guard(async () => {
59
+ const api = getAnalyticsApi('[DEFAULT]');
60
+ api.setUserId(userId);
61
+ return null;
62
+ });
63
+ },
64
+
65
+ setUserProperty(key: string, value: string | null): Promise<null> {
66
+ return guard(async () => {
67
+ const api = getAnalyticsApi('[DEFAULT]');
68
+ api.setUserProperty(key, value);
69
+ return null;
70
+ });
71
+ },
72
+
73
+ setUserProperties(properties: AnalyticsUserProperties): Promise<null> {
74
+ return guard(async () => {
75
+ const api = getAnalyticsApi('[DEFAULT]');
76
+ api.setUserProperties(properties);
77
+ return null;
78
+ });
79
+ },
80
+
81
+ setDefaultEventParameters(params: AnalyticsEventParameters | null): Promise<null> {
82
+ return guard(async () => {
83
+ const api = getAnalyticsApi('[DEFAULT]');
84
+ api.setDefaultEventParameters(params);
85
+ return null;
86
+ });
87
+ },
88
+
89
+ setConsent(consent: AnalyticsConsent): Promise<null> {
90
+ return guard(async () => {
91
+ const api = getAnalyticsApi('[DEFAULT]');
92
+ // TODO currently we only support ad_personalization
93
+ if (consent && consent.ad_personalization !== undefined) {
94
+ api.setConsent({ ad_personalization: consent.ad_personalization });
95
+ }
96
+ return null;
97
+ });
98
+ },
99
+
100
+ setAnalyticsCollectionEnabled(enabled: boolean): Promise<null> {
101
+ return guard(async () => {
102
+ const api = getAnalyticsApi('[DEFAULT]');
103
+ api.setAnalyticsCollectionEnabled(enabled);
104
+ return null;
105
+ });
106
+ },
107
+
108
+ resetAnalyticsData(): Promise<null> {
109
+ // Unsupported for web.
110
+ return guard(async () => {
111
+ return null;
112
+ });
113
+ },
114
+
115
+ setSessionTimeoutDuration(): Promise<null> {
116
+ // Unsupported for web.
117
+ return guard(async () => {
118
+ return null;
119
+ });
120
+ },
121
+
122
+ getAppInstanceId(): Promise<string | null> {
123
+ return guard(async () => {
124
+ const api = getAnalyticsApi('[DEFAULT]');
125
+ return api._getCid();
126
+ });
127
+ },
128
+
129
+ getSessionId(): Promise<null> {
130
+ // Unsupported for web.
131
+ return guard(async () => {
132
+ return null;
133
+ });
134
+ },
135
+ };
package/lib/web/api.ts ADDED
@@ -0,0 +1,366 @@
1
+ /* eslint-disable no-console */
2
+ import {
3
+ getApp,
4
+ getId,
5
+ onIdChange,
6
+ getInstallations,
7
+ makeIDBAvailable,
8
+ } from '@react-native-firebase/app/lib/internal/web/firebaseInstallations';
9
+ import {
10
+ getItem,
11
+ setItem,
12
+ isMemoryStorage,
13
+ } from '@react-native-firebase/app/lib/internal/asyncStorage';
14
+
15
+ import { isNumber } from '@react-native-firebase/app/lib/common';
16
+ import type {
17
+ AnalyticsEventParameters,
18
+ AnalyticsUserProperties,
19
+ AnalyticsConsent,
20
+ AnalyticsApi as IAnalyticsApi,
21
+ } from '../types/web';
22
+
23
+ /**
24
+ * Generates a Google Analytics client ID.
25
+ * @returns {string} The generated client ID.
26
+ */
27
+ function generateGAClientId(): string {
28
+ const randomNumber = Math.round(Math.random() * 2147483647);
29
+ // TODO: Don't seem to need this for now.
30
+ // var hash = 1;
31
+ // if (seed) {
32
+ // for (var i = seed.length - 1; i >= 0; i--) {
33
+ // var char = seed.charCodeAt(i);
34
+ // hash = ((hash << 6) & 268435455) + char + (char << 14);
35
+ // var flag = hash & 266338304;
36
+ // hash = flag !== 0 ? hash ^ (flag >> 21) : hash;
37
+ // }
38
+ // }
39
+ // const randomPart = seed ? String(randomNumber ^ (hash & 2147483647)) : String(randomNumber);
40
+ const randomPart = String(randomNumber);
41
+ const timestamp = Math.round(Date.now() / 1000);
42
+ return randomPart + '.' + timestamp;
43
+ }
44
+
45
+ interface AnalyticsEvent {
46
+ name: string;
47
+ params: AnalyticsEventParameters;
48
+ }
49
+
50
+ class AnalyticsApi implements IAnalyticsApi {
51
+ public readonly appName: string;
52
+ public readonly measurementId: string;
53
+ private eventQueue: AnalyticsEvent[];
54
+ private queueTimer: number | null;
55
+ private readonly queueInterval: number;
56
+ private defaultEventParameters: AnalyticsEventParameters;
57
+ private userId: string | null;
58
+ private userProperties: AnalyticsUserProperties;
59
+ private consent: AnalyticsConsent;
60
+ private analyticsCollectionEnabled: boolean;
61
+ private started: boolean;
62
+ private installationId: string | null;
63
+ private debug: boolean;
64
+ private currentScreen: string | null;
65
+ private sessionId?: number;
66
+ private cid?: string | null;
67
+
68
+ constructor(appName: string, measurementId: string) {
69
+ this.appName = appName;
70
+ this.measurementId = measurementId;
71
+ this.eventQueue = [];
72
+ this.queueTimer = null;
73
+ this.queueInterval = 250;
74
+ this.defaultEventParameters = {};
75
+ this.userId = null;
76
+ this.userProperties = {};
77
+ this.consent = {};
78
+ this.analyticsCollectionEnabled = true;
79
+ this.started = false;
80
+ this.installationId = null;
81
+ this.debug = false;
82
+ this.currentScreen = null;
83
+
84
+ this._getInstallationId().catch(error => {
85
+ if ((globalThis as any).RNFBDebug) {
86
+ console.debug('[RNFB->Analytics][🔴] Error getting Firebase Installation Id:', error);
87
+ } else {
88
+ // No-op. This is a non-critical error.
89
+ }
90
+ });
91
+ }
92
+
93
+ setDefaultEventParameters(params: AnalyticsEventParameters | null): void {
94
+ if (params === null || params === undefined) {
95
+ this.defaultEventParameters = {};
96
+ } else {
97
+ for (const [key, value] of Object.entries(params)) {
98
+ this.defaultEventParameters[key] = value;
99
+ if (value === null) {
100
+ delete this.defaultEventParameters[key];
101
+ }
102
+ }
103
+ }
104
+ }
105
+
106
+ setDebug(enabled: boolean): void {
107
+ this.debug = enabled;
108
+ }
109
+
110
+ setUserId(userId: string | null): void {
111
+ this.userId = userId;
112
+ }
113
+
114
+ setCurrentScreen(screenName: string | null): void {
115
+ this.currentScreen = screenName;
116
+ }
117
+
118
+ setUserProperty(key: string, value: string | null): void {
119
+ this.userProperties[key] = value;
120
+ if (value === null) {
121
+ delete this.userProperties[key];
122
+ }
123
+ }
124
+
125
+ setUserProperties(properties: AnalyticsUserProperties): void {
126
+ for (const [key, value] of Object.entries(properties)) {
127
+ this.setUserProperty(key, value as string | null);
128
+ }
129
+ }
130
+
131
+ setConsent(consentSettings: AnalyticsConsent): void {
132
+ this.consent = { ...this.consent, ...consentSettings };
133
+ }
134
+
135
+ setAnalyticsCollectionEnabled(enabled: boolean): void {
136
+ this.analyticsCollectionEnabled = enabled;
137
+ if (!enabled) {
138
+ this._stopQueueProcessing();
139
+ } else {
140
+ this._startQueueProcessing();
141
+ }
142
+ }
143
+
144
+ logEvent(eventName: string, eventParams: AnalyticsEventParameters = {}): void {
145
+ if (!this.analyticsCollectionEnabled) return;
146
+ this.eventQueue.push({
147
+ name: eventName,
148
+ params: { ...this.defaultEventParameters, ...eventParams },
149
+ });
150
+ this._startQueueProcessing();
151
+ }
152
+
153
+ private async _getInstallationId(): Promise<void> {
154
+ // @ts-ignore
155
+ if (navigator !== null) {
156
+ // @ts-ignore
157
+ (navigator as any).onLine = true;
158
+ }
159
+ makeIDBAvailable();
160
+ const app = getApp(this.appName);
161
+ const installations = getInstallations(app);
162
+ const id = await getId(installations);
163
+ if ((globalThis as any).RNFBDebug) {
164
+ console.debug('[RNFB->Analytics][📊] Firebase Installation Id:', id);
165
+ }
166
+ this.installationId = id;
167
+ onIdChange(installations, (newId: string) => {
168
+ this.installationId = newId;
169
+ });
170
+ }
171
+
172
+ private _startQueueProcessing(): void {
173
+ if (this.started) return;
174
+ this.sessionId = Math.floor(Date.now() / 1000);
175
+ this.started = true;
176
+ this.queueTimer = setInterval(
177
+ () => this._processQueue().catch(console.error),
178
+ this.queueInterval,
179
+ ) as unknown as number;
180
+ }
181
+
182
+ private _stopQueueProcessing(): void {
183
+ if (!this.started) return;
184
+ this.started = false;
185
+ if (this.queueTimer) {
186
+ clearInterval(this.queueTimer);
187
+ }
188
+ }
189
+
190
+ private async _processQueue(): Promise<void> {
191
+ if (this.eventQueue.length === 0) return;
192
+ const events = this.eventQueue.splice(0, 5);
193
+ await this._sendEvents(events);
194
+ if (this.eventQueue.length === 0) {
195
+ this._stopQueueProcessing();
196
+ }
197
+ }
198
+
199
+ async _getCid(): Promise<string> {
200
+ this.cid = await getItem('analytics:cid');
201
+ if (this.cid) {
202
+ return this.cid;
203
+ }
204
+ this.cid = generateGAClientId();
205
+ await setItem('analytics:cid', this.cid);
206
+ if (isMemoryStorage()) {
207
+ console.warn(
208
+ 'Firebase Analytics is using in memory persistence. This means that the analytics\n' +
209
+ 'client ID is reset every time your app is restarted which may result in\n' +
210
+ 'inaccurate data being shown on the Firebase Analytics dashboard.\n' +
211
+ '\n' +
212
+ 'To enable persistence, provide an Async Storage implementation.\n' +
213
+ '\n' +
214
+ 'For example, to use React Native Async Storage:\n' +
215
+ '\n' +
216
+ " import AsyncStorage from '@react-native-async-storage/async-storage';\n" +
217
+ '\n' +
218
+ ' // Before initializing Firebase set the Async Storage implementation\n' +
219
+ ' // that will be used to persist user sessions.\n' +
220
+ ' firebase.setReactNativeAsyncStorage(AsyncStorage);\n' +
221
+ '\n' +
222
+ ' // Then initialize Firebase as normal.\n' +
223
+ ' await firebase.initializeApp({ ... });\n',
224
+ );
225
+ }
226
+ return this.cid;
227
+ }
228
+
229
+ private async _sendEvents(events: AnalyticsEvent[]): Promise<void> {
230
+ const cid = this.cid || (await this._getCid());
231
+ for (const event of events) {
232
+ const queryParams = new URLSearchParams({
233
+ v: '2',
234
+ tid: this.measurementId,
235
+ en: event.name,
236
+ cid,
237
+ pscdl: 'noapi',
238
+ sid: String(this.sessionId),
239
+ 'ep.origin': 'firebase',
240
+ _z: 'fetch',
241
+ _p: '' + Date.now(),
242
+ _s: '1',
243
+ _ee: '1',
244
+ dma: '0',
245
+ tfd: String(Math.round(performance.now())),
246
+ are: '1',
247
+ sct: '2',
248
+ seg: '1',
249
+ frm: '0',
250
+ });
251
+
252
+ if (this.debug) {
253
+ queryParams.append('_dbg', '1');
254
+ queryParams.append('ep.debug_mode', '1');
255
+ }
256
+
257
+ if (this.consent && !this.consent.ad_personalization) {
258
+ queryParams.append('npa', '1');
259
+ } else {
260
+ queryParams.append('npa', '0');
261
+ }
262
+
263
+ if (this.userId) {
264
+ queryParams.append('uid', this.userId);
265
+ }
266
+
267
+ if (this.installationId) {
268
+ queryParams.append('_fid', this.installationId);
269
+ }
270
+
271
+ if (this.userProperties && Object.keys(this.userProperties).length > 0) {
272
+ for (const [key, value] of Object.entries(this.userProperties)) {
273
+ queryParams.append(`up.${key}`, `${value}`);
274
+ }
275
+ }
276
+
277
+ if (this.currentScreen) {
278
+ queryParams.append('ep.screen_name', this.currentScreen);
279
+ queryParams.append('ep.firebase_screen', this.currentScreen);
280
+ }
281
+
282
+ if (event.params && Object.keys(event.params).length > 0) {
283
+ // TODO we need to handle 'items' arrays and also key name conversions based on the following map;
284
+ // const keyConvert = {
285
+ // item_id: 'id',
286
+ // item_name: 'nm',
287
+ // item_brand: 'br',
288
+ // item_category: 'ca',
289
+ // item_category2: 'c2',
290
+ // item_category3: 'c3',
291
+ // item_category4: 'c4',
292
+ // item_category5: 'c5',
293
+ // item_variant: 'va',
294
+ // price: 'pr',
295
+ // quantity: 'qt',
296
+ // coupon: 'cp',
297
+ // item_list_name: 'ln',
298
+ // index: 'lp',
299
+ // item_list_id: 'li',
300
+ // discount: 'ds',
301
+ // affiliation: 'af',
302
+ // promotion_id: 'pi',
303
+ // promotion_name: 'pn',
304
+ // creative_name: 'cn',
305
+ // creative_slot: 'cs',
306
+ // location_id: 'lo',
307
+ // id: 'id',
308
+ // name: 'nm',
309
+ // brand: 'br',
310
+ // variant: 'va',
311
+ // list_name: 'ln',
312
+ // list_position: 'lp',
313
+ // list: 'ln',
314
+ // position: 'lp',
315
+ // creative: 'cn',
316
+ // };
317
+ // items array should for example become:
318
+ // pr1 for items[0]
319
+ // pr2 for items[1]
320
+ // ... etc
321
+ // with the format for each looking something like:
322
+ // iditem_id~nmitem_name~britem_brand~caitem_category~c2item_category2~c3item_category3~c4item_category4~c5item_category5~vaitem_variant~prprice~qtquantity~cpcoupon~lnitem_list_name~lpindex~liitem_list_id~dsdiscount~afaffiliation~pipromotion_id~pnpromotion_name~cncreative_name~cscreative_slot~lolocation_id
323
+ for (const [key, value] of Object.entries(event.params)) {
324
+ if (isNumber(value)) {
325
+ queryParams.append(`epn.${key}`, `${value}`);
326
+ } else {
327
+ queryParams.append(`ep.${key}`, `${value}`);
328
+ }
329
+ }
330
+ }
331
+
332
+ try {
333
+ const url = `https://www.google-analytics.com/g/collect?${queryParams.toString()}`;
334
+ if ((globalThis as any).RNFBDebug) {
335
+ console.debug(`[RNFB-->Fetch][📊] Sending analytics call: ${url}`);
336
+ }
337
+ const response = await fetch(url, {
338
+ method: 'POST',
339
+ mode: 'no-cors',
340
+ headers: {
341
+ accept: '*/*',
342
+ 'accept-encoding': 'gzip, deflate, br',
343
+ 'Content-Type': 'text/plain;charset=UTF-8',
344
+ 'accept-language': 'en-US,en;q=0.9',
345
+ 'cache-control': 'no-cache',
346
+ 'content-length': '0',
347
+ origin: 'firebase',
348
+ pragma: 'no-cache',
349
+ 'sec-fetch-dest': 'empty',
350
+ 'sec-fetch-site': 'cross-site',
351
+ 'user-agent': 'react-native-firebase',
352
+ },
353
+ });
354
+ if ((globalThis as any).RNFBDebug) {
355
+ console.debug(`[RNFB<--Fetch][📊] Response: ${response.status}`);
356
+ }
357
+ } catch (error) {
358
+ if ((globalThis as any).RNFBDebug) {
359
+ console.debug('[RNFB<--Fetch][🔴] Error sending Analytics event:', error);
360
+ }
361
+ }
362
+ }
363
+ }
364
+ }
365
+
366
+ export { AnalyticsApi };
package/package.json CHANGED
@@ -1,14 +1,16 @@
1
1
  {
2
2
  "name": "@react-native-firebase/analytics",
3
- "version": "23.6.0",
3
+ "version": "23.8.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
- "main": "lib/index.js",
7
- "types": "lib/index.d.ts",
6
+ "main": "./dist/commonjs/index.js",
7
+ "module": "./dist/module/index.js",
8
+ "types": "./dist/typescript/commonjs/lib/index.d.ts",
8
9
  "scripts": {
9
- "build": "genversion --semi lib/version.js",
10
+ "build": "genversion --esm --semi lib/version.ts",
10
11
  "build:clean": "rimraf android/build && rimraf ios/build",
11
- "prepare": "yarn run build"
12
+ "compile": "bob build",
13
+ "prepare": "yarn run build && yarn compile"
12
14
  },
13
15
  "repository": {
14
16
  "type": "git",
@@ -22,7 +24,7 @@
22
24
  "analytics"
23
25
  ],
24
26
  "peerDependencies": {
25
- "@react-native-firebase/app": "23.6.0"
27
+ "@react-native-firebase/app": "23.8.0"
26
28
  },
27
29
  "publishConfig": {
28
30
  "access": "public",
@@ -31,5 +33,57 @@
31
33
  "dependencies": {
32
34
  "superstruct": "^2.0.2"
33
35
  },
34
- "gitHead": "748e89f9bfcdfbee971c627cd8a698963ba09f33"
36
+ "devDependencies": {
37
+ "react-native-builder-bob": "^0.40.13"
38
+ },
39
+ "exports": {
40
+ ".": {
41
+ "source": "./lib/index.ts",
42
+ "import": {
43
+ "types": "./dist/typescript/module/lib/index.d.ts",
44
+ "default": "./dist/module/index.js"
45
+ },
46
+ "require": {
47
+ "types": "./dist/typescript/commonjs/lib/index.d.ts",
48
+ "default": "./dist/commonjs/index.js"
49
+ }
50
+ },
51
+ "./package.json": "./package.json"
52
+ },
53
+ "files": [
54
+ "lib",
55
+ "dist",
56
+ "!**/__tests__",
57
+ "!**/__fixtures__",
58
+ "!**/__mocks__"
59
+ ],
60
+ "react-native-builder-bob": {
61
+ "source": "lib",
62
+ "output": "dist",
63
+ "targets": [
64
+ [
65
+ "module",
66
+ {
67
+ "esm": true
68
+ }
69
+ ],
70
+ [
71
+ "commonjs",
72
+ {
73
+ "esm": true
74
+ }
75
+ ],
76
+ [
77
+ "typescript",
78
+ {
79
+ "tsc": "../../node_modules/.bin/tsc"
80
+ }
81
+ ]
82
+ ]
83
+ },
84
+ "eslintIgnore": [
85
+ "node_modules/",
86
+ "dist/"
87
+ ],
88
+ "gitHead": "724ddcfea6ebe93875e5a54ff38ca57ab5990822"
35
89
  }