@snowplow/react-native-tracker 1.4.0 → 2.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.
Files changed (239) hide show
  1. package/.editorconfig +15 -0
  2. package/.eslintignore +6 -0
  3. package/.gitattributes +3 -0
  4. package/.github/ISSUE_TEMPLATE/bug_report.md +29 -0
  5. package/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  6. package/.github/actions/setup/action.yml +28 -0
  7. package/.github/workflows/build.yml +150 -0
  8. package/.github/workflows/deploy.yml +98 -0
  9. package/.github/workflows/e2e-android.yml +121 -0
  10. package/.github/workflows/e2e-ios.yml +90 -0
  11. package/.github/workflows/snyk.yml +21 -0
  12. package/.gitignore +70 -0
  13. package/.npmignore +60 -0
  14. package/.nvmrc +1 -0
  15. package/.watchmanconfig +1 -0
  16. package/.yarnrc +3 -0
  17. package/CHANGELOG +166 -0
  18. package/CONTRIBUTING.md +80 -0
  19. package/README.md +23 -110
  20. package/android/build.gradle +93 -37
  21. package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  22. package/android/gradle/wrapper/gradle-wrapper.properties +1 -2
  23. package/android/gradle.properties +5 -2
  24. package/android/gradlew +172 -110
  25. package/android/gradlew.bat +24 -19
  26. package/android/src/main/AndroidManifest.xml +1 -3
  27. package/android/src/main/AndroidManifestNew.xml +2 -0
  28. package/android/src/main/java/com/snowplow/reactnativetracker/ReactNativeTrackerModule.kt +704 -0
  29. package/android/src/main/java/com/snowplow/reactnativetracker/ReactNativeTrackerPackage.kt +17 -0
  30. package/android/src/main/java/com/snowplow/reactnativetracker/util/ConfigUtil.kt +271 -0
  31. package/android/src/main/java/com/snowplow/reactnativetracker/util/EventUtil.kt +213 -0
  32. package/android/src/main/java/com/snowplow/reactnativetracker/util/TrackerVersion.kt +5 -0
  33. package/babel.config.js +3 -0
  34. package/example/.watchmanconfig +1 -0
  35. package/example/Gemfile +6 -0
  36. package/example/android/app/build.gradle +129 -0
  37. package/example/android/app/debug.keystore +0 -0
  38. package/example/android/app/proguard-rules.pro +10 -0
  39. package/example/android/app/src/androidTest/java/com/reactnativetrackerexample/DetoxTest.java +36 -0
  40. package/example/android/app/src/androidTest/java/com/reactnativetrackerexample/DetoxTestAppJUnitRunner.java +21 -0
  41. package/example/android/app/src/debug/AndroidManifest.xml +13 -0
  42. package/example/android/app/src/debug/java/com/reactnativetrackerexample/ReactNativeFlipper.java +75 -0
  43. package/example/android/app/src/main/AndroidManifest.xml +26 -0
  44. package/example/android/app/src/main/java/com/reactnativetrackerexample/MainActivity.java +32 -0
  45. package/example/android/app/src/main/java/com/reactnativetrackerexample/MainApplication.java +62 -0
  46. package/example/android/app/src/main/res/drawable/rn_edit_text_material.xml +36 -0
  47. package/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
  48. package/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
  49. package/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
  50. package/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
  51. package/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  52. package/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
  53. package/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  54. package/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
  55. package/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  56. package/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
  57. package/example/android/app/src/main/res/values/strings.xml +3 -0
  58. package/example/android/app/src/main/res/values/styles.xml +9 -0
  59. package/example/android/app/src/release/java/com/reactnativetrackerexample/ReactNativeFlipper.java +20 -0
  60. package/example/android/build.gradle +31 -0
  61. package/example/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  62. package/example/android/gradle/wrapper/gradle-wrapper.properties +6 -0
  63. package/example/android/gradle.properties +44 -0
  64. package/example/android/gradlew +244 -0
  65. package/example/android/gradlew.bat +92 -0
  66. package/example/android/settings.gradle +4 -0
  67. package/example/app.json +4 -0
  68. package/example/babel.config.js +17 -0
  69. package/example/detox.config.js +92 -0
  70. package/example/e2e/config.json +10 -0
  71. package/example/e2e/emitEvents.e2e.detox.js +108 -0
  72. package/example/e2e/environment.js +23 -0
  73. package/example/e2e/helpers/microCommands.js +153 -0
  74. package/example/e2e/helpers/microHelpers.js +346 -0
  75. package/example/e2e/helpers/microHelpers.test.js +308 -0
  76. package/example/e2e/helpers/schemas.js +62 -0
  77. package/example/e2e/jest.config.js +16 -0
  78. package/example/e2e/setup.js +4 -0
  79. package/example/e2e/testEvents.micro.test.js +300 -0
  80. package/example/index.js +5 -0
  81. package/example/ios/.xcode.env +11 -0
  82. package/example/ios/Podfile +64 -0
  83. package/example/ios/Podfile.lock +737 -0
  84. package/example/ios/ReactNativeTrackerExample/AppDelegate.h +6 -0
  85. package/example/ios/ReactNativeTrackerExample/AppDelegate.mm +26 -0
  86. package/example/ios/ReactNativeTrackerExample/Images.xcassets/AppIcon.appiconset/Contents.json +53 -0
  87. package/example/ios/ReactNativeTrackerExample/Images.xcassets/Contents.json +6 -0
  88. package/example/ios/ReactNativeTrackerExample/Info.plist +55 -0
  89. package/example/ios/ReactNativeTrackerExample/LaunchScreen.storyboard +47 -0
  90. package/example/ios/ReactNativeTrackerExample/main.m +10 -0
  91. package/example/ios/ReactNativeTrackerExample-Bridging-Header.h +3 -0
  92. package/example/ios/ReactNativeTrackerExample.xcodeproj/project.pbxproj +722 -0
  93. package/{ios/RNSnowplowTracker.xcodeproj/xcshareddata/xcschemes/RNSnowplowTracker.xcscheme → example/ios/ReactNativeTrackerExample.xcodeproj/xcshareddata/xcschemes/ReactNativeTrackerExample.xcscheme} +29 -21
  94. package/example/ios/ReactNativeTrackerExample.xcworkspace/contents.xcworkspacedata +10 -0
  95. package/example/ios/ReactNativeTrackerExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  96. package/example/ios/ReactNativeTrackerExampleTests/Info.plist +24 -0
  97. package/example/ios/ReactNativeTrackerExampleTests/ReactNativeTrackerExampleTests.m +66 -0
  98. package/example/metro.config.js +45 -0
  99. package/example/package.json +54 -0
  100. package/example/react-native.config.js +10 -0
  101. package/example/src/App.js +557 -0
  102. package/example/tsconfig.json +5 -0
  103. package/example/yarn.lock +7379 -0
  104. package/ios/ReactNativeTracker-Bridging-Header.h +2 -0
  105. package/ios/ReactNativeTracker.mm +165 -0
  106. package/ios/ReactNativeTracker.swift +757 -0
  107. package/ios/{RNSnowplowTracker.xcodeproj → ReactNativeTracker.xcodeproj}/project.pbxproj +55 -79
  108. package/ios/Util/ConfigUtils.swift +206 -0
  109. package/ios/Util/TrackerVersion.swift +3 -0
  110. package/ios/Util/Utilities.swift +37 -0
  111. package/lefthook.yml +11 -0
  112. package/lib/commonjs/api.js +475 -0
  113. package/lib/commonjs/api.js.map +1 -0
  114. package/lib/commonjs/configurations.js +209 -0
  115. package/lib/commonjs/configurations.js.map +1 -0
  116. package/lib/commonjs/constants.js +85 -0
  117. package/lib/commonjs/constants.js.map +1 -0
  118. package/lib/commonjs/events.js +256 -0
  119. package/lib/commonjs/events.js.map +1 -0
  120. package/lib/commonjs/index.js +141 -0
  121. package/lib/commonjs/index.js.map +1 -0
  122. package/lib/commonjs/jsCore.js +393 -0
  123. package/lib/commonjs/jsCore.js.map +1 -0
  124. package/lib/commonjs/native.js +29 -0
  125. package/lib/commonjs/native.js.map +1 -0
  126. package/lib/commonjs/subject.js +248 -0
  127. package/lib/commonjs/subject.js.map +1 -0
  128. package/lib/commonjs/tracker.js +221 -0
  129. package/lib/commonjs/tracker.js.map +1 -0
  130. package/lib/commonjs/types.js +2 -0
  131. package/lib/commonjs/types.js.map +1 -0
  132. package/lib/commonjs/utils.js +85 -0
  133. package/lib/commonjs/utils.js.map +1 -0
  134. package/lib/commonjs/webViewInterface.js +79 -0
  135. package/lib/commonjs/webViewInterface.js.map +1 -0
  136. package/lib/module/api.js +439 -0
  137. package/lib/module/api.js.map +1 -0
  138. package/lib/module/configurations.js +197 -0
  139. package/lib/module/configurations.js.map +1 -0
  140. package/lib/module/constants.js +80 -0
  141. package/lib/module/constants.js.map +1 -0
  142. package/lib/module/events.js +240 -0
  143. package/lib/module/events.js.map +1 -0
  144. package/lib/module/index.js +129 -0
  145. package/lib/module/index.js.map +1 -0
  146. package/lib/module/jsCore.js +390 -0
  147. package/lib/module/jsCore.js.map +1 -0
  148. package/lib/module/native.js +25 -0
  149. package/lib/module/native.js.map +1 -0
  150. package/lib/module/subject.js +235 -0
  151. package/lib/module/subject.js.map +1 -0
  152. package/lib/module/tracker.js +209 -0
  153. package/lib/module/tracker.js.map +1 -0
  154. package/lib/module/types.js +2 -0
  155. package/lib/module/types.js.map +1 -0
  156. package/lib/module/utils.js +79 -0
  157. package/lib/module/utils.js.map +1 -0
  158. package/lib/module/webViewInterface.js +75 -0
  159. package/lib/module/webViewInterface.js.map +1 -0
  160. package/lib/typescript/__tests__/api.test.d.ts +2 -0
  161. package/lib/typescript/__tests__/api.test.d.ts.map +1 -0
  162. package/lib/typescript/__tests__/configurations.test.d.ts +2 -0
  163. package/lib/typescript/__tests__/configurations.test.d.ts.map +1 -0
  164. package/lib/typescript/__tests__/events.test.d.ts +2 -0
  165. package/lib/typescript/__tests__/events.test.d.ts.map +1 -0
  166. package/lib/typescript/__tests__/index.test.d.ts +2 -0
  167. package/lib/typescript/__tests__/index.test.d.ts.map +1 -0
  168. package/lib/typescript/__tests__/jsCore.test.d.ts +2 -0
  169. package/lib/typescript/__tests__/jsCore.test.d.ts.map +1 -0
  170. package/lib/typescript/__tests__/utils.test.d.ts +2 -0
  171. package/lib/typescript/__tests__/utils.test.d.ts.map +1 -0
  172. package/lib/typescript/api.d.ts +226 -0
  173. package/lib/typescript/api.d.ts.map +1 -0
  174. package/lib/typescript/configurations.d.ts +73 -0
  175. package/lib/typescript/configurations.d.ts.map +1 -0
  176. package/lib/typescript/constants.d.ts +59 -0
  177. package/lib/typescript/constants.d.ts.map +1 -0
  178. package/lib/typescript/events.d.ts +101 -0
  179. package/lib/typescript/events.d.ts.map +1 -0
  180. package/lib/typescript/index.d.ts +27 -0
  181. package/lib/typescript/index.d.ts.map +1 -0
  182. package/lib/typescript/jsCore.d.ts +140 -0
  183. package/lib/typescript/jsCore.d.ts.map +1 -0
  184. package/lib/typescript/native.d.ts +4 -0
  185. package/lib/typescript/native.d.ts.map +1 -0
  186. package/lib/typescript/subject.d.ts +91 -0
  187. package/lib/typescript/subject.d.ts.map +1 -0
  188. package/lib/typescript/tracker.d.ts +93 -0
  189. package/lib/typescript/tracker.d.ts.map +1 -0
  190. package/{dist/index.d.ts → lib/typescript/types.d.ts} +188 -75
  191. package/lib/typescript/types.d.ts.map +1 -0
  192. package/lib/typescript/utils.d.ts +35 -0
  193. package/lib/typescript/utils.d.ts.map +1 -0
  194. package/lib/typescript/webViewInterface.d.ts +15 -0
  195. package/lib/typescript/webViewInterface.d.ts.map +1 -0
  196. package/package.json +134 -52
  197. package/scripts/bootstrap.js +29 -0
  198. package/snowplow-react-native-tracker.podspec +42 -0
  199. package/src/__mocks__/react-native.js +7 -0
  200. package/src/__tests__/api.test.ts +34 -0
  201. package/src/__tests__/configurations.test.ts +620 -0
  202. package/src/__tests__/events.test.ts +749 -0
  203. package/src/__tests__/index.test.ts +27 -0
  204. package/src/__tests__/jsCore.test.ts +169 -0
  205. package/src/__tests__/utils.test.ts +23 -0
  206. package/src/api.ts +535 -0
  207. package/src/configurations.ts +337 -0
  208. package/src/constants.ts +102 -0
  209. package/src/events.ts +330 -0
  210. package/src/index.ts +189 -0
  211. package/src/jsCore.ts +553 -0
  212. package/src/native.ts +34 -0
  213. package/src/subject.ts +315 -0
  214. package/src/tracker.ts +330 -0
  215. package/src/types.ts +1087 -0
  216. package/src/utils.ts +78 -0
  217. package/src/webViewInterface.ts +105 -0
  218. package/tsconfig.build.json +5 -0
  219. package/tsconfig.json +28 -0
  220. package/turbo.json +34 -0
  221. package/yarn.lock +9333 -0
  222. package/RNSnowplowTracker.podspec +0 -24
  223. package/android/src/main/java/com/snowplowanalytics/react/tracker/RNSnowplowTrackerModule.java +0 -750
  224. package/android/src/main/java/com/snowplowanalytics/react/tracker/RNSnowplowTrackerPackage.java +0 -29
  225. package/android/src/main/java/com/snowplowanalytics/react/util/ConfigUtil.java +0 -351
  226. package/android/src/main/java/com/snowplowanalytics/react/util/EventUtil.java +0 -339
  227. package/android/src/main/java/com/snowplowanalytics/react/util/TrackerVersion.java +0 -7
  228. package/dist/index.js +0 -2026
  229. package/dist/index.js.map +0 -1
  230. package/ios/RNSnowplowTracker.h +0 -34
  231. package/ios/RNSnowplowTracker.m +0 -911
  232. package/ios/Util/NSDictionary+RNSP_TypeMethods.h +0 -33
  233. package/ios/Util/NSDictionary+RNSP_TypeMethods.m +0 -40
  234. package/ios/Util/RNConfigUtils.h +0 -44
  235. package/ios/Util/RNConfigUtils.m +0 -209
  236. package/ios/Util/RNTrackerVersion.h +0 -27
  237. package/ios/Util/RNTrackerVersion.m +0 -27
  238. package/ios/Util/RNUtilities.h +0 -32
  239. package/ios/Util/RNUtilities.m +0 -68
package/src/jsCore.ts ADDED
@@ -0,0 +1,553 @@
1
+ /*
2
+ * Copyright (c) 2020-2023 Snowplow Analytics Ltd. All rights reserved.
3
+ *
4
+ * This program is licensed to you under the Apache License Version 2.0,
5
+ * and you may not use this file except in compliance with the Apache License Version 2.0.
6
+ * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
7
+ *
8
+ * Unless required by applicable law or agreed to in writing,
9
+ * software distributed under the Apache License Version 2.0 is distributed on an
10
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
12
+ */
13
+
14
+ 'use strict';
15
+
16
+ import type {
17
+ InitTrackerConfiguration,
18
+ SelfDescribing,
19
+ EventContext,
20
+ StructuredProps,
21
+ ScreenViewProps,
22
+ ScreenSize,
23
+ PageViewProps,
24
+ TimingProps,
25
+ ConsentGrantedProps,
26
+ ConsentWithdrawnProps,
27
+ EcommerceTransactionProps,
28
+ DeepLinkReceivedProps,
29
+ MessageNotificationProps,
30
+ NetworkConfiguration,
31
+ } from './types';
32
+
33
+ import {
34
+ type Payload,
35
+ trackerCore,
36
+ type PayloadBuilder,
37
+ buildSelfDescribingEvent,
38
+ buildStructEvent,
39
+ buildPageView,
40
+ buildConsentGranted,
41
+ buildConsentWithdrawn,
42
+ buildEcommerceTransaction,
43
+ buildEcommerceTransactionItem,
44
+ } from '@snowplow/tracker-core';
45
+ import type { TrackerCore } from '@snowplow/tracker-core';
46
+ import { errorHandler } from './utils';
47
+ import { schemas } from './constants';
48
+ import { v4 as uuid } from 'uuid';
49
+
50
+ // Tracker version added to the events
51
+ const trackerVersion = 'rn-2.0.0';
52
+
53
+ interface Tracker extends TrackerCore {
54
+ setDomainUserId: (duid: string | undefined) => void;
55
+ setNetworkUserId: (nuid: string | undefined) => void;
56
+ }
57
+
58
+ let trackers: { [namespace: string]: Tracker } = {};
59
+
60
+ function preparePayload(payload: Payload): Record<string, string> {
61
+ const stringifiedPayload: Record<string, string> = {};
62
+
63
+ payload['stm'] = new Date().getTime().toString();
64
+
65
+ for (const key in payload) {
66
+ if (Object.prototype.hasOwnProperty.call(payload, key)) {
67
+ stringifiedPayload[key] = String(payload[key]);
68
+ }
69
+ }
70
+ return stringifiedPayload;
71
+ }
72
+
73
+ function createEmitCallback(
74
+ networkConfig: NetworkConfiguration
75
+ ): (e: Payload) => void {
76
+ return (e: Payload) => {
77
+ const postJson = {
78
+ schema: schemas.payloadData,
79
+ data: [preparePayload(e)],
80
+ };
81
+ const endpoint = networkConfig.endpoint;
82
+ const postPath =
83
+ networkConfig.customPostPath ?? '/com.snowplowanalytics.snowplow/tp2';
84
+ const headers = networkConfig.requestHeaders ?? {};
85
+ fetch(endpoint + postPath, {
86
+ method: 'POST',
87
+ body: JSON.stringify(postJson),
88
+ headers: {
89
+ 'Content-Type': 'application/json',
90
+ ...headers,
91
+ },
92
+ }).catch(errorHandler);
93
+ };
94
+ }
95
+
96
+ function updateTrackerProperties(
97
+ tracker: Tracker,
98
+ configuration: InitTrackerConfiguration
99
+ ): void {
100
+ tracker.setPlatform(configuration.trackerConfig?.devicePlatform ?? 'mob');
101
+ tracker.setTrackerVersion(trackerVersion);
102
+ tracker.setTrackerNamespace(configuration.namespace);
103
+ if (configuration.trackerConfig?.appId != null) {
104
+ tracker.setAppId(configuration.trackerConfig.appId);
105
+ }
106
+ if (configuration.subjectConfig?.colorDepth != null) {
107
+ tracker.setColorDepth(String(configuration.subjectConfig.colorDepth));
108
+ }
109
+ if (configuration.subjectConfig?.domainUserId != null) {
110
+ tracker.setDomainUserId(configuration.subjectConfig.domainUserId);
111
+ }
112
+ if (configuration.subjectConfig?.ipAddress != null) {
113
+ tracker.setIpAddress(configuration.subjectConfig.ipAddress);
114
+ }
115
+ if (configuration.subjectConfig?.language != null) {
116
+ tracker.setLang(configuration.subjectConfig.language);
117
+ }
118
+ if (configuration.subjectConfig?.screenResolution != null) {
119
+ tracker.setScreenResolution(
120
+ String(configuration.subjectConfig.screenResolution[0]),
121
+ String(configuration.subjectConfig.screenResolution[1])
122
+ );
123
+ }
124
+ if (configuration.subjectConfig?.screenViewport != null) {
125
+ tracker.setViewport(
126
+ String(configuration.subjectConfig.screenViewport[0]),
127
+ String(configuration.subjectConfig.screenViewport[1])
128
+ );
129
+ }
130
+ if (configuration.subjectConfig?.timezone != null) {
131
+ tracker.setTimezone(configuration.subjectConfig.timezone);
132
+ }
133
+ if (configuration.subjectConfig?.userId != null) {
134
+ tracker.setUserId(configuration.subjectConfig.userId);
135
+ }
136
+ if (configuration.subjectConfig?.useragent != null) {
137
+ tracker.setUseragent(configuration.subjectConfig.useragent);
138
+ }
139
+ }
140
+
141
+ function createTracker(
142
+ configuration: InitTrackerConfiguration,
143
+ emitCallback?: (e: Payload) => void
144
+ ): Promise<void> {
145
+ // create an emit callback if not given
146
+ const emitter =
147
+ emitCallback ?? createEmitCallback(configuration.networkConfig);
148
+
149
+ // the tracker core does not provide an option to set the duid, so we need to add custom
150
+ let domainUserId: string | undefined;
151
+ const setDomainUserId = (userId: string | undefined): void => {
152
+ domainUserId = userId;
153
+ };
154
+ let networkUserId: string | undefined;
155
+ const setNetworkUserId = (userId: string | undefined): void => {
156
+ networkUserId = userId;
157
+ };
158
+
159
+ // initialize the tracker core
160
+ const core = trackerCore({
161
+ base64: configuration.trackerConfig?.base64Encoding ?? true,
162
+ callback: (payload: PayloadBuilder) => {
163
+ if (domainUserId != null) {
164
+ payload.add('duid', domainUserId);
165
+ }
166
+ if (networkUserId != null) {
167
+ payload.add('tnuid', networkUserId);
168
+ }
169
+ const builtPayload = payload.build();
170
+ emitter(builtPayload);
171
+ },
172
+ });
173
+ const tracker = { ...core, setDomainUserId, setNetworkUserId };
174
+ trackers[configuration.namespace] = tracker;
175
+
176
+ // update tracker properties to reflect subject and tracker info
177
+ updateTrackerProperties(tracker, configuration);
178
+
179
+ return <Promise<void>>Promise.resolve();
180
+ }
181
+
182
+ function removeTracker(details: { tracker: string }): Promise<boolean> {
183
+ delete trackers[details.tracker];
184
+ return <Promise<boolean>>Promise.resolve(true);
185
+ }
186
+
187
+ function removeAllTrackers(): Promise<boolean> {
188
+ trackers = {};
189
+ return <Promise<boolean>>Promise.resolve(true);
190
+ }
191
+
192
+ function forTracker(
193
+ namespace: string | null,
194
+ callback: (tracker: Tracker) => void
195
+ ): void {
196
+ const tracker =
197
+ namespace != null ? trackers[namespace] : Object.values(trackers)[0];
198
+
199
+ if (tracker) {
200
+ callback(tracker);
201
+ } else {
202
+ errorHandler(new Error('No such tracker found.'));
203
+ }
204
+ }
205
+
206
+ function trackSelfDescribingEvent(details: {
207
+ tracker: string | null;
208
+ eventData: SelfDescribing;
209
+ contexts: EventContext[];
210
+ }): Promise<void> {
211
+ forTracker(details.tracker, (tracker) => {
212
+ tracker.track(
213
+ buildSelfDescribingEvent({
214
+ event: details.eventData,
215
+ }),
216
+ details.contexts
217
+ );
218
+ });
219
+ return <Promise<void>>Promise.resolve();
220
+ }
221
+
222
+ function trackStructuredEvent(details: {
223
+ tracker: string | null;
224
+ eventData: StructuredProps;
225
+ contexts: EventContext[];
226
+ }): Promise<void> {
227
+ forTracker(details.tracker, (tracker) => {
228
+ tracker.track(buildStructEvent(details.eventData), details.contexts);
229
+ });
230
+ return <Promise<void>>Promise.resolve();
231
+ }
232
+
233
+ function trackScreenViewEvent(details: {
234
+ tracker: string | null;
235
+ eventData: ScreenViewProps;
236
+ contexts: EventContext[];
237
+ }): Promise<void> {
238
+ const data: ScreenViewProps = {
239
+ name: details.eventData.name,
240
+ id: details.eventData.id ?? uuid(),
241
+ };
242
+ if (details.eventData.type != null) {
243
+ data.type = details.eventData.type;
244
+ }
245
+ if (details.eventData.previousName != null) {
246
+ data.previousName = details.eventData.previousName;
247
+ }
248
+ if (details.eventData.previousId != null) {
249
+ data.previousId = details.eventData.previousId;
250
+ }
251
+ if (details.eventData.previousType != null) {
252
+ data.previousType = details.eventData.previousType;
253
+ }
254
+ if (details.eventData.transitionType != null) {
255
+ data.transitionType = details.eventData.transitionType;
256
+ }
257
+
258
+ return trackSelfDescribingEvent({
259
+ tracker: details.tracker,
260
+ eventData: {
261
+ schema: schemas.screenViewSchema,
262
+ data: data,
263
+ },
264
+ contexts: details.contexts,
265
+ });
266
+ }
267
+
268
+ function trackPageViewEvent(details: {
269
+ tracker: string | null;
270
+ eventData: PageViewProps;
271
+ contexts: EventContext[];
272
+ }): Promise<void> {
273
+ forTracker(details.tracker, (tracker) => {
274
+ tracker.track(buildPageView(details.eventData), details.contexts);
275
+ });
276
+ return <Promise<void>>Promise.resolve();
277
+ }
278
+
279
+ function trackTimingEvent(details: {
280
+ tracker: string | null;
281
+ eventData: TimingProps;
282
+ contexts: EventContext[];
283
+ }): Promise<void> {
284
+ return trackSelfDescribingEvent({
285
+ tracker: details.tracker,
286
+ eventData: {
287
+ schema: schemas.timingSchema,
288
+ data: details.eventData,
289
+ },
290
+ contexts: details.contexts,
291
+ });
292
+ }
293
+
294
+ function trackConsentGrantedEvent(details: {
295
+ tracker: string | null;
296
+ eventData: ConsentGrantedProps;
297
+ contexts: EventContext[];
298
+ }): Promise<void> {
299
+ forTracker(details.tracker, (tracker) => {
300
+ const built = buildConsentGranted({
301
+ id: details.eventData.documentId,
302
+ version: details.eventData.version,
303
+ name: details.eventData.name,
304
+ description: details.eventData.documentDescription,
305
+ expiry: details.eventData.expiry,
306
+ });
307
+ tracker.track(built.event, details.contexts.concat(built.context));
308
+ });
309
+ return <Promise<void>>Promise.resolve();
310
+ }
311
+
312
+ function trackConsentWithdrawnEvent(details: {
313
+ tracker: string | null;
314
+ eventData: ConsentWithdrawnProps;
315
+ contexts: EventContext[];
316
+ }): Promise<void> {
317
+ forTracker(details.tracker, (tracker) => {
318
+ const built = buildConsentWithdrawn({
319
+ all: details.eventData.all,
320
+ id: details.eventData.documentId,
321
+ version: details.eventData.version,
322
+ name: details.eventData.name,
323
+ description: details.eventData.documentDescription,
324
+ });
325
+ tracker.track(built.event, details.contexts.concat(built.context));
326
+ });
327
+ return <Promise<void>>Promise.resolve();
328
+ }
329
+
330
+ function trackEcommerceTransactionEvent(details: {
331
+ tracker: string | null;
332
+ eventData: EcommerceTransactionProps;
333
+ contexts: EventContext[];
334
+ }): Promise<void> {
335
+ forTracker(details.tracker, (tracker) => {
336
+ details.eventData.items.forEach((item) => {
337
+ tracker.track(
338
+ buildEcommerceTransactionItem({
339
+ ...item,
340
+ orderId: details.eventData.orderId,
341
+ }),
342
+ details.contexts
343
+ );
344
+ });
345
+ tracker.track(
346
+ buildEcommerceTransaction({
347
+ orderId: details.eventData.orderId,
348
+ total: details.eventData.totalValue,
349
+ affiliation: details.eventData.affiliation,
350
+ tax: details.eventData.taxValue,
351
+ shipping: details.eventData.shipping,
352
+ city: details.eventData.city,
353
+ state: details.eventData.state,
354
+ country: details.eventData.country,
355
+ currency: details.eventData.currency,
356
+ }),
357
+ details.contexts
358
+ );
359
+ });
360
+ return <Promise<void>>Promise.resolve();
361
+ }
362
+
363
+ function trackDeepLinkReceivedEvent(details: {
364
+ tracker: string | null;
365
+ eventData: DeepLinkReceivedProps;
366
+ contexts: EventContext[];
367
+ }): Promise<void> {
368
+ return trackSelfDescribingEvent({
369
+ tracker: details.tracker,
370
+ eventData: {
371
+ schema: schemas.deepLinkReceivedSchema,
372
+ data: details.eventData,
373
+ },
374
+ contexts: details.contexts,
375
+ });
376
+ }
377
+
378
+ function trackMessageNotificationEvent(details: {
379
+ tracker: string | null;
380
+ eventData: MessageNotificationProps;
381
+ contexts: EventContext[];
382
+ }): Promise<void> {
383
+ return trackSelfDescribingEvent({
384
+ tracker: details.tracker,
385
+ eventData: {
386
+ schema: schemas.messageNotificationSchema,
387
+ data: details.eventData,
388
+ },
389
+ contexts: details.contexts,
390
+ });
391
+ }
392
+
393
+ function removeGlobalContexts(): Promise<void> {
394
+ return <Promise<void>>Promise.reject(new Error('Not implemented'));
395
+ }
396
+
397
+ function addGlobalContexts(): Promise<void> {
398
+ return <Promise<void>>Promise.reject(new Error('Not implemented'));
399
+ }
400
+
401
+ function setUserId(details: {
402
+ tracker: string;
403
+ userId: string | null;
404
+ }): Promise<void> {
405
+ trackers[details.tracker]?.setUserId(details.userId ?? '');
406
+ return <Promise<void>>Promise.resolve();
407
+ }
408
+
409
+ function setNetworkUserId(details: {
410
+ tracker: string;
411
+ networkUserId: string | null;
412
+ }): Promise<void> {
413
+ trackers[details.tracker]?.setNetworkUserId(details.networkUserId ?? '');
414
+ return <Promise<void>>Promise.resolve();
415
+ }
416
+
417
+ function setDomainUserId(details: {
418
+ tracker: string;
419
+ domainUserId: string | null;
420
+ }): Promise<void> {
421
+ trackers[details.tracker]?.setDomainUserId(details.domainUserId ?? '');
422
+ return <Promise<void>>Promise.resolve();
423
+ }
424
+
425
+ function setIpAddress(details: {
426
+ tracker: string;
427
+ ipAddress: string | null;
428
+ }): Promise<void> {
429
+ trackers[details.tracker]?.setIpAddress(details.ipAddress ?? '');
430
+ return <Promise<void>>Promise.resolve();
431
+ }
432
+
433
+ function setUseragent(details: {
434
+ tracker: string;
435
+ useragent: string | null;
436
+ }): Promise<void> {
437
+ trackers[details.tracker]?.setUseragent(details.useragent ?? '');
438
+ return <Promise<void>>Promise.resolve();
439
+ }
440
+
441
+ function setTimezone(details: {
442
+ tracker: string;
443
+ timezone: string | null;
444
+ }): Promise<void> {
445
+ trackers[details.tracker]?.setTimezone(details.timezone ?? '');
446
+ return <Promise<void>>Promise.resolve();
447
+ }
448
+
449
+ function setLanguage(details: {
450
+ tracker: string;
451
+ language: string | null;
452
+ }): Promise<void> {
453
+ trackers[details.tracker]?.setLang(details.language ?? '');
454
+ return <Promise<void>>Promise.resolve();
455
+ }
456
+
457
+ function setScreenResolution(details: {
458
+ tracker: string;
459
+ screenResolution: ScreenSize | null;
460
+ }): Promise<void> {
461
+ if (details.screenResolution) {
462
+ trackers[details.tracker]?.setScreenResolution(
463
+ String(details.screenResolution[0]),
464
+ String(details.screenResolution[1])
465
+ );
466
+ } else {
467
+ trackers[details.tracker]?.addPayloadPair('res', '');
468
+ }
469
+ return <Promise<void>>Promise.resolve();
470
+ }
471
+
472
+ function setScreenViewport(details: {
473
+ tracker: string;
474
+ screenViewport: ScreenSize | null;
475
+ }): Promise<void> {
476
+ if (details.screenViewport) {
477
+ trackers[details.tracker]?.setViewport(
478
+ String(details.screenViewport[0]),
479
+ String(details.screenViewport[1])
480
+ );
481
+ } else {
482
+ trackers[details.tracker]?.addPayloadPair('vp', '');
483
+ }
484
+ return <Promise<void>>Promise.resolve();
485
+ }
486
+
487
+ function setColorDepth(details: {
488
+ tracker: string;
489
+ colorDepth: number | null;
490
+ }): Promise<void> {
491
+ trackers[details.tracker]?.setColorDepth(String(details.colorDepth ?? ''));
492
+ return <Promise<void>>Promise.resolve();
493
+ }
494
+
495
+ function getSessionUserId(): Promise<string> {
496
+ return <Promise<string>>Promise.reject(new Error('Not implemented'));
497
+ }
498
+
499
+ function getSessionId(): Promise<string> {
500
+ return <Promise<string>>Promise.reject(new Error('Not implemented'));
501
+ }
502
+
503
+ function getSessionIndex(): Promise<number> {
504
+ return <Promise<number>>Promise.reject(new Error('Not implemented'));
505
+ }
506
+
507
+ function getIsInBackground(): Promise<boolean> {
508
+ return <Promise<boolean>>Promise.reject(new Error('Not implemented'));
509
+ }
510
+
511
+ function getBackgroundIndex(): Promise<number> {
512
+ return <Promise<number>>Promise.reject(new Error('Not implemented'));
513
+ }
514
+
515
+ function getForegroundIndex(): Promise<number> {
516
+ return <Promise<number>>Promise.reject(new Error('Not implemented'));
517
+ }
518
+
519
+ const JSSnowplowTracker = Object.freeze({
520
+ createTracker,
521
+ removeTracker,
522
+ removeAllTrackers,
523
+ trackSelfDescribingEvent,
524
+ trackStructuredEvent,
525
+ trackScreenViewEvent,
526
+ trackPageViewEvent,
527
+ trackTimingEvent,
528
+ trackConsentGrantedEvent,
529
+ trackConsentWithdrawnEvent,
530
+ trackEcommerceTransactionEvent,
531
+ trackDeepLinkReceivedEvent,
532
+ trackMessageNotificationEvent,
533
+ removeGlobalContexts,
534
+ addGlobalContexts,
535
+ setUserId,
536
+ setNetworkUserId,
537
+ setDomainUserId,
538
+ setIpAddress,
539
+ setUseragent,
540
+ setTimezone,
541
+ setLanguage,
542
+ setScreenResolution,
543
+ setScreenViewport,
544
+ setColorDepth,
545
+ getSessionUserId,
546
+ getSessionId,
547
+ getSessionIndex,
548
+ getIsInBackground,
549
+ getBackgroundIndex,
550
+ getForegroundIndex,
551
+ });
552
+
553
+ export { JSSnowplowTracker };
package/src/native.ts ADDED
@@ -0,0 +1,34 @@
1
+ /*
2
+ * Copyright (c) 2020-2023 Snowplow Analytics Ltd. All rights reserved.
3
+ *
4
+ * This program is licensed to you under the Apache License Version 2.0,
5
+ * and you may not use this file except in compliance with the Apache License Version 2.0.
6
+ * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
7
+ *
8
+ * Unless required by applicable law or agreed to in writing,
9
+ * software distributed under the Apache License Version 2.0 is distributed on an
10
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
12
+ */
13
+
14
+ 'use strict';
15
+
16
+ import { NativeModules } from 'react-native';
17
+ import { JSSnowplowTracker } from './jsCore';
18
+ import type { Native } from './types';
19
+ import { errorHandler } from './utils';
20
+
21
+ const isAvailable = NativeModules.ReactNativeTracker != null;
22
+ if (!isAvailable) {
23
+ errorHandler(
24
+ new Error(
25
+ 'Unable to access the native iOS/Android Snowplow tracker, a tracker implementation with very limited functionality is used.'
26
+ )
27
+ );
28
+ }
29
+
30
+ const RNSnowplowTracker: Native = isAvailable
31
+ ? (NativeModules.ReactNativeTracker as Native)
32
+ : JSSnowplowTracker;
33
+
34
+ export { RNSnowplowTracker };