react-native-moengage-personalize 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +12 -0
- package/README.md +3 -0
- package/ReactNativeMoEngagePersonalize.podspec +30 -0
- package/android/build.gradle +69 -0
- package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/android/gradle/wrapper/gradle-wrapper.properties +5 -0
- package/android/gradlew +185 -0
- package/android/gradlew.bat +89 -0
- package/android/src/main/AndroidManifest.xml +1 -0
- package/android/src/main/java/com/moengage/react/personalize/MoEngagePersonalizeHandler.kt +104 -0
- package/android/src/main/java/com/moengage/react/personalize/MoengagePersonalizePackage.kt +50 -0
- package/android/src/newarch/java/com/moengage/react/personalize/MoEReactPersonalize.kt +54 -0
- package/android/src/oldarch/java/com/moengage/react/personalize/MoEReactPersonalize.kt +63 -0
- package/ios/MoEReactNativePersonalizeHandler.h +26 -0
- package/ios/MoEReactNativePersonalizeHandler.m +118 -0
- package/ios/MoEngagePersonalizeBridge.h +15 -0
- package/ios/MoEngagePersonalizeBridge.mm +46 -0
- package/package.json +52 -0
- package/src/NativeMoEngagePersonalize.ts +51 -0
- package/src/index.ts +164 -0
- package/src/internal/Constants.ts +16 -0
- package/src/internal/MoEngagePersonalizeHandler.ts +97 -0
- package/src/internal/utils/PayloadBuilder.ts +91 -0
- package/src/internal/utils/PayloadParser.ts +117 -0
- package/src/model/DataSource.ts +12 -0
- package/src/model/ExperienceCampaign.ts +47 -0
- package/src/model/ExperienceCampaignFailure.ts +28 -0
- package/src/model/ExperienceCampaignMeta.ts +34 -0
- package/src/model/ExperienceCampaignsMetadata.ts +29 -0
- package/src/model/ExperienceCampaignsResult.ts +30 -0
- package/src/model/ExperienceFailureReason.ts +36 -0
- package/src/model/ExperienceStatus.ts +14 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026 MoEngage, Inc.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
* Use of source code or binaries contained within MoEngage's SDKs is permitted only to enable use of the MoEngage platform by customers of MoEngage. The Licensee may not:
|
|
5
|
+
* - permit any third party to use the Software;
|
|
6
|
+
* - modify or translate the Software except as otherwise permitted;
|
|
7
|
+
* - reverse engineer, decompile, or disassemble the Software;
|
|
8
|
+
* - copy the Software, except as expressly provided above; or
|
|
9
|
+
* - remove or obscure any proprietary rights notices or labels on the Software.
|
|
10
|
+
* - Licensee may not transfer the Software or any rights under this Agreement without the Licensor's prior written consent.
|
|
11
|
+
* - MoEngage owns the Software and all intellectual property rights embodied therein, including copyrights and valuable trade secrets embodied in the Software. The Licensee shall not alter or remove this copyright notice.
|
|
12
|
+
*
|
|
13
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE USER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
package com.moengage.react.personalize
|
|
17
|
+
|
|
18
|
+
import com.facebook.react.bridge.Promise
|
|
19
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
20
|
+
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
|
21
|
+
import com.facebook.react.bridge.ReactMethod
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Bridge to communicate with personalize plugin JS code in old arch.
|
|
25
|
+
*/
|
|
26
|
+
class MoEReactPersonalize(
|
|
27
|
+
reactContext: ReactApplicationContext
|
|
28
|
+
) : ReactContextBaseJavaModule(reactContext) {
|
|
29
|
+
|
|
30
|
+
private val bridgeHandler = MoEngagePersonalizeHandler(reactContext.applicationContext)
|
|
31
|
+
|
|
32
|
+
override fun getName() = bridgeHandler.getName()
|
|
33
|
+
|
|
34
|
+
@ReactMethod
|
|
35
|
+
fun fetchExperiencesMeta(payload: String, promise: Promise) {
|
|
36
|
+
bridgeHandler.fetchExperiencesMeta(payload, promise)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@ReactMethod
|
|
40
|
+
fun fetchExperiences(payload: String, promise: Promise) {
|
|
41
|
+
bridgeHandler.fetchExperiences(payload, promise)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@ReactMethod
|
|
45
|
+
fun experiencesShown(payload: String) {
|
|
46
|
+
bridgeHandler.trackExperienceShown(payload)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@ReactMethod
|
|
50
|
+
fun experienceClicked(payload: String) {
|
|
51
|
+
bridgeHandler.trackExperienceClicked(payload)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@ReactMethod
|
|
55
|
+
fun offeringsShown(payload: String) {
|
|
56
|
+
bridgeHandler.trackOfferingShown(payload)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
@ReactMethod
|
|
60
|
+
fun offeringClicked(payload: String) {
|
|
61
|
+
bridgeHandler.trackOfferingClicked(payload)
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
//
|
|
2
|
+
// MoEReactNativePersonalizeHandler.h
|
|
3
|
+
// ReactNativeMoEngagePersonalize
|
|
4
|
+
//
|
|
5
|
+
|
|
6
|
+
#import <Foundation/Foundation.h>
|
|
7
|
+
#import <UIKit/UIKit.h>
|
|
8
|
+
#import <React/RCTBridgeModule.h>
|
|
9
|
+
|
|
10
|
+
@interface MoEReactNativePersonalizeHandler : NSObject
|
|
11
|
+
|
|
12
|
+
+(instancetype)sharedInstance;
|
|
13
|
+
|
|
14
|
+
// Fetch APIs
|
|
15
|
+
-(void)fetchExperiencesMeta:(NSString *)payload resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject;
|
|
16
|
+
-(void)fetchExperiences:(NSString *)payload resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject;
|
|
17
|
+
|
|
18
|
+
// Experience Tracking
|
|
19
|
+
-(void)experiencesShown:(NSString *)payload;
|
|
20
|
+
-(void)experienceClicked:(NSString *)payload;
|
|
21
|
+
|
|
22
|
+
// Offering Tracking
|
|
23
|
+
-(void)offeringsShown:(NSString *)payload;
|
|
24
|
+
-(void)offeringClicked:(NSString *)payload;
|
|
25
|
+
|
|
26
|
+
@end
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
//
|
|
2
|
+
// MoEReactNativePersonalizeHandler.m
|
|
3
|
+
// ReactNativeMoEngagePersonalize
|
|
4
|
+
//
|
|
5
|
+
|
|
6
|
+
#import <Foundation/Foundation.h>
|
|
7
|
+
#import "MoEReactNativePersonalizeHandler.h"
|
|
8
|
+
#import "ReactNativeMoEngage/MoEngageReactUtils.h"
|
|
9
|
+
|
|
10
|
+
@import MoEngagePluginPersonalize;
|
|
11
|
+
|
|
12
|
+
static NSString * const kLogTag = @"[MoEngageReactPersonalize]";
|
|
13
|
+
|
|
14
|
+
@implementation MoEReactNativePersonalizeHandler : NSObject
|
|
15
|
+
|
|
16
|
+
+(instancetype)sharedInstance {
|
|
17
|
+
static dispatch_once_t onceToken;
|
|
18
|
+
static MoEReactNativePersonalizeHandler *instance;
|
|
19
|
+
dispatch_once(&onceToken, ^{
|
|
20
|
+
instance = [[MoEReactNativePersonalizeHandler alloc] init];
|
|
21
|
+
});
|
|
22
|
+
return instance;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
#pragma mark - Helpers
|
|
26
|
+
|
|
27
|
+
/// Serializes the bridge response and resolves/rejects the JS promise. If the
|
|
28
|
+
/// response carries an `error` key (per the contract), the promise is rejected
|
|
29
|
+
/// with the stringified payload. JSON serialization failures reject with PARSE_ERROR.
|
|
30
|
+
-(void)resolveResponse:(NSDictionary *)response
|
|
31
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
32
|
+
rejecter:(RCTPromiseRejectBlock)reject
|
|
33
|
+
method:(NSString *)method {
|
|
34
|
+
NSError *err;
|
|
35
|
+
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:response options:0 error:&err];
|
|
36
|
+
if (jsonData) {
|
|
37
|
+
NSString *strPayload = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
|
|
38
|
+
if (response[@"error"] != nil) {
|
|
39
|
+
NSLog(@"%@ %@: rejecting with PERSONALIZE_ERROR — %@", kLogTag, method, response[@"error"]);
|
|
40
|
+
reject(@"PERSONALIZE_ERROR", strPayload, nil);
|
|
41
|
+
} else {
|
|
42
|
+
resolve(strPayload);
|
|
43
|
+
}
|
|
44
|
+
} else {
|
|
45
|
+
NSLog(@"%@ %@: failed to serialize response — %@", kLogTag, method, err);
|
|
46
|
+
reject(@"PARSE_ERROR", @"Failed to serialize response", err);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/// Logs and parses the incoming JS payload string into an NSDictionary. Returns
|
|
51
|
+
/// nil (and logs) on parse failure so callers can short-circuit safely.
|
|
52
|
+
-(NSDictionary *)parsePayload:(NSString *)payload method:(NSString *)method {
|
|
53
|
+
NSDictionary *jsonPayload = [MoEngageReactUtils getJSONRepresentation:payload];
|
|
54
|
+
if (jsonPayload == nil) {
|
|
55
|
+
NSLog(@"%@ %@: failed to parse payload — input: %@", kLogTag, method, payload);
|
|
56
|
+
}
|
|
57
|
+
return jsonPayload;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
#pragma mark - Fetch APIs
|
|
61
|
+
|
|
62
|
+
-(void)fetchExperiencesMeta:(NSString *)payload resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject {
|
|
63
|
+
NSLog(@"%@ fetchExperiencesMeta", kLogTag);
|
|
64
|
+
NSDictionary *jsonPayload = [self parsePayload:payload method:@"fetchExperiencesMeta"];
|
|
65
|
+
if (jsonPayload == nil) {
|
|
66
|
+
reject(@"PARSE_ERROR", @"Failed to parse incoming payload", nil);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
[[MoEngagePluginPersonalizeBridge sharedInstance] fetchExperiencesMeta:jsonPayload completionHandler:^(NSDictionary<NSString *,id> * _Nonnull response) {
|
|
70
|
+
[self resolveResponse:response resolver:resolve rejecter:reject method:@"fetchExperiencesMeta"];
|
|
71
|
+
}];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
-(void)fetchExperiences:(NSString *)payload resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject {
|
|
75
|
+
NSLog(@"%@ fetchExperiences", kLogTag);
|
|
76
|
+
NSDictionary *jsonPayload = [self parsePayload:payload method:@"fetchExperiences"];
|
|
77
|
+
if (jsonPayload == nil) {
|
|
78
|
+
reject(@"PARSE_ERROR", @"Failed to parse incoming payload", nil);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
[[MoEngagePluginPersonalizeBridge sharedInstance] fetchExperiences:jsonPayload completionHandler:^(NSDictionary<NSString *,id> * _Nonnull response) {
|
|
82
|
+
[self resolveResponse:response resolver:resolve rejecter:reject method:@"fetchExperiences"];
|
|
83
|
+
}];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
#pragma mark - Experience Tracking
|
|
87
|
+
|
|
88
|
+
-(void)experiencesShown:(NSString *)payload {
|
|
89
|
+
NSLog(@"%@ experiencesShown", kLogTag);
|
|
90
|
+
NSDictionary *jsonPayload = [self parsePayload:payload method:@"experiencesShown"];
|
|
91
|
+
if (jsonPayload == nil) return;
|
|
92
|
+
[[MoEngagePluginPersonalizeBridge sharedInstance] experiencesShown:jsonPayload];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
-(void)experienceClicked:(NSString *)payload {
|
|
96
|
+
NSLog(@"%@ experienceClicked", kLogTag);
|
|
97
|
+
NSDictionary *jsonPayload = [self parsePayload:payload method:@"experienceClicked"];
|
|
98
|
+
if (jsonPayload == nil) return;
|
|
99
|
+
[[MoEngagePluginPersonalizeBridge sharedInstance] experienceClicked:jsonPayload];
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
#pragma mark - Offering Tracking
|
|
103
|
+
|
|
104
|
+
-(void)offeringsShown:(NSString *)payload {
|
|
105
|
+
NSLog(@"%@ offeringsShown", kLogTag);
|
|
106
|
+
NSDictionary *jsonPayload = [self parsePayload:payload method:@"offeringsShown"];
|
|
107
|
+
if (jsonPayload == nil) return;
|
|
108
|
+
[[MoEngagePluginPersonalizeBridge sharedInstance] offeringsShown:jsonPayload];
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
-(void)offeringClicked:(NSString *)payload {
|
|
112
|
+
NSLog(@"%@ offeringClicked", kLogTag);
|
|
113
|
+
NSDictionary *jsonPayload = [self parsePayload:payload method:@"offeringClicked"];
|
|
114
|
+
if (jsonPayload == nil) return;
|
|
115
|
+
[[MoEngagePluginPersonalizeBridge sharedInstance] offeringClicked:jsonPayload];
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
@end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// MoEngagePersonalizeBridge.h
|
|
2
|
+
|
|
3
|
+
#import <React/RCTBridgeModule.h>
|
|
4
|
+
|
|
5
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
6
|
+
#import <NativeMoEngagePersonalizeSpec/NativeMoEngagePersonalizeSpec.h>
|
|
7
|
+
#endif
|
|
8
|
+
|
|
9
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
10
|
+
@interface MoEngagePersonalizeBridge : NSObject <NativeMoEngagePersonalizeSpec>
|
|
11
|
+
@end
|
|
12
|
+
#else
|
|
13
|
+
@interface MoEngagePersonalizeBridge : NSObject <RCTBridgeModule>
|
|
14
|
+
@end
|
|
15
|
+
#endif
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// MoEngagePersonalizeBridge.mm
|
|
2
|
+
|
|
3
|
+
#import "MoEngagePersonalizeBridge.h"
|
|
4
|
+
#import "MoEReactNativePersonalizeHandler.h"
|
|
5
|
+
|
|
6
|
+
@implementation MoEngagePersonalizeBridge
|
|
7
|
+
|
|
8
|
+
RCT_EXPORT_MODULE()
|
|
9
|
+
|
|
10
|
+
#pragma mark - Fetch APIs
|
|
11
|
+
|
|
12
|
+
RCT_EXPORT_METHOD(fetchExperiencesMeta:(NSString *)payload resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
|
|
13
|
+
[[MoEReactNativePersonalizeHandler sharedInstance] fetchExperiencesMeta:payload resolve:resolve reject:reject];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
RCT_EXPORT_METHOD(fetchExperiences:(NSString *)payload resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
|
|
17
|
+
[[MoEReactNativePersonalizeHandler sharedInstance] fetchExperiences:payload resolve:resolve reject:reject];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
#pragma mark - Experience Tracking
|
|
21
|
+
|
|
22
|
+
RCT_EXPORT_METHOD(experiencesShown:(NSString *)payload) {
|
|
23
|
+
[[MoEReactNativePersonalizeHandler sharedInstance] experiencesShown:payload];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
RCT_EXPORT_METHOD(experienceClicked:(NSString *)payload) {
|
|
27
|
+
[[MoEReactNativePersonalizeHandler sharedInstance] experienceClicked:payload];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
#pragma mark - Offering Tracking
|
|
31
|
+
|
|
32
|
+
RCT_EXPORT_METHOD(offeringsShown:(NSString *)payload) {
|
|
33
|
+
[[MoEReactNativePersonalizeHandler sharedInstance] offeringsShown:payload];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
RCT_EXPORT_METHOD(offeringClicked:(NSString *)payload) {
|
|
37
|
+
[[MoEReactNativePersonalizeHandler sharedInstance] offeringClicked:payload];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
41
|
+
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const facebook::react::ObjCTurboModule::InitParams &)params {
|
|
42
|
+
return std::make_shared<facebook::react::NativeMoEngagePersonalizeSpecJSI>(params);
|
|
43
|
+
}
|
|
44
|
+
#endif
|
|
45
|
+
|
|
46
|
+
@end
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "react-native-moengage-personalize",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Personalize Module for the MoEngage Platform",
|
|
5
|
+
"main": "src/index.ts",
|
|
6
|
+
"files": [
|
|
7
|
+
"android",
|
|
8
|
+
"ios",
|
|
9
|
+
"src",
|
|
10
|
+
"package.json",
|
|
11
|
+
"ReactNativeMoEngagePersonalize.podspec",
|
|
12
|
+
"README.md",
|
|
13
|
+
"!**/__tests__",
|
|
14
|
+
"!**/__mocks__"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"test": "jest",
|
|
18
|
+
"build": "echo \"Not required\" && exit 0"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"react-native",
|
|
22
|
+
"ios",
|
|
23
|
+
"android",
|
|
24
|
+
"moengage"
|
|
25
|
+
],
|
|
26
|
+
"repository": "https://github.com/moengage/React-Native",
|
|
27
|
+
"author": {
|
|
28
|
+
"name": "MoEngage",
|
|
29
|
+
"email": "mobiledevs@moengage.com"
|
|
30
|
+
},
|
|
31
|
+
"publishConfig": {
|
|
32
|
+
"registry": "https://registry.npmjs.org/"
|
|
33
|
+
},
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"react-native-moengage": "^12.0.0"
|
|
36
|
+
},
|
|
37
|
+
"license": "SEE LICENSE IN LICENSE.md",
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@types/jest": "^29.5.0",
|
|
40
|
+
"react-native": "0.73.0",
|
|
41
|
+
"ts-jest": "^29.1.0",
|
|
42
|
+
"typescript": "^4.3.0"
|
|
43
|
+
},
|
|
44
|
+
"codegenConfig": {
|
|
45
|
+
"name": "NativeMoEngagePersonalizeSpec",
|
|
46
|
+
"type": "modules",
|
|
47
|
+
"jsSrcsDir": "src",
|
|
48
|
+
"android": {
|
|
49
|
+
"javaPackageName": "com.moengage.react.personalize"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { TurboModule } from 'react-native/Libraries/TurboModule/RCTExport';
|
|
2
|
+
import { TurboModuleRegistry } from 'react-native';
|
|
3
|
+
|
|
4
|
+
export interface Spec extends TurboModule {
|
|
5
|
+
/**
|
|
6
|
+
* Fetches experience campaign metadata filtered by status.
|
|
7
|
+
*
|
|
8
|
+
* @param payload Stringified JSON payload.
|
|
9
|
+
* @returns {Promise<string>} A promise that contains experience metadata.
|
|
10
|
+
*/
|
|
11
|
+
fetchExperiencesMeta(payload: string): Promise<string>;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Fetches experience campaigns for the given keys and optional attributes.
|
|
15
|
+
*
|
|
16
|
+
* @param payload Stringified JSON payload.
|
|
17
|
+
* @returns {Promise<string>} A promise that contains experiences and failures.
|
|
18
|
+
*/
|
|
19
|
+
fetchExperiences(payload: string): Promise<string>;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Tracks impression events for one or more experience campaigns.
|
|
23
|
+
*
|
|
24
|
+
* @param payload Stringified JSON payload.
|
|
25
|
+
*/
|
|
26
|
+
experiencesShown(payload: string): void;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Tracks a click event for a single experience campaign.
|
|
30
|
+
*
|
|
31
|
+
* @param payload Stringified JSON payload.
|
|
32
|
+
*/
|
|
33
|
+
experienceClicked(payload: string): void;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Tracks impression events for one or more offerings.
|
|
37
|
+
*
|
|
38
|
+
* @param payload Stringified JSON payload.
|
|
39
|
+
*/
|
|
40
|
+
offeringsShown(payload: string): void;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Tracks a click event for a single offering within an experience campaign.
|
|
44
|
+
*
|
|
45
|
+
* @param payload Stringified JSON payload.
|
|
46
|
+
*/
|
|
47
|
+
offeringClicked(payload: string): void;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const MoEngagePersonalizeBridge = TurboModuleRegistry.getEnforcing<Spec>('MoEngagePersonalizeBridge');
|
|
51
|
+
export default MoEngagePersonalizeBridge;
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import ExperienceCampaign from "./model/ExperienceCampaign";
|
|
2
|
+
import ExperienceCampaignFailure from "./model/ExperienceCampaignFailure";
|
|
3
|
+
import ExperienceCampaignMeta from "./model/ExperienceCampaignMeta";
|
|
4
|
+
import ExperienceCampaignsMetadata from "./model/ExperienceCampaignsMetadata";
|
|
5
|
+
import ExperienceCampaignsResult from "./model/ExperienceCampaignsResult";
|
|
6
|
+
import { DataSource } from "./model/DataSource";
|
|
7
|
+
import { ExperienceStatus } from "./model/ExperienceStatus";
|
|
8
|
+
import { ExperienceFailureReason } from "./model/ExperienceFailureReason";
|
|
9
|
+
import MoEngagePersonalizeHandler from "./internal/MoEngagePersonalizeHandler";
|
|
10
|
+
import { MoEngageLogger } from "react-native-moengage";
|
|
11
|
+
import { MODULE_TAG } from "./internal/Constants";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Public API for the MoEngage Personalize Experience module. Each instance is
|
|
15
|
+
* scoped to a single MoEngage workspace (app id) — multiple workspaces should
|
|
16
|
+
* each instantiate their own.
|
|
17
|
+
*
|
|
18
|
+
* @author MoEngage
|
|
19
|
+
* @since 1.0.0
|
|
20
|
+
*/
|
|
21
|
+
class ReactMoEngagePersonalize {
|
|
22
|
+
|
|
23
|
+
private readonly TAG = `${MODULE_TAG}ReactMoEngagePersonalize`;
|
|
24
|
+
|
|
25
|
+
private handler: MoEngagePersonalizeHandler;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Construct a personalize instance for the given workspace.
|
|
29
|
+
*
|
|
30
|
+
* @param appId The MoEngage workspace identifier.
|
|
31
|
+
* @since 1.0.0
|
|
32
|
+
*/
|
|
33
|
+
constructor(appId: string) {
|
|
34
|
+
MoEngageLogger.debug(`${this.TAG} constructor() : appId=${appId}`);
|
|
35
|
+
this.handler = new MoEngagePersonalizeHandler(appId);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Fetches experience campaign metadata filtered by status.
|
|
40
|
+
*
|
|
41
|
+
* @param statuses Array of {@link ExperienceStatus} to filter by.
|
|
42
|
+
* @returns Promise resolving to {@link ExperienceCampaignsMetadata}.
|
|
43
|
+
* @throws Rejects on SDK-level failures (SDK not initialized, network error, etc.).
|
|
44
|
+
* @since 1.0.0
|
|
45
|
+
*/
|
|
46
|
+
fetchExperiencesMeta(statuses: ExperienceStatus[]): Promise<ExperienceCampaignsMetadata> {
|
|
47
|
+
MoEngageLogger.verbose(`${this.TAG} fetchExperiencesMeta() : `);
|
|
48
|
+
return this.handler.fetchExperiencesMeta(statuses);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Fetches a single experience campaign for the given key.
|
|
53
|
+
*
|
|
54
|
+
* @param experienceKey The experience key to fetch.
|
|
55
|
+
* @param attributes Optional key-value attributes for personalization.
|
|
56
|
+
* @returns Promise resolving to {@link ExperienceCampaignsResult}.
|
|
57
|
+
* @throws Rejects on SDK-level failures.
|
|
58
|
+
* @since 1.0.0
|
|
59
|
+
*/
|
|
60
|
+
fetchExperience(
|
|
61
|
+
experienceKey: string,
|
|
62
|
+
attributes: Record<string, string> = {}
|
|
63
|
+
): Promise<ExperienceCampaignsResult> {
|
|
64
|
+
MoEngageLogger.verbose(`${this.TAG} fetchExperience() : `);
|
|
65
|
+
return this.fetchExperiences([experienceKey], attributes);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Fetches experience campaigns for the given keys and optional attributes.
|
|
70
|
+
*
|
|
71
|
+
* @param experienceKeys Array of experience keys to fetch.
|
|
72
|
+
* @param attributes Optional key-value attributes for personalization.
|
|
73
|
+
* @returns Promise resolving to {@link ExperienceCampaignsResult}.
|
|
74
|
+
* @throws Rejects on SDK-level failures.
|
|
75
|
+
* @since 1.0.0
|
|
76
|
+
*/
|
|
77
|
+
fetchExperiences(
|
|
78
|
+
experienceKeys: string[],
|
|
79
|
+
attributes: Record<string, string> = {}
|
|
80
|
+
): Promise<ExperienceCampaignsResult> {
|
|
81
|
+
MoEngageLogger.verbose(`${this.TAG} fetchExperiences() : `);
|
|
82
|
+
return this.handler.fetchExperiences(experienceKeys, attributes);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Tracks impression events for one or more experience campaigns.
|
|
87
|
+
*
|
|
88
|
+
* @param campaigns Array of {@link ExperienceCampaign} that were shown.
|
|
89
|
+
* @since 1.0.0
|
|
90
|
+
*/
|
|
91
|
+
experiencesShown(campaigns: ExperienceCampaign[]): void {
|
|
92
|
+
MoEngageLogger.verbose(`${this.TAG} experiencesShown() : `);
|
|
93
|
+
this.handler.experiencesShown(campaigns);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Tracks an impression event for a single experience campaign.
|
|
98
|
+
*
|
|
99
|
+
* @param campaign The {@link ExperienceCampaign} that was shown.
|
|
100
|
+
* @since 1.0.0
|
|
101
|
+
*/
|
|
102
|
+
experienceShown(campaign: ExperienceCampaign): void {
|
|
103
|
+
MoEngageLogger.verbose(`${this.TAG} experienceShown() : `);
|
|
104
|
+
this.experiencesShown([campaign]);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Tracks a click event for a single experience campaign.
|
|
109
|
+
*
|
|
110
|
+
* @param campaign The {@link ExperienceCampaign} that was clicked.
|
|
111
|
+
* @since 1.0.0
|
|
112
|
+
*/
|
|
113
|
+
experienceClicked(campaign: ExperienceCampaign): void {
|
|
114
|
+
MoEngageLogger.verbose(`${this.TAG} experienceClicked() : `);
|
|
115
|
+
this.handler.experienceClicked(campaign);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Tracks impression events for one or more offerings.
|
|
120
|
+
*
|
|
121
|
+
* @param offeringPayloads Array of full offering payload dictionaries.
|
|
122
|
+
* @since 1.0.0
|
|
123
|
+
*/
|
|
124
|
+
offeringsShown(offeringPayloads: Record<string, any>[]): void {
|
|
125
|
+
MoEngageLogger.verbose(`${this.TAG} offeringsShown() : `);
|
|
126
|
+
this.handler.offeringsShown(offeringPayloads);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Tracks an impression event for a single offering.
|
|
131
|
+
*
|
|
132
|
+
* @param offeringPayload The full offering payload dictionary that was shown.
|
|
133
|
+
* @since 1.0.0
|
|
134
|
+
*/
|
|
135
|
+
offeringShown(offeringPayload: Record<string, any>): void {
|
|
136
|
+
MoEngageLogger.verbose(`${this.TAG} offeringShown() : `);
|
|
137
|
+
this.offeringsShown([offeringPayload]);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Tracks a click event for a single offering within an experience campaign.
|
|
142
|
+
*
|
|
143
|
+
* @param campaign The {@link ExperienceCampaign} containing the offering.
|
|
144
|
+
* @param offeringPayload The full offering payload dictionary that was clicked.
|
|
145
|
+
* @since 1.0.0
|
|
146
|
+
*/
|
|
147
|
+
offeringClicked(campaign: ExperienceCampaign, offeringPayload: Record<string, any>): void {
|
|
148
|
+
MoEngageLogger.verbose(`${this.TAG} offeringClicked() : `);
|
|
149
|
+
this.handler.offeringClicked(campaign, offeringPayload);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export {
|
|
154
|
+
ExperienceCampaign,
|
|
155
|
+
ExperienceCampaignFailure,
|
|
156
|
+
ExperienceCampaignMeta,
|
|
157
|
+
ExperienceCampaignsMetadata,
|
|
158
|
+
ExperienceCampaignsResult,
|
|
159
|
+
DataSource,
|
|
160
|
+
ExperienceStatus,
|
|
161
|
+
ExperienceFailureReason,
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
export default ReactMoEngagePersonalize;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export const MODULE_TAG = "MoEngageReactPersonalize_"
|
|
2
|
+
|
|
3
|
+
export const keyData = 'data'
|
|
4
|
+
|
|
5
|
+
export const keyStatus = 'status'
|
|
6
|
+
|
|
7
|
+
export const keyExperiences = 'experiences'
|
|
8
|
+
export const keyExperienceKey = 'experienceKey'
|
|
9
|
+
export const keyExperienceName = 'experienceName'
|
|
10
|
+
export const keyPayload = 'payload'
|
|
11
|
+
export const keyExperienceContext = 'experienceContext'
|
|
12
|
+
export const keySource = 'source'
|
|
13
|
+
|
|
14
|
+
export const keyFailures = 'failures'
|
|
15
|
+
export const keyReason = 'reason'
|
|
16
|
+
export const keyExperienceKeys = 'experienceKeys'
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import MoEngagePersonalizeBridge from "../NativeMoEngagePersonalize";
|
|
2
|
+
import ExperienceCampaign from "../model/ExperienceCampaign";
|
|
3
|
+
import ExperienceCampaignsMetadata from "../model/ExperienceCampaignsMetadata";
|
|
4
|
+
import ExperienceCampaignsResult from "../model/ExperienceCampaignsResult";
|
|
5
|
+
import { ExperienceStatus } from "../model/ExperienceStatus";
|
|
6
|
+
import { MoEngageLogger } from "react-native-moengage";
|
|
7
|
+
import { MODULE_TAG } from "./Constants";
|
|
8
|
+
import * as PayloadBuilder from "./utils/PayloadBuilder";
|
|
9
|
+
import * as Parser from "./utils/PayloadParser";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Helper class that translates Public Personalize APIs into native bridge calls.
|
|
13
|
+
*
|
|
14
|
+
* @author MoEngage
|
|
15
|
+
* @since 1.0.0
|
|
16
|
+
*/
|
|
17
|
+
export default class MoEngagePersonalizeHandler {
|
|
18
|
+
|
|
19
|
+
private TAG = `${MODULE_TAG}MoEngagePersonalizeHandler`;
|
|
20
|
+
|
|
21
|
+
private appId: string;
|
|
22
|
+
|
|
23
|
+
constructor(appId: string) {
|
|
24
|
+
this.appId = appId;
|
|
25
|
+
MoEngageLogger.debug(`${this.TAG} constructor() : initialised for appId=${appId}`);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async fetchExperiencesMeta(statuses: ExperienceStatus[]): Promise<ExperienceCampaignsMetadata> {
|
|
29
|
+
try {
|
|
30
|
+
const payload = PayloadBuilder.buildFetchExperiencesMetaPayload(this.appId, statuses);
|
|
31
|
+
MoEngageLogger.verbose(`${this.TAG} fetchExperiencesMeta() : ${payload}`);
|
|
32
|
+
const response = await MoEngagePersonalizeBridge.fetchExperiencesMeta(payload);
|
|
33
|
+
return Parser.parseExperiencesMetadata(response);
|
|
34
|
+
} catch (error) {
|
|
35
|
+
MoEngageLogger.error(`${this.TAG} fetchExperiencesMeta() : `, error);
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async fetchExperiences(
|
|
41
|
+
experienceKeys: string[],
|
|
42
|
+
attributes: Record<string, string>
|
|
43
|
+
): Promise<ExperienceCampaignsResult> {
|
|
44
|
+
try {
|
|
45
|
+
const payload = PayloadBuilder.buildFetchExperiencesPayload(this.appId, experienceKeys, attributes);
|
|
46
|
+
MoEngageLogger.verbose(`${this.TAG} fetchExperiences() : ${payload}`);
|
|
47
|
+
const response = await MoEngagePersonalizeBridge.fetchExperiences(payload);
|
|
48
|
+
return Parser.parseExperiencesResult(response);
|
|
49
|
+
} catch (error) {
|
|
50
|
+
MoEngageLogger.error(`${this.TAG} fetchExperiences() : `, error);
|
|
51
|
+
throw error;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
experiencesShown(campaigns: ExperienceCampaign[]): void {
|
|
56
|
+
try {
|
|
57
|
+
const payload = PayloadBuilder.buildExperiencesShownPayload(this.appId, campaigns);
|
|
58
|
+
MoEngageLogger.verbose(`${this.TAG} experiencesShown() : ${payload}`);
|
|
59
|
+
MoEngagePersonalizeBridge.experiencesShown(payload);
|
|
60
|
+
} catch (error) {
|
|
61
|
+
MoEngageLogger.error(`${this.TAG} experiencesShown() : `, error);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
experienceClicked(campaign: ExperienceCampaign): void {
|
|
66
|
+
try {
|
|
67
|
+
const payload = PayloadBuilder.buildExperienceClickedPayload(this.appId, campaign);
|
|
68
|
+
MoEngageLogger.verbose(`${this.TAG} experienceClicked() : ${payload}`);
|
|
69
|
+
MoEngagePersonalizeBridge.experienceClicked(payload);
|
|
70
|
+
} catch (error) {
|
|
71
|
+
MoEngageLogger.error(`${this.TAG} experienceClicked() : `, error);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
offeringsShown(offeringPayloads: Record<string, any>[]): void {
|
|
76
|
+
try {
|
|
77
|
+
const payload = PayloadBuilder.buildOfferingsShownPayload(this.appId, offeringPayloads);
|
|
78
|
+
MoEngageLogger.verbose(`${this.TAG} offeringsShown() : ${payload}`);
|
|
79
|
+
MoEngagePersonalizeBridge.offeringsShown(payload);
|
|
80
|
+
} catch (error) {
|
|
81
|
+
MoEngageLogger.error(`${this.TAG} offeringsShown() : `, error);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
offeringClicked(
|
|
86
|
+
campaign: ExperienceCampaign,
|
|
87
|
+
offeringPayload: Record<string, any>
|
|
88
|
+
): void {
|
|
89
|
+
try {
|
|
90
|
+
const payload = PayloadBuilder.buildOfferingClickedPayload(this.appId, campaign, offeringPayload);
|
|
91
|
+
MoEngageLogger.verbose(`${this.TAG} offeringClicked() : ${payload}`);
|
|
92
|
+
MoEngagePersonalizeBridge.offeringClicked(payload);
|
|
93
|
+
} catch (error) {
|
|
94
|
+
MoEngageLogger.error(`${this.TAG} offeringClicked() : `, error);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|