@convivainc/conviva-react-native-appanalytics 0.2.10000 → 0.3.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 +28 -0
- package/README.md +25 -7
- package/RNConvivaAppAnalytics.podspec +1 -1
- package/android/build.gradle +2 -1
- package/android/gradle.properties +2 -1
- package/android/src/main/java/com/conviva/react/apptracker/RNConvivaTrackerModule.java +133 -1
- package/android/src/main/java/com/conviva/react/apptracker/util/TrackerVersion.java +1 -1
- package/conviva-react-native-appanalytics.d.ts +53 -1
- package/conviva-react-native-appanalytics.js +81 -7
- package/instrumentation/index.js +4 -66
- package/ios/RNConvivaAppAnalytics.m +103 -1
- package/ios/Util/RNTrackerVersion.m +1 -1
- package/package.json +7 -1
- package/plugin.js +140 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
|
|
2
2
|
# Changelog
|
|
3
|
+
## 0.3.0 (14/Apr/2026)
|
|
4
|
+
- Babel plugin simplified to `@convivainc/conviva-react-native-appanalytics/plugin`; app-level `babel-types` and `babel-template` dependencies no longer needed.
|
|
5
|
+
- `add-react-displayname` plugin no longer needed; absorbed internally by the Conviva plugin.
|
|
6
|
+
- Using latest android(v1.3.1) and ios(v1.10.2) native packages.
|
|
7
|
+
|
|
8
|
+
## 0.2.8 (06/Apr/2025)
|
|
9
|
+
- Added trackRevenueEvent API to track purchase and revenue events.
|
|
10
|
+
- Using latest android(v1.3.1) and ios(v1.10.1) native packages.
|
|
11
|
+
|
|
12
|
+
## 0.2.7 (31/Dec/2025)
|
|
13
|
+
- Supports network request url query params tracking.
|
|
14
|
+
- Enhanced the remote configuration feature to support instant updates.
|
|
15
|
+
- Using latest android(v1.2.6) and ios(v1.8.0) native packages.
|
|
16
|
+
|
|
17
|
+
## 0.2.6 (16/Dec/2025)
|
|
18
|
+
- Improves App Load Time metric by collecting more data.
|
|
19
|
+
- Using latest android(v1.2.6) and ios(v1.7.0) native packages.
|
|
20
|
+
|
|
21
|
+
## 0.2.5 (25/Nov/2025)
|
|
22
|
+
- Improved crash reporting and ANRs to deliver deeper insights and faster fixes for a more stable app experience. Applicable for:
|
|
23
|
+
- Android 11 (API 30) and above
|
|
24
|
+
- iOS 14 and above
|
|
25
|
+
|
|
26
|
+
## 0.2.4 (16/Oct/2025)
|
|
27
|
+
- Using latest android(v1.2.3) and ios(v1.5.0) native packages.
|
|
28
|
+
|
|
29
|
+
## 0.2.3 (23/Sep/2025)
|
|
30
|
+
- Resolved an issue where certain network requests on Apple mobile platforms were not being captured by the DPI module.
|
|
3
31
|
|
|
4
32
|
## 0.2.2 (27/Mar/2025)
|
|
5
33
|
- Exposing getClientId and setClientId methods for ts.
|
package/README.md
CHANGED
|
@@ -76,22 +76,40 @@ tracker.trackPageView(pageViewEvent);
|
|
|
76
76
|
```
|
|
77
77
|
|
|
78
78
|
## Auto detect button clicks.
|
|
79
|
-
Even though the React Native components can be natively mapped in Android and iOS, for the Auto detection of button clicks for **Button**, **TouchableHighlight**, **TouchableOpacity**, **TouchableWithoutFeedback** and **TouchableNativeFeedback** Components, needs explicit addition of babel
|
|
79
|
+
Even though the React Native components can be natively mapped in Android and iOS, for the Auto detection of button clicks for **Button**, **TouchableHighlight**, **TouchableOpacity**, **TouchableWithoutFeedback** and **TouchableNativeFeedback** Components, needs explicit addition of babel transformation. Add below plugin code in your application `.babelrc` or `babel.config.js` file:
|
|
80
80
|
|
|
81
|
+
**>= 0.3.0** - no extra dependencies needed in the app:
|
|
81
82
|
```js
|
|
82
83
|
|
|
83
|
-
"plugins": ["
|
|
84
|
+
"plugins": ["@convivainc/conviva-react-native-appanalytics/plugin"]
|
|
84
85
|
|
|
85
86
|
```
|
|
86
87
|
|
|
87
|
-
|
|
88
|
-
To support Conviva to Auto Detect the Screen Name part of the ScreenView Events, add below plugin code in your application .babel.rc or babel.config.js file:
|
|
88
|
+
**<= 0.2.8** - also required `babel-types` and `babel-template` as explicit app-level dependencies:
|
|
89
89
|
```js
|
|
90
90
|
|
|
91
|
+
"plugins": ["./node_modules/@convivainc/conviva-react-native-appanalytics/instrumentation/index.js"]
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
```json
|
|
95
|
+
|
|
96
|
+
"babel-types": "...",
|
|
97
|
+
"babel-template": "..."
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## `displayName` auto-detection
|
|
102
|
+
**<= 0.2.8** - required as a separate entry in `.babelrc` / `babel.config.js`:
|
|
103
|
+
```js
|
|
91
104
|
"plugins": ["add-react-displayname"]
|
|
105
|
+
```
|
|
92
106
|
|
|
107
|
+
**>= 0.3.0** - no separate entry needed. `displayName` auto-detection is absorbed internally by the Conviva plugin:
|
|
108
|
+
```js
|
|
109
|
+
"plugins": ["@convivainc/conviva-react-native-appanalytics/plugin"]
|
|
93
110
|
```
|
|
94
111
|
|
|
112
|
+
## Auto detect ScreenView Events for tracking screen navigation.
|
|
95
113
|
For React Navigation versions 5 and above, to autocapture screenviews, wrap withReactNavigationAutotrack(autocaptureNavigationTrack) around the NavigationContainer:
|
|
96
114
|
|
|
97
115
|
```js
|
|
@@ -114,7 +132,7 @@ withReactNavigationAutotrack(autocaptureNavigationTrack)(NavigationContainer);
|
|
|
114
132
|
</ConvivaNavigationContainer>
|
|
115
133
|
```
|
|
116
134
|
|
|
117
|
-
For React Navigation versions below 5, wrap the AppContainer (the result of a call to React Navigation
|
|
135
|
+
For React Navigation versions below 5, wrap the AppContainer (the result of a call to React Navigation's createAppContainer() method) with withReactNavigationAutotrack(autocaptureNavigationTrack)
|
|
118
136
|
```js
|
|
119
137
|
|
|
120
138
|
let AppNavigator = createStackNavigator(
|
|
@@ -189,9 +207,9 @@ tracker.clearAllCustomTags();
|
|
|
189
207
|
Event | Occurrence |
|
|
190
208
|
------|------------ |
|
|
191
209
|
network_request | after receiving the network request response ; auto collected from the Native Sensors, Need android-plugin inclusion for Android|
|
|
192
|
-
screen_view | when the screen is interacted on either first launch or relaunch ; auto collected from the Native Sensors + React Native Screens; Need
|
|
210
|
+
screen_view | when the screen is interacted on either first launch or relaunch ; auto collected from the Native Sensors + React Native Screens; Need Conviva `plugin.js` (includes `displayName` injection) and wrapping of Navigation Components |
|
|
193
211
|
application_error | when an error occurrs in the application ; auto collected from the Native Sensors|
|
|
194
|
-
button_click | on the button click callback ; auto collected from the Native Sensors + React Native **Button**, **TouchableHighlight**, **TouchableOpacity**, **TouchableWithoutFeedback** and **TouchableNativeFeedback** Components; Need Conviva
|
|
212
|
+
button_click | on the button click callback ; auto collected from the Native Sensors + React Native **Button**, **TouchableHighlight**, **TouchableOpacity**, **TouchableWithoutFeedback** and **TouchableNativeFeedback** Components; Need Conviva `plugin.js` from the node_modules folder|
|
|
195
213
|
application_background | when the application is taken to the background ; auto collected from the Native Sensors|
|
|
196
214
|
application_foreground | when the application is taken to the foreground ; auto collected from the Native Sensors|
|
|
197
215
|
application_install | when the application is launched for the first time after it's installed. (It's not the exact installed time.) |
|
package/android/build.gradle
CHANGED
|
@@ -16,6 +16,7 @@ buildscript {
|
|
|
16
16
|
apply plugin: "com.android.library"
|
|
17
17
|
|
|
18
18
|
android {
|
|
19
|
+
namespace "com.conviva.react.apptracker"
|
|
19
20
|
compileSdkVersion safeExtGet('compileSdkVersion', 33)
|
|
20
21
|
buildToolsVersion safeExtGet('buildToolsVersion', '30.0.2')
|
|
21
22
|
|
|
@@ -51,5 +52,5 @@ dependencies {
|
|
|
51
52
|
implementation "com.squareup.okhttp3:okhttp:4.9.3"
|
|
52
53
|
implementation "com.facebook.react:react-native:+"
|
|
53
54
|
implementation 'com.googlecode.json-simple:json-simple:1.1'
|
|
54
|
-
implementation 'com.conviva.sdk:conviva-android-tracker:1.
|
|
55
|
+
implementation 'com.conviva.sdk:conviva-android-tracker:1.3.1'
|
|
55
56
|
}
|
|
@@ -13,6 +13,8 @@ import com.conviva.apptracker.configuration.TrackerConfiguration;
|
|
|
13
13
|
import com.conviva.apptracker.controller.TrackerController;
|
|
14
14
|
import com.conviva.apptracker.event.ButtonClick;
|
|
15
15
|
import com.conviva.apptracker.event.ConsentGranted;
|
|
16
|
+
import com.conviva.apptracker.revenue.ConvivaRevenueEvent;
|
|
17
|
+
import com.conviva.apptracker.revenue.ConvivaRevenueEventItem;
|
|
16
18
|
import com.conviva.apptracker.event.ConsentWithdrawn;
|
|
17
19
|
import com.conviva.apptracker.event.DeepLinkReceived;
|
|
18
20
|
import com.conviva.apptracker.event.EcommerceTransaction;
|
|
@@ -37,6 +39,7 @@ import com.facebook.react.bridge.ReadableArray;
|
|
|
37
39
|
import com.facebook.react.bridge.ReadableMap;
|
|
38
40
|
import com.facebook.react.bridge.ReadableMapKeySetIterator;
|
|
39
41
|
|
|
42
|
+
import org.json.JSONObject;
|
|
40
43
|
import org.json.simple.JSONValue;
|
|
41
44
|
|
|
42
45
|
import java.util.ArrayList;
|
|
@@ -48,13 +51,40 @@ import java.util.concurrent.TimeUnit;
|
|
|
48
51
|
import okhttp3.OkHttpClient;
|
|
49
52
|
import okhttp3.Request;
|
|
50
53
|
|
|
54
|
+
import com.facebook.react.bridge.ReactMarker;
|
|
55
|
+
import com.facebook.react.bridge.ReactMarker.MarkerListener;
|
|
56
|
+
import com.facebook.react.bridge.ReactMarkerConstants;
|
|
57
|
+
|
|
58
|
+
|
|
51
59
|
public class RNConvivaTrackerModule extends ReactContextBaseJavaModule {
|
|
52
60
|
|
|
53
61
|
private final ReactApplicationContext reactContext;
|
|
54
62
|
|
|
63
|
+
public static volatile long contentAppearedTimestamp;
|
|
64
|
+
|
|
65
|
+
|
|
55
66
|
public RNConvivaTrackerModule(ReactApplicationContext reactContext) {
|
|
56
67
|
super(reactContext);
|
|
57
68
|
this.reactContext = reactContext;
|
|
69
|
+
|
|
70
|
+
addContentAppearedMarkerListener();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
private void addContentAppearedMarkerListener() {
|
|
74
|
+
if (contentAppearedTimestamp <= 0) {
|
|
75
|
+
ReactMarker.addListener(new MarkerListener() {
|
|
76
|
+
@Override
|
|
77
|
+
public void logMarker(ReactMarkerConstants name, String tag, int instanceKey) {
|
|
78
|
+
if (name == ReactMarkerConstants.CONTENT_APPEARED && contentAppearedTimestamp <= 0) {
|
|
79
|
+
contentAppearedTimestamp = System.currentTimeMillis();
|
|
80
|
+
TrackerController tracker = ConvivaAppAnalytics.getDefaultTracker();
|
|
81
|
+
if (tracker != null) {
|
|
82
|
+
tracker.setContentAppearedTimestamp(contentAppearedTimestamp);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
}
|
|
58
88
|
}
|
|
59
89
|
|
|
60
90
|
@Override
|
|
@@ -163,7 +193,12 @@ public class RNConvivaTrackerModule extends ReactContextBaseJavaModule {
|
|
|
163
193
|
}
|
|
164
194
|
|
|
165
195
|
// create the tracker
|
|
166
|
-
ConvivaAppAnalytics.createTracker(this.reactContext, customerKey, appName, controllers.toArray(new Configuration[controllers.size()]));
|
|
196
|
+
TrackerController trackerController = ConvivaAppAnalytics.createTracker(this.reactContext, customerKey, appName, controllers.toArray(new Configuration[controllers.size()]));
|
|
197
|
+
|
|
198
|
+
//Set the contentAppearedTimestamp if already captured
|
|
199
|
+
if(trackerController != null && contentAppearedTimestamp > 0) {
|
|
200
|
+
trackerController.setContentAppearedTimestamp(contentAppearedTimestamp);
|
|
201
|
+
}
|
|
167
202
|
|
|
168
203
|
promise.resolve(true);
|
|
169
204
|
|
|
@@ -188,6 +223,16 @@ public class RNConvivaTrackerModule extends ReactContextBaseJavaModule {
|
|
|
188
223
|
}
|
|
189
224
|
}
|
|
190
225
|
|
|
226
|
+
@ReactMethod
|
|
227
|
+
public void cleanup(Promise promise) {
|
|
228
|
+
try {
|
|
229
|
+
// commented out deprecated methods
|
|
230
|
+
promise.resolve(true);
|
|
231
|
+
|
|
232
|
+
} catch (Throwable t) {
|
|
233
|
+
promise.reject("ERROR", t.getMessage());
|
|
234
|
+
}
|
|
235
|
+
}
|
|
191
236
|
@ReactMethod
|
|
192
237
|
public void removeAllTrackers(Promise promise) {
|
|
193
238
|
try {
|
|
@@ -501,6 +546,78 @@ public class RNConvivaTrackerModule extends ReactContextBaseJavaModule {
|
|
|
501
546
|
}
|
|
502
547
|
}
|
|
503
548
|
|
|
549
|
+
@ReactMethod
|
|
550
|
+
public void trackRevenueEvent(ReadableMap details, Promise promise) {
|
|
551
|
+
try {
|
|
552
|
+
String namespace = details.getString("tracker");
|
|
553
|
+
TrackerController trackerController = getTracker(namespace);
|
|
554
|
+
if (trackerController != null) {
|
|
555
|
+
ReadableMap argmap = details.getMap("eventData");
|
|
556
|
+
|
|
557
|
+
double totalOrderAmount = argmap.getDouble("totalOrderAmount");
|
|
558
|
+
String transactionId = argmap.getString("transactionId");
|
|
559
|
+
String currency = argmap.getString("currency");
|
|
560
|
+
|
|
561
|
+
ConvivaRevenueEvent.Builder builder =
|
|
562
|
+
ConvivaRevenueEvent.builder(totalOrderAmount, transactionId, currency);
|
|
563
|
+
|
|
564
|
+
if (argmap.hasKey("taxAmount") && !argmap.isNull("taxAmount"))
|
|
565
|
+
builder.taxAmount(argmap.getDouble("taxAmount"));
|
|
566
|
+
if (argmap.hasKey("shippingCost") && !argmap.isNull("shippingCost"))
|
|
567
|
+
builder.shippingCost(argmap.getDouble("shippingCost"));
|
|
568
|
+
if (argmap.hasKey("discount") && !argmap.isNull("discount"))
|
|
569
|
+
builder.discount(argmap.getDouble("discount"));
|
|
570
|
+
if (argmap.hasKey("cartSize") && !argmap.isNull("cartSize"))
|
|
571
|
+
builder.cartSize(argmap.getInt("cartSize"));
|
|
572
|
+
if (argmap.hasKey("paymentMethod") && !argmap.isNull("paymentMethod"))
|
|
573
|
+
builder.paymentMethod(argmap.getString("paymentMethod"));
|
|
574
|
+
if (argmap.hasKey("paymentProvider") && !argmap.isNull("paymentProvider"))
|
|
575
|
+
builder.paymentProvider(argmap.getString("paymentProvider"));
|
|
576
|
+
if (argmap.hasKey("extraMetadata") && !argmap.isNull("extraMetadata"))
|
|
577
|
+
builder.extraMetadata(new JSONObject(argmap.getMap("extraMetadata").toHashMap()));
|
|
578
|
+
|
|
579
|
+
if (argmap.hasKey("items") && !argmap.isNull("items")) {
|
|
580
|
+
ReadableArray itemsArray = argmap.getArray("items");
|
|
581
|
+
List<ConvivaRevenueEventItem> items = new ArrayList<>();
|
|
582
|
+
for (int i = 0; i < itemsArray.size(); i++) {
|
|
583
|
+
ReadableMap itemDict = itemsArray.getMap(i);
|
|
584
|
+
ConvivaRevenueEventItem.Builder itemBuilder = ConvivaRevenueEventItem.builder();
|
|
585
|
+
if (itemDict.hasKey("productId") && !itemDict.isNull("productId"))
|
|
586
|
+
itemBuilder.productId(itemDict.getString("productId"));
|
|
587
|
+
if (itemDict.hasKey("name") && !itemDict.isNull("name"))
|
|
588
|
+
itemBuilder.name(itemDict.getString("name"));
|
|
589
|
+
if (itemDict.hasKey("sku") && !itemDict.isNull("sku"))
|
|
590
|
+
itemBuilder.sku(itemDict.getString("sku"));
|
|
591
|
+
if (itemDict.hasKey("category") && !itemDict.isNull("category"))
|
|
592
|
+
itemBuilder.category(EventUtil.createStrings(itemDict.getArray("category")));
|
|
593
|
+
if (itemDict.hasKey("unitPrice") && !itemDict.isNull("unitPrice"))
|
|
594
|
+
itemBuilder.unitPrice(itemDict.getDouble("unitPrice"));
|
|
595
|
+
if (itemDict.hasKey("quantity") && !itemDict.isNull("quantity"))
|
|
596
|
+
itemBuilder.quantity(itemDict.getInt("quantity"));
|
|
597
|
+
if (itemDict.hasKey("discount") && !itemDict.isNull("discount"))
|
|
598
|
+
itemBuilder.discount(itemDict.getDouble("discount"));
|
|
599
|
+
if (itemDict.hasKey("brand") && !itemDict.isNull("brand"))
|
|
600
|
+
itemBuilder.brand(itemDict.getString("brand"));
|
|
601
|
+
if (itemDict.hasKey("variant") && !itemDict.isNull("variant"))
|
|
602
|
+
itemBuilder.variant(itemDict.getString("variant"));
|
|
603
|
+
if (itemDict.hasKey("extraMetadata") && !itemDict.isNull("extraMetadata"))
|
|
604
|
+
itemBuilder.extraMetadata(new JSONObject(itemDict.getMap("extraMetadata").toHashMap()));
|
|
605
|
+
items.add(itemBuilder.build());
|
|
606
|
+
}
|
|
607
|
+
builder.items(items);
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
trackerController.trackRevenueEvent(builder.build());
|
|
611
|
+
promise.resolve(true);
|
|
612
|
+
} else {
|
|
613
|
+
promise.reject("ERROR", "TrackerController is null");
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
} catch (Throwable t) {
|
|
617
|
+
promise.reject("ERROR", t.getMessage());
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
|
|
504
621
|
@ReactMethod
|
|
505
622
|
public void setCustomTags(ReadableMap details, Promise promise) {
|
|
506
623
|
try {
|
|
@@ -947,6 +1064,21 @@ public class RNConvivaTrackerModule extends ReactContextBaseJavaModule {
|
|
|
947
1064
|
}
|
|
948
1065
|
}
|
|
949
1066
|
|
|
1067
|
+
@ReactMethod
|
|
1068
|
+
private void setContentAppearedTimestamp(ReadableMap argmap, Promise promise) {
|
|
1069
|
+
try {
|
|
1070
|
+
String namespace = argmap.getString("tracker");
|
|
1071
|
+
long contentAppearedTimestamp = (long) argmap.getDouble("contentAppearedTimestamp");
|
|
1072
|
+
TrackerController trackerController = getTracker(namespace);
|
|
1073
|
+
if (trackerController != null) {
|
|
1074
|
+
trackerController.setContentAppearedTimestamp(contentAppearedTimestamp);
|
|
1075
|
+
}
|
|
1076
|
+
promise.resolve(true);
|
|
1077
|
+
} catch (Throwable t) {
|
|
1078
|
+
promise.reject("ERROR", t.getMessage());
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
|
|
950
1082
|
private TrackerController getTracker(String namespace) {
|
|
951
1083
|
return namespace == null ? ConvivaAppAnalytics.getDefaultTracker() : ConvivaAppAnalytics.getTracker(namespace);
|
|
952
1084
|
}
|
|
@@ -71,6 +71,11 @@ interface NetworkConfiguration {
|
|
|
71
71
|
*/
|
|
72
72
|
requestHeaders?: Record<string, string>;
|
|
73
73
|
}
|
|
74
|
+
interface TraceparentConfiguration {
|
|
75
|
+
force: Boolean;
|
|
76
|
+
enabled: Boolean;
|
|
77
|
+
targetUrl: string[];
|
|
78
|
+
}
|
|
74
79
|
/**
|
|
75
80
|
* TrackerConfiguration
|
|
76
81
|
*/
|
|
@@ -304,6 +309,7 @@ interface RemoteConfiguration {
|
|
|
304
309
|
*/
|
|
305
310
|
interface TrackerControllerConfiguration {
|
|
306
311
|
networkConfig?: NetworkConfiguration;
|
|
312
|
+
traceparentConfig?: TraceparentConfiguration;
|
|
307
313
|
trackerConfig?: TrackerConfiguration;
|
|
308
314
|
sessionConfig?: SessionConfiguration;
|
|
309
315
|
emitterConfig?: EmitterConfiguration;
|
|
@@ -572,6 +578,39 @@ type MessageNotificationProps = {
|
|
|
572
578
|
*/
|
|
573
579
|
trigger: Trigger;
|
|
574
580
|
};
|
|
581
|
+
/**
|
|
582
|
+
* RevenueEventItem properties.
|
|
583
|
+
* All fields are optional.
|
|
584
|
+
*/
|
|
585
|
+
type RevenueEventItemProps = {
|
|
586
|
+
productId?: string;
|
|
587
|
+
name?: string;
|
|
588
|
+
sku?: string;
|
|
589
|
+
category?: string[];
|
|
590
|
+
unitPrice?: number;
|
|
591
|
+
quantity?: number;
|
|
592
|
+
discount?: number;
|
|
593
|
+
brand?: string;
|
|
594
|
+
variant?: string;
|
|
595
|
+
extraMetadata?: Record<string, unknown>;
|
|
596
|
+
};
|
|
597
|
+
/**
|
|
598
|
+
* RevenueEvent properties.
|
|
599
|
+
* Required: totalOrderAmount, transactionId, currency.
|
|
600
|
+
*/
|
|
601
|
+
type RevenueEventProps = {
|
|
602
|
+
totalOrderAmount: number;
|
|
603
|
+
transactionId: string;
|
|
604
|
+
currency: string;
|
|
605
|
+
taxAmount?: number;
|
|
606
|
+
shippingCost?: number;
|
|
607
|
+
discount?: number;
|
|
608
|
+
cartSize?: number;
|
|
609
|
+
paymentMethod?: string;
|
|
610
|
+
paymentProvider?: string;
|
|
611
|
+
items?: RevenueEventItemProps[];
|
|
612
|
+
extraMetadata?: Record<string, unknown>;
|
|
613
|
+
};
|
|
575
614
|
/**
|
|
576
615
|
* The ReactNativeTracker type
|
|
577
616
|
*/
|
|
@@ -656,6 +695,13 @@ type ReactNativeTracker = {
|
|
|
656
695
|
* @returns {Promise}
|
|
657
696
|
*/
|
|
658
697
|
readonly trackCustomEvent: (eventName: string, eventData: any, contexts?: EventContext[]) => Promise<void>;
|
|
698
|
+
/**
|
|
699
|
+
* Tracks a revenue event
|
|
700
|
+
*
|
|
701
|
+
* @param argmap - The revenue event properties
|
|
702
|
+
* @param contexts - The array of event contexts
|
|
703
|
+
*/
|
|
704
|
+
readonly trackRevenueEvent: (argmap: RevenueEventProps, contexts?: EventContext[]) => Promise<void>;
|
|
659
705
|
/**
|
|
660
706
|
* Sets custom tags
|
|
661
707
|
*
|
|
@@ -848,6 +894,12 @@ declare function removeTracker(trackerNamespace: string): Promise<boolean>;
|
|
|
848
894
|
* @returns - A boolean promise
|
|
849
895
|
*/
|
|
850
896
|
declare function removeAllTrackers(): Promise<boolean>;
|
|
897
|
+
/**
|
|
898
|
+
* Cleanup
|
|
899
|
+
*
|
|
900
|
+
* @returns - A boolean promise
|
|
901
|
+
*/
|
|
902
|
+
declare function cleanup(): Promise<boolean>;
|
|
851
903
|
/**
|
|
852
904
|
* Gets the cliend id
|
|
853
905
|
*
|
|
@@ -868,4 +920,4 @@ declare const _default: {
|
|
|
868
920
|
withReactNavigationAutotrack: (AppContainer: any) => react.ForwardRefExoticComponent<react.RefAttributes<any>>;
|
|
869
921
|
};
|
|
870
922
|
|
|
871
|
-
export { Basis, BufferOption, ConsentDocument, ConsentGrantedProps, ConsentWithdrawnProps, DeepLinkReceivedProps, DevicePlatform, EcommerceItem, EcommerceTransactionProps, EmitterConfiguration, EventContext, GCConfiguration, GdprConfiguration, GlobalContext, HttpMethod, LogLevel, MessageNotificationProps, NetworkConfiguration, PageViewProps, ReactNativeTracker, ScreenSize, ScreenViewProps, SelfDescribing, SessionConfiguration, StructuredProps, SubjectConfiguration, TimingProps, TrackerConfiguration, TrackerControllerConfiguration, Trigger, autocaptureNavigationTrack, createTracker, _default as default, getWebViewCallback, removeAllTrackers, removeTracker,
|
|
923
|
+
export { Basis, BufferOption, ConsentDocument, ConsentGrantedProps, ConsentWithdrawnProps, DeepLinkReceivedProps, DevicePlatform, EcommerceItem, EcommerceTransactionProps, EmitterConfiguration, EventContext, GCConfiguration, GdprConfiguration, GlobalContext, HttpMethod, LogLevel, MessageNotificationProps, NetworkConfiguration, PageViewProps, ReactNativeTracker, RevenueEventItemProps, RevenueEventProps, ScreenSize, ScreenViewProps, SelfDescribing, SessionConfiguration, StructuredProps, SubjectConfiguration, TimingProps, TrackerConfiguration, TrackerControllerConfiguration, Trigger, autocaptureNavigationTrack, cleanup, createTracker, _default as default, getClientId, getWebViewCallback, removeAllTrackers, removeTracker, setClientId, withReactNavigationAutotrack };
|
|
@@ -52,11 +52,11 @@ function safeWaitCallback(callPromise, errHandle) {
|
|
|
52
52
|
* Handles an error.
|
|
53
53
|
*
|
|
54
54
|
* @param err - The error to be handled.
|
|
55
|
+
* @param alwaysLog - When true, the error is logged regardless of the __DEV__ flag.
|
|
55
56
|
*/
|
|
56
|
-
function errorHandler(err) {
|
|
57
|
-
if (__DEV__) {
|
|
57
|
+
function errorHandler(err, alwaysLog = false) {
|
|
58
|
+
if (__DEV__ || alwaysLog) {
|
|
58
59
|
console.warn('ConvivaTracker:' + err.message);
|
|
59
|
-
return undefined;
|
|
60
60
|
}
|
|
61
61
|
return undefined;
|
|
62
62
|
}
|
|
@@ -128,6 +128,10 @@ const logMessages = {
|
|
|
128
128
|
deepLinkReq: 'deepLinkReceived event requires the url parameter to be set',
|
|
129
129
|
messageNotificationReq: 'messageNotification event requires title, body, and trigger parameters to be set',
|
|
130
130
|
trackCustomEvent: 'trackCustomEvent event requires name and data',
|
|
131
|
+
revenueEventNullEvent: 'event is null. Event not sent.',
|
|
132
|
+
revenueEventInvalidTotalOrderAmount: 'Must be a finite number. Event not sent.',
|
|
133
|
+
revenueEventInvalidTransactionId: 'Must be a non-empty string. Event not sent.',
|
|
134
|
+
revenueEventInvalidCurrency: 'Must be a non-empty string. Event not sent.',
|
|
131
135
|
trackClickEvent: 'click event requires atleast one attribute',
|
|
132
136
|
// custom tags contexts
|
|
133
137
|
setCustomTags: 'setCustomTags requires tags',
|
|
@@ -152,6 +156,7 @@ const logMessages = {
|
|
|
152
156
|
trackEcommerceTransaction: 'trackEcommerceTransaction:',
|
|
153
157
|
trackDeepLinkReceived: 'trackDeepLinkReceivedEvent:',
|
|
154
158
|
trackMessageNotification: 'trackMessageNotificationEvent:',
|
|
159
|
+
trackRevenueEvent: 'trackRevenueEvent:',
|
|
155
160
|
removeGlobalContexts: 'removeGlobalContexts:',
|
|
156
161
|
addGlobalContexts: 'addGlobalContexts:',
|
|
157
162
|
// setters
|
|
@@ -413,11 +418,26 @@ function validateEcommerceTransaction(argmap) {
|
|
|
413
418
|
return Promise.resolve(true);
|
|
414
419
|
}
|
|
415
420
|
/**
|
|
416
|
-
* Validates a
|
|
421
|
+
* Validates a revenue event
|
|
417
422
|
*
|
|
418
423
|
* @param argmap {Object} - the object to validate
|
|
419
424
|
* @returns - boolean promise
|
|
420
425
|
*/
|
|
426
|
+
function validateRevenueEvent(argmap) {
|
|
427
|
+
if (!isObject(argmap)) {
|
|
428
|
+
return Promise.reject(new Error(logMessages.revenueEventNullEvent));
|
|
429
|
+
}
|
|
430
|
+
if (typeof argmap.totalOrderAmount !== 'number' || !Number.isFinite(argmap.totalOrderAmount)) {
|
|
431
|
+
return Promise.reject(new Error(`invalid totalOrderAmount "${argmap.totalOrderAmount}". ${logMessages.revenueEventInvalidTotalOrderAmount}`));
|
|
432
|
+
}
|
|
433
|
+
if (typeof argmap.transactionId !== 'string' || argmap.transactionId.trim() === '') {
|
|
434
|
+
return Promise.reject(new Error(`invalid transactionId "${argmap.transactionId}". ${logMessages.revenueEventInvalidTransactionId}`));
|
|
435
|
+
}
|
|
436
|
+
if (typeof argmap.currency !== 'string' || argmap.currency.trim() === '') {
|
|
437
|
+
return Promise.reject(new Error(`invalid currency "${argmap.currency}". ${logMessages.revenueEventInvalidCurrency}`));
|
|
438
|
+
}
|
|
439
|
+
return Promise.resolve(true);
|
|
440
|
+
}
|
|
421
441
|
function validateCustomEvent(argmap) {
|
|
422
442
|
// validate type
|
|
423
443
|
if (!isObject(argmap)) {
|
|
@@ -954,6 +974,26 @@ function trackCustomEvent$1(namespace, name, arg, contexts = []) {
|
|
|
954
974
|
throw new Error(`${logMessages.trackCustomEvent} ${error.message}`);
|
|
955
975
|
});
|
|
956
976
|
}
|
|
977
|
+
/**
|
|
978
|
+
* Tracks a revenue event
|
|
979
|
+
*
|
|
980
|
+
* @param namespace {string} - the tracker namespace
|
|
981
|
+
* @param argmap {Object} - the event data
|
|
982
|
+
* @param contexts {Array}- the event contexts
|
|
983
|
+
* @returns {Promise}
|
|
984
|
+
*/
|
|
985
|
+
function trackRevenueEvent$1(namespace, argmap, contexts = []) {
|
|
986
|
+
return validateRevenueEvent(argmap)
|
|
987
|
+
.then(() => validateContexts(contexts))
|
|
988
|
+
.then(() => RNConvivaTracker.trackRevenueEvent({
|
|
989
|
+
tracker: namespace,
|
|
990
|
+
eventData: argmap,
|
|
991
|
+
contexts: contexts
|
|
992
|
+
}))
|
|
993
|
+
.catch((error) => {
|
|
994
|
+
throw new Error(`${logMessages.trackRevenueEvent} ${error.message}`);
|
|
995
|
+
});
|
|
996
|
+
}
|
|
957
997
|
/**
|
|
958
998
|
* Sets custom tags
|
|
959
999
|
*
|
|
@@ -1330,6 +1370,14 @@ function removeAllTrackers$1() {
|
|
|
1330
1370
|
}
|
|
1331
1371
|
return Promise.resolve(RNConvivaTracker.removeAllTrackers());
|
|
1332
1372
|
}
|
|
1373
|
+
/**
|
|
1374
|
+
* Cleanup
|
|
1375
|
+
*
|
|
1376
|
+
* @returns - A void promise
|
|
1377
|
+
*/
|
|
1378
|
+
function cleanup$1() {
|
|
1379
|
+
return Promise.resolve(RNConvivaTracker.cleanup());
|
|
1380
|
+
}
|
|
1333
1381
|
/**
|
|
1334
1382
|
* Get the client id which is in prescribed format.
|
|
1335
1383
|
*
|
|
@@ -1508,6 +1556,20 @@ function trackCustomEvent(namespace) {
|
|
|
1508
1556
|
return trackCustomEvent$1(namespace, eventName, eventData, contexts);
|
|
1509
1557
|
};
|
|
1510
1558
|
}
|
|
1559
|
+
/**
|
|
1560
|
+
* Returns a function to track a RevenueEvent by a tracker
|
|
1561
|
+
*
|
|
1562
|
+
* @param namespace {string} - The tracker namespace
|
|
1563
|
+
* @returns - A function to track a RevenueEvent
|
|
1564
|
+
*/
|
|
1565
|
+
function trackRevenueEvent(namespace) {
|
|
1566
|
+
return function (argmap, contexts = []) {
|
|
1567
|
+
if (!isTrackerInitialised) {
|
|
1568
|
+
return Promise.reject(new Error(logMessages.createTrackerNotSet));
|
|
1569
|
+
}
|
|
1570
|
+
return trackRevenueEvent$1(namespace, argmap, contexts);
|
|
1571
|
+
};
|
|
1572
|
+
}
|
|
1511
1573
|
function setCustomTags(namespace) {
|
|
1512
1574
|
return function (tags, contexts = []) {
|
|
1513
1575
|
if (!isTrackerInitialised) {
|
|
@@ -2015,7 +2077,7 @@ class NavigationUtil {
|
|
|
2015
2077
|
}
|
|
2016
2078
|
}
|
|
2017
2079
|
|
|
2018
|
-
const version = "0.
|
|
2080
|
+
const version = "0.3.0";
|
|
2019
2081
|
|
|
2020
2082
|
const { Platform } = require('react-native');
|
|
2021
2083
|
let reactNativeVersionString = null;
|
|
@@ -2174,6 +2236,8 @@ controllerConfig = {}) {
|
|
|
2174
2236
|
}));
|
|
2175
2237
|
// mkMethod creates methods subscribed to the initTrackerPromise
|
|
2176
2238
|
const mkMethod = safeWait(initTrackerPromise, errorHandler);
|
|
2239
|
+
// mkMethodAlwaysLog creates methods that always log errors, regardless of __DEV__
|
|
2240
|
+
const mkMethodAlwaysLog = safeWait(initTrackerPromise, (err) => errorHandler(err, true));
|
|
2177
2241
|
// mkCallback creates callbacks subscribed to the initTrackerPromise
|
|
2178
2242
|
const mkCallback = safeWaitCallback(initTrackerPromise, errorHandler);
|
|
2179
2243
|
// track methods
|
|
@@ -2189,6 +2253,7 @@ controllerConfig = {}) {
|
|
|
2189
2253
|
const trackDeepLinkReceivedEvent$1 = mkMethod(trackDeepLinkReceivedEvent(namespace));
|
|
2190
2254
|
const trackMessageNotificationEvent$1 = mkMethod(trackMessageNotificationEvent(namespace));
|
|
2191
2255
|
const trackCustomEvent$1 = mkMethod(trackCustomEvent(namespace));
|
|
2256
|
+
const trackRevenueEvent$1 = mkMethodAlwaysLog(trackRevenueEvent(namespace));
|
|
2192
2257
|
const trackClickEvent$1 = mkMethod(trackClickEvent(namespace));
|
|
2193
2258
|
// custom tags contexts
|
|
2194
2259
|
const setCustomTags$1 = mkMethod(setCustomTags(namespace));
|
|
@@ -2229,6 +2294,7 @@ controllerConfig = {}) {
|
|
|
2229
2294
|
trackDeepLinkReceivedEvent: trackDeepLinkReceivedEvent$1,
|
|
2230
2295
|
trackMessageNotificationEvent: trackMessageNotificationEvent$1,
|
|
2231
2296
|
trackCustomEvent: trackCustomEvent$1,
|
|
2297
|
+
trackRevenueEvent: trackRevenueEvent$1,
|
|
2232
2298
|
setCustomTags: setCustomTags$1,
|
|
2233
2299
|
setCustomTagsWithCategory: setCustomTagsWithCategory$1,
|
|
2234
2300
|
clearCustomTags: clearCustomTags$1,
|
|
@@ -2274,6 +2340,15 @@ function removeAllTrackers() {
|
|
|
2274
2340
|
return removeAllTrackers$1()
|
|
2275
2341
|
.catch((e) => errorHandler(e));
|
|
2276
2342
|
}
|
|
2343
|
+
/**
|
|
2344
|
+
* Cleanup
|
|
2345
|
+
*
|
|
2346
|
+
* @returns - A boolean promise
|
|
2347
|
+
*/
|
|
2348
|
+
function cleanup() {
|
|
2349
|
+
return cleanup$1()
|
|
2350
|
+
.catch((e) => errorHandler(e));
|
|
2351
|
+
}
|
|
2277
2352
|
/**
|
|
2278
2353
|
* Gets the cliend id
|
|
2279
2354
|
*
|
|
@@ -2298,7 +2373,6 @@ const autocaptureNavigationTrack = handleError((payload) => {
|
|
|
2298
2373
|
trackScreenViewEvent('CAT')(payload).catch((e) => errorHandler(e));
|
|
2299
2374
|
}, 'Event autocapture', true);
|
|
2300
2375
|
const autocaptureTrack = handleError((payload) => {
|
|
2301
|
-
checkDisplayNamePlugin();
|
|
2302
2376
|
trackClickEvent('CAT')(payload).catch((e) => errorHandler(e));
|
|
2303
2377
|
}, 'Event autocapture', true);
|
|
2304
2378
|
var index = {
|
|
@@ -2306,5 +2380,5 @@ var index = {
|
|
|
2306
2380
|
withReactNavigationAutotrack: withReactNavigationAutotrack(autocaptureNavigationTrack)
|
|
2307
2381
|
};
|
|
2308
2382
|
|
|
2309
|
-
export { autocaptureNavigationTrack, createTracker, index as default, getClientId, getWebViewCallback, removeAllTrackers, removeTracker, setClientId, withReactNavigationAutotrack };
|
|
2383
|
+
export { autocaptureNavigationTrack, cleanup, createTracker, index as default, getClientId, getWebViewCallback, removeAllTrackers, removeTracker, setClientId, withReactNavigationAutotrack };
|
|
2310
2384
|
//# sourceMappingURL=conviva-react-native-appanalytics.js.map
|
package/instrumentation/index.js
CHANGED
|
@@ -1,66 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
require('@convivainc/conviva-react-native-appanalytics').default || {
|
|
6
|
-
HIGHER_ORDER_COMP: (Component) => Component,
|
|
7
|
-
}
|
|
8
|
-
)`);
|
|
9
|
-
|
|
10
|
-
const createHigherOrderComponent = template(`
|
|
11
|
-
const COMPONENT_ID = HIGHER_ORDER_COMP_CALL_EXPRESSION;
|
|
12
|
-
`);
|
|
13
|
-
|
|
14
|
-
const ALLOWED_TOUCHABLE_COMPONENTS = [
|
|
15
|
-
'TouchableOpacity',
|
|
16
|
-
'TouchableNativeFeedback',
|
|
17
|
-
'TouchableWithoutFeedback',
|
|
18
|
-
'TouchableHighlight',
|
|
19
|
-
];
|
|
20
|
-
|
|
21
|
-
const replaceWithTouchableAutoTrackHigherOrderComponent = path => {
|
|
22
|
-
|
|
23
|
-
if (!ALLOWED_TOUCHABLE_COMPONENTS.includes(path.node.id.name)) {
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
// console.log("replaceWithTouchableAutoTrackHigherOrderComponent++");
|
|
27
|
-
|
|
28
|
-
const equivalentExpression = t.classExpression(
|
|
29
|
-
path.node.id,
|
|
30
|
-
path.node.superClass,
|
|
31
|
-
path.node.body,
|
|
32
|
-
path.node.decorators || []
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
const hocID = t.identifier('convivaTouchableAutoTrack');
|
|
36
|
-
|
|
37
|
-
const convivaImport = convivaLibImport({
|
|
38
|
-
HIGHER_ORDER_COMP: hocID,
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
const autotrackExpression = t.callExpression(
|
|
42
|
-
t.memberExpression(convivaImport.expression, hocID),
|
|
43
|
-
[equivalentExpression]
|
|
44
|
-
);
|
|
45
|
-
|
|
46
|
-
const replacement = createHigherOrderComponent({
|
|
47
|
-
COMPONENT_ID: path.node.id,
|
|
48
|
-
HIGHER_ORDER_COMP_CALL_EXPRESSION: autotrackExpression,
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
path.replaceWith(replacement);
|
|
52
|
-
|
|
53
|
-
// console.log("replaceWithTouchableAutoTrackHigherOrderComponent--");
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
function transform(babel) {
|
|
57
|
-
return {
|
|
58
|
-
visitor: {
|
|
59
|
-
ClassDeclaration(path) {
|
|
60
|
-
replaceWithTouchableAutoTrackHigherOrderComponent(path);
|
|
61
|
-
},
|
|
62
|
-
},
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
module.exports = transform;
|
|
1
|
+
'use strict';
|
|
2
|
+
// Backward-compatibility shim. The canonical implementation lives in plugin.js.
|
|
3
|
+
// Existing integrations that reference this path directly continue to work.
|
|
4
|
+
module.exports = require('../plugin.js');
|
|
@@ -45,6 +45,8 @@
|
|
|
45
45
|
#import <ConvivaAppAnalytics/CATEcommerce.h>
|
|
46
46
|
#import <ConvivaAppAnalytics/CATDeepLinkReceived.h>
|
|
47
47
|
#import <ConvivaAppAnalytics/CATMessageNotification.h>
|
|
48
|
+
#import <ConvivaAppAnalytics/CATRevenueEvent.h>
|
|
49
|
+
#import <ConvivaAppAnalytics/CATRevenueEventItem.h>
|
|
48
50
|
#import <Foundation/NSObject.h>
|
|
49
51
|
|
|
50
52
|
@implementation RNConvivaTracker
|
|
@@ -173,6 +175,11 @@ RCT_EXPORT_METHOD(removeAllTrackers: (RCTPromiseResolveBlock)resolve rejecter:(R
|
|
|
173
175
|
resolve(@YES);
|
|
174
176
|
}
|
|
175
177
|
|
|
178
|
+
RCT_EXPORT_METHOD(cleanup: (RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
|
|
179
|
+
[CATAppAnalytics cleanup];
|
|
180
|
+
resolve(@YES);
|
|
181
|
+
}
|
|
182
|
+
|
|
176
183
|
RCT_EXPORT_METHOD(trackSelfDescribingEvent:
|
|
177
184
|
(NSDictionary *)details
|
|
178
185
|
resolver:(RCTPromiseResolveBlock)resolve
|
|
@@ -650,6 +657,101 @@ RCT_EXPORT_METHOD(trackCustomEvent:
|
|
|
650
657
|
}
|
|
651
658
|
}
|
|
652
659
|
|
|
660
|
+
RCT_EXPORT_METHOD(trackRevenueEvent:
|
|
661
|
+
(NSDictionary *)details
|
|
662
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
663
|
+
rejecter:(RCTPromiseRejectBlock)reject) {
|
|
664
|
+
|
|
665
|
+
NSString *namespace = [details objectForKey:@"tracker"];
|
|
666
|
+
|
|
667
|
+
id<CATTrackerController> trackerController = [self trackerByNamespace:namespace];
|
|
668
|
+
|
|
669
|
+
if (trackerController != nil) {
|
|
670
|
+
NSDictionary *argmap = [details objectForKey:@"eventData"];
|
|
671
|
+
|
|
672
|
+
NSNumber *totalOrderAmount = [argmap objectForKey:@"totalOrderAmount"];
|
|
673
|
+
NSString *transactionId = [argmap objectForKey:@"transactionId"];
|
|
674
|
+
NSString *currency = [argmap objectForKey:@"currency"];
|
|
675
|
+
|
|
676
|
+
CATRevenueEvent *event = [[CATRevenueEvent alloc]
|
|
677
|
+
initWithTotalOrderAmount:totalOrderAmount
|
|
678
|
+
transactionId:transactionId
|
|
679
|
+
currency:currency];
|
|
680
|
+
|
|
681
|
+
if ([argmap objectForKey:@"taxAmount"] && ![[argmap objectForKey:@"taxAmount"] isEqual:[NSNull null]]) {
|
|
682
|
+
event.taxAmount = [argmap objectForKey:@"taxAmount"];
|
|
683
|
+
}
|
|
684
|
+
if ([argmap objectForKey:@"shippingCost"] && ![[argmap objectForKey:@"shippingCost"] isEqual:[NSNull null]]) {
|
|
685
|
+
event.shippingCost = [argmap objectForKey:@"shippingCost"];
|
|
686
|
+
}
|
|
687
|
+
if ([argmap objectForKey:@"discount"] && ![[argmap objectForKey:@"discount"] isEqual:[NSNull null]]) {
|
|
688
|
+
event.discount = [argmap objectForKey:@"discount"];
|
|
689
|
+
}
|
|
690
|
+
if ([argmap objectForKey:@"cartSize"] && ![[argmap objectForKey:@"cartSize"] isEqual:[NSNull null]]) {
|
|
691
|
+
event.cartSize = [argmap objectForKey:@"cartSize"];
|
|
692
|
+
}
|
|
693
|
+
if ([argmap objectForKey:@"paymentMethod"] && ![[argmap objectForKey:@"paymentMethod"] isEqual:[NSNull null]]) {
|
|
694
|
+
event.paymentMethod = [argmap objectForKey:@"paymentMethod"];
|
|
695
|
+
}
|
|
696
|
+
if ([argmap objectForKey:@"paymentProvider"] && ![[argmap objectForKey:@"paymentProvider"] isEqual:[NSNull null]]) {
|
|
697
|
+
event.paymentProvider = [argmap objectForKey:@"paymentProvider"];
|
|
698
|
+
}
|
|
699
|
+
if ([argmap objectForKey:@"extraMetadata"] && ![[argmap objectForKey:@"extraMetadata"] isEqual:[NSNull null]]) {
|
|
700
|
+
event.extraMetadata = [argmap objectForKey:@"extraMetadata"];
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
NSArray *itemsArray = [argmap objectForKey:@"items"];
|
|
704
|
+
if (itemsArray && ![itemsArray isEqual:[NSNull null]] && [itemsArray isKindOfClass:[NSArray class]]) {
|
|
705
|
+
NSMutableArray<CATRevenueEventItem *> *items = [NSMutableArray array];
|
|
706
|
+
for (NSDictionary *itemDict in itemsArray) {
|
|
707
|
+
if (![itemDict isKindOfClass:[NSDictionary class]]) continue;
|
|
708
|
+
|
|
709
|
+
CATRevenueEventItem *item = [[CATRevenueEventItem alloc] init];
|
|
710
|
+
|
|
711
|
+
if ([itemDict objectForKey:@"productId"] && ![[itemDict objectForKey:@"productId"] isEqual:[NSNull null]]) {
|
|
712
|
+
item.productId = [itemDict objectForKey:@"productId"];
|
|
713
|
+
}
|
|
714
|
+
if ([itemDict objectForKey:@"name"] && ![[itemDict objectForKey:@"name"] isEqual:[NSNull null]]) {
|
|
715
|
+
item.name = [itemDict objectForKey:@"name"];
|
|
716
|
+
}
|
|
717
|
+
if ([itemDict objectForKey:@"sku"] && ![[itemDict objectForKey:@"sku"] isEqual:[NSNull null]]) {
|
|
718
|
+
item.sku = [itemDict objectForKey:@"sku"];
|
|
719
|
+
}
|
|
720
|
+
if ([itemDict objectForKey:@"category"] && ![[itemDict objectForKey:@"category"] isEqual:[NSNull null]]) {
|
|
721
|
+
item.category = [itemDict objectForKey:@"category"];
|
|
722
|
+
}
|
|
723
|
+
if ([itemDict objectForKey:@"unitPrice"] && ![[itemDict objectForKey:@"unitPrice"] isEqual:[NSNull null]]) {
|
|
724
|
+
item.unitPrice = [itemDict objectForKey:@"unitPrice"];
|
|
725
|
+
}
|
|
726
|
+
if ([itemDict objectForKey:@"quantity"] && ![[itemDict objectForKey:@"quantity"] isEqual:[NSNull null]]) {
|
|
727
|
+
item.quantity = [itemDict objectForKey:@"quantity"];
|
|
728
|
+
}
|
|
729
|
+
if ([itemDict objectForKey:@"discount"] && ![[itemDict objectForKey:@"discount"] isEqual:[NSNull null]]) {
|
|
730
|
+
item.discount = [itemDict objectForKey:@"discount"];
|
|
731
|
+
}
|
|
732
|
+
if ([itemDict objectForKey:@"brand"] && ![[itemDict objectForKey:@"brand"] isEqual:[NSNull null]]) {
|
|
733
|
+
item.brand = [itemDict objectForKey:@"brand"];
|
|
734
|
+
}
|
|
735
|
+
if ([itemDict objectForKey:@"variant"] && ![[itemDict objectForKey:@"variant"] isEqual:[NSNull null]]) {
|
|
736
|
+
item.variant = [itemDict objectForKey:@"variant"];
|
|
737
|
+
}
|
|
738
|
+
if ([itemDict objectForKey:@"extraMetadata"] && ![[itemDict objectForKey:@"extraMetadata"] isEqual:[NSNull null]]) {
|
|
739
|
+
item.extraMetadata = [itemDict objectForKey:@"extraMetadata"];
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
[items addObject:item];
|
|
743
|
+
}
|
|
744
|
+
event.items = items;
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
[trackerController trackRevenueEvent:event];
|
|
748
|
+
resolve(@YES);
|
|
749
|
+
} else {
|
|
750
|
+
NSError* error = [NSError errorWithDomain:@"ConvivaAppAnalytics" code:200 userInfo:nil];
|
|
751
|
+
reject(@"ERROR", @"tracker with given namespace not found", error);
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
|
|
653
755
|
RCT_EXPORT_METHOD(setCustomTags:
|
|
654
756
|
(NSDictionary *)details
|
|
655
757
|
resolver:(RCTPromiseResolveBlock)resolve
|
|
@@ -1021,7 +1123,7 @@ RCT_EXPORT_METHOD(getIsInBackground:
|
|
|
1021
1123
|
// NSError* error = [NSError errorWithDomain:@"ConvivaAppAnalytics" code:200 userInfo:nil];
|
|
1022
1124
|
// reject(@"ERROR", @"tracker with given namespace not found", error);
|
|
1023
1125
|
// }
|
|
1024
|
-
|
|
1126
|
+
|
|
1025
1127
|
@try {
|
|
1026
1128
|
resolve(@(YES));
|
|
1027
1129
|
} @catch (NSException *exception) {
|
package/package.json
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@convivainc/conviva-react-native-appanalytics",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Conviva React Native Application Analytics Library",
|
|
5
5
|
"main": "conviva-react-native-appanalytics.js",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "git+github.com:Conviva/conviva-react-native-appanalytics.git"
|
|
9
9
|
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@babel/plugin-transform-react-display-name": "^7.0.0",
|
|
12
|
+
"hoist-non-react-statics": "^3.3.2",
|
|
13
|
+
"lodash": "^4.17.21",
|
|
14
|
+
"tslib": "^2.6.0"
|
|
15
|
+
},
|
|
10
16
|
"keywords": [
|
|
11
17
|
"Conviva",
|
|
12
18
|
"Application",
|
package/plugin.js
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Resolve babel-types and babel-template in a version-agnostic way.
|
|
4
|
+
// Priority order:
|
|
5
|
+
// 1. Use types/template injected by Babel itself (Babel 7 plugin API).
|
|
6
|
+
// 2. Fall back to @babel/types / @babel/template (Babel 7 standalone packages).
|
|
7
|
+
// 3. Fall back to babel-types / babel-template (Babel 6 legacy packages,
|
|
8
|
+
// guaranteed present via this package's own dependencies).
|
|
9
|
+
// The fallback chain means the plugin works whether the host project uses
|
|
10
|
+
// Babel 6 or Babel 7, without requiring either legacy package to be installed
|
|
11
|
+
// explicitly by the consuming app.
|
|
12
|
+
|
|
13
|
+
function resolveTypes(babel) {
|
|
14
|
+
if (babel && babel.types) {
|
|
15
|
+
return babel.types;
|
|
16
|
+
}
|
|
17
|
+
try { return require('@babel/types'); } catch (_) {}
|
|
18
|
+
try { return require('babel-types'); } catch (_) {}
|
|
19
|
+
throw new Error('[conviva] Could not resolve babel types. Install @babel/types (Babel 7) or babel-types (Babel 6).');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function resolveTemplate(babel) {
|
|
23
|
+
if (babel && babel.template) {
|
|
24
|
+
return babel.template;
|
|
25
|
+
}
|
|
26
|
+
try { return require('@babel/template').default || require('@babel/template'); } catch (_) {}
|
|
27
|
+
try { return require('babel-template'); } catch (_) {}
|
|
28
|
+
throw new Error('[conviva] Could not resolve babel template. Install @babel/template (Babel 7) or babel-template (Babel 6).');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const ALLOWED_TOUCHABLE_COMPONENTS = [
|
|
32
|
+
'TouchableOpacity',
|
|
33
|
+
'TouchableNativeFeedback',
|
|
34
|
+
'TouchableWithoutFeedback',
|
|
35
|
+
'TouchableHighlight',
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
function replaceWithTouchableAutoTrackHigherOrderComponent(path, t, template) {
|
|
39
|
+
if (!ALLOWED_TOUCHABLE_COMPONENTS.includes(path.node.id.name)) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const convivaLibImport = template(`(
|
|
44
|
+
require('@convivainc/conviva-react-native-appanalytics').default || {
|
|
45
|
+
HIGHER_ORDER_COMP: (Component) => Component,
|
|
46
|
+
}
|
|
47
|
+
)`);
|
|
48
|
+
|
|
49
|
+
const createHigherOrderComponent = template(`
|
|
50
|
+
const COMPONENT_ID = HIGHER_ORDER_COMP_CALL_EXPRESSION;
|
|
51
|
+
`);
|
|
52
|
+
|
|
53
|
+
const equivalentExpression = t.classExpression(
|
|
54
|
+
path.node.id,
|
|
55
|
+
path.node.superClass,
|
|
56
|
+
path.node.body,
|
|
57
|
+
path.node.decorators || []
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
const hocID = t.identifier('convivaTouchableAutoTrack');
|
|
61
|
+
|
|
62
|
+
const convivaImport = convivaLibImport({
|
|
63
|
+
HIGHER_ORDER_COMP: hocID,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const autotrackExpression = t.callExpression(
|
|
67
|
+
t.memberExpression(convivaImport.expression, hocID),
|
|
68
|
+
[equivalentExpression]
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
const replacement = createHigherOrderComponent({
|
|
72
|
+
COMPONENT_ID: path.node.id,
|
|
73
|
+
HIGHER_ORDER_COMP_CALL_EXPRESSION: autotrackExpression,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
path.replaceWith(replacement);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// @babel/plugin-transform-react-display-name is listed in this package's
|
|
80
|
+
// dependencies, so it is always present in the package's own node_modules.
|
|
81
|
+
function resolveDisplayNamePlugin() {
|
|
82
|
+
try {
|
|
83
|
+
const mod = require('@babel/plugin-transform-react-display-name');
|
|
84
|
+
return mod.default || mod;
|
|
85
|
+
} catch (_) {}
|
|
86
|
+
throw new Error(
|
|
87
|
+
'[conviva] Could not resolve @babel/plugin-transform-react-display-name. ' +
|
|
88
|
+
'Make sure it is installed: npm install --save-dev @babel/plugin-transform-react-display-name'
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Injects `ClassName.displayName = 'ClassName'` after ES6 class declarations
|
|
93
|
+
// that contain a render() method. This covers the gap left by
|
|
94
|
+
// @babel/plugin-transform-react-display-name v7.x, which only handles
|
|
95
|
+
// React.createClass() / createReactClass() call patterns and has no
|
|
96
|
+
// ClassDeclaration visitor.
|
|
97
|
+
// Touchable components are skipped because they are replaced entirely by the
|
|
98
|
+
// HOC wrapping logic above.
|
|
99
|
+
function injectClassDisplayName(path, t) {
|
|
100
|
+
const className = path.node.id && path.node.id.name;
|
|
101
|
+
if (!className || ALLOWED_TOUCHABLE_COMPONENTS.includes(className)) return;
|
|
102
|
+
|
|
103
|
+
const hasRenderMethod = path.node.body.body.some(
|
|
104
|
+
member =>
|
|
105
|
+
member.type === 'ClassMethod' &&
|
|
106
|
+
member.key &&
|
|
107
|
+
member.key.name === 'render'
|
|
108
|
+
);
|
|
109
|
+
if (!hasRenderMethod) return;
|
|
110
|
+
|
|
111
|
+
path.insertAfter(
|
|
112
|
+
t.expressionStatement(
|
|
113
|
+
t.assignmentExpression(
|
|
114
|
+
'=',
|
|
115
|
+
t.memberExpression(t.identifier(className), t.identifier('displayName')),
|
|
116
|
+
t.stringLiteral(className)
|
|
117
|
+
)
|
|
118
|
+
)
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function transform(babel) {
|
|
123
|
+
const t = resolveTypes(babel);
|
|
124
|
+
const template = resolveTemplate(babel);
|
|
125
|
+
|
|
126
|
+
return {
|
|
127
|
+
// Bundles @babel/plugin-transform-react-display-name so consumers don't
|
|
128
|
+
// need to add it separately - display name injection is a Conviva concern
|
|
129
|
+
// required for screen_view auto-detection via ConvivaNavigationContainer.
|
|
130
|
+
inherits: resolveDisplayNamePlugin(),
|
|
131
|
+
visitor: {
|
|
132
|
+
ClassDeclaration(path) {
|
|
133
|
+
replaceWithTouchableAutoTrackHigherOrderComponent(path, t, template);
|
|
134
|
+
injectClassDisplayName(path, t);
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
module.exports = transform;
|