@adobe/react-native-aepmessaging 7.1.1 → 7.2.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/README.md +66 -2
- package/android/src/main/java/com/adobe/marketing/mobile/reactnative/messaging/RCTAEPMessagingConstants.java +19 -0
- package/android/src/main/java/com/adobe/marketing/mobile/reactnative/messaging/RCTAEPMessagingModule.java +151 -18
- package/android/src/main/java/com/adobe/marketing/mobile/reactnative/messaging/RCTAEPMessagingUtil.java +1 -1
- package/dist/Messaging.d.ts +17 -0
- package/dist/Messaging.js +27 -6
- package/dist/Messaging.js.map +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.js +11 -1
- package/dist/index.js.map +1 -1
- package/dist/models/ContentCard.d.ts +6 -1
- package/dist/models/ContentCard.js +9 -0
- package/dist/models/ContentCard.js.map +1 -1
- package/dist/models/HTMLProposition.d.ts +6 -2
- package/dist/models/HTMLProposition.js +9 -0
- package/dist/models/HTMLProposition.js.map +1 -1
- package/dist/models/JSONProposition.d.ts +12 -0
- package/dist/models/{JSONPropositionItem.js → JSONProposition.js} +10 -1
- package/dist/models/JSONProposition.js.map +1 -0
- package/dist/models/Message.d.ts +14 -0
- package/dist/models/Message.js +43 -0
- package/dist/models/Message.js.map +1 -1
- package/dist/models/MessagingProposition.d.ts +10 -3
- package/dist/models/MessagingProposition.js +45 -0
- package/dist/models/MessagingProposition.js.map +1 -1
- package/dist/models/MessagingPropositionItem.d.ts +3 -2
- package/dist/models/PropositionItem.d.ts +83 -0
- package/dist/models/PropositionItem.js +78 -0
- package/dist/models/PropositionItem.js.map +1 -0
- package/ios/src/RCTAEPMessaging.mm +13 -0
- package/ios/src/RCTAEPMessaging.swift +123 -6
- package/ios/src/RCTAEPMessagingConstants.swift +5 -1
- package/ios/src/RCTAEPMessagingDataBridge.swift +19 -0
- package/package.json +2 -2
- package/src/Messaging.ts +34 -12
- package/src/index.ts +13 -5
- package/src/models/ContentCard.ts +12 -1
- package/src/models/HTMLProposition.ts +15 -6
- package/src/models/{JSONPropositionItem.ts → JSONProposition.ts} +15 -6
- package/src/models/Message.ts +51 -1
- package/src/models/MessagingProposition.ts +45 -3
- package/src/models/MessagingPropositionItem.ts +6 -2
- package/src/models/PropositionItem.ts +135 -0
- package/tutorials/In-App Messaging.md +67 -0
- package/dist/models/JSONPropositionItem.d.ts +0 -8
- package/dist/models/JSONPropositionItem.js.map +0 -1
package/src/Messaging.ts
CHANGED
|
@@ -37,6 +37,7 @@ export interface NativeMessagingModule {
|
|
|
37
37
|
updatePropositionsForSurfaces: (surfaces: string[]) => void;
|
|
38
38
|
trackContentCardDisplay: (proposition: MessagingProposition, contentCard: ContentCard) => void;
|
|
39
39
|
trackContentCardInteraction: (proposition: MessagingProposition, contentCard: ContentCard) => void;
|
|
40
|
+
trackPropositionItem: (itemId: string, interaction: string | null, eventType: number, tokens: string[] | null) => void;
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
const RCTAEPMessaging: NativeModule & NativeMessagingModule =
|
|
@@ -92,15 +93,33 @@ class Messaging {
|
|
|
92
93
|
): Promise<Record<string, MessagingProposition[]>> {
|
|
93
94
|
return await RCTAEPMessaging.getPropositionsForSurfaces(surfaces);
|
|
94
95
|
}
|
|
95
|
-
|
|
96
|
+
/**
|
|
97
|
+
* @deprecated Use PropositionItem.track(...) instead.
|
|
98
|
+
*/
|
|
96
99
|
static trackContentCardDisplay(proposition: MessagingProposition, contentCard: ContentCard): void {
|
|
97
100
|
RCTAEPMessaging.trackContentCardDisplay(proposition, contentCard);
|
|
98
101
|
}
|
|
99
102
|
|
|
103
|
+
/**
|
|
104
|
+
* @deprecated Use PropositionItem.track(...) instead.
|
|
105
|
+
*/
|
|
100
106
|
static trackContentCardInteraction(proposition: MessagingProposition, contentCard: ContentCard): void {
|
|
101
107
|
RCTAEPMessaging.trackContentCardInteraction(proposition, contentCard);
|
|
102
108
|
}
|
|
103
109
|
|
|
110
|
+
/**
|
|
111
|
+
* Tracks interactions with a PropositionItem using the provided interaction and event type.
|
|
112
|
+
* This method is used internally by the PropositionItem.track() method.
|
|
113
|
+
*
|
|
114
|
+
* @param {string} itemId - The unique identifier of the PropositionItem
|
|
115
|
+
* @param {string | null} interaction - A custom string value to be recorded in the interaction
|
|
116
|
+
* @param {number} eventType - The MessagingEdgeEventType numeric value
|
|
117
|
+
* @param {string[] | null} tokens - Array containing the sub-item tokens for recording interaction
|
|
118
|
+
*/
|
|
119
|
+
static trackPropositionItem(itemId: string, interaction: string | null, eventType: number, tokens: string[] | null): void {
|
|
120
|
+
RCTAEPMessaging.trackPropositionItem(itemId, interaction, eventType, tokens);
|
|
121
|
+
}
|
|
122
|
+
|
|
104
123
|
/**
|
|
105
124
|
* Function to set the UI Message delegate to listen the Message lifecycle events.
|
|
106
125
|
* @returns A function to unsubscribe from all event listeners
|
|
@@ -110,31 +129,34 @@ class Messaging {
|
|
|
110
129
|
|
|
111
130
|
const eventEmitter = new NativeEventEmitter(RCTAEPMessaging);
|
|
112
131
|
|
|
113
|
-
eventEmitter.addListener('onShow', (message) =>
|
|
114
|
-
messagingDelegate?.onShow?.(message)
|
|
132
|
+
eventEmitter.addListener('onShow', (message: Message) =>
|
|
133
|
+
messagingDelegate?.onShow?.(new Message(message))
|
|
115
134
|
);
|
|
116
135
|
|
|
117
|
-
eventEmitter.addListener('onDismiss', (message) => {
|
|
118
|
-
|
|
136
|
+
eventEmitter.addListener('onDismiss', (message: Message) => {
|
|
137
|
+
const messageInstance = new Message(message);
|
|
138
|
+
messageInstance._clearJavascriptMessageHandlers();
|
|
139
|
+
messagingDelegate?.onDismiss?.(messageInstance);
|
|
119
140
|
});
|
|
120
141
|
|
|
121
|
-
eventEmitter.addListener('shouldShowMessage', (message) => {
|
|
142
|
+
eventEmitter.addListener('shouldShowMessage', (message: Message) => {
|
|
143
|
+
const messageInstance = new Message(message);
|
|
122
144
|
const shouldShowMessage =
|
|
123
|
-
messagingDelegate?.shouldShowMessage?.(
|
|
145
|
+
messagingDelegate?.shouldShowMessage?.(messageInstance) ?? true;
|
|
124
146
|
const shouldSaveMessage =
|
|
125
|
-
messagingDelegate?.shouldSaveMessage?.(
|
|
147
|
+
messagingDelegate?.shouldSaveMessage?.(messageInstance) ?? false;
|
|
126
148
|
RCTAEPMessaging.setMessageSettings(shouldShowMessage, shouldSaveMessage);
|
|
127
149
|
});
|
|
128
150
|
|
|
129
151
|
if (Platform.OS === 'ios') {
|
|
130
|
-
eventEmitter.addListener('urlLoaded', (event) =>
|
|
131
|
-
messagingDelegate?.urlLoaded?.(event.url, event.message)
|
|
152
|
+
eventEmitter.addListener('urlLoaded', (event: {url: string, message: Message}) =>
|
|
153
|
+
messagingDelegate?.urlLoaded?.(event.url, new Message(event.message))
|
|
132
154
|
);
|
|
133
155
|
}
|
|
134
156
|
|
|
135
157
|
if (Platform.OS === 'android') {
|
|
136
|
-
eventEmitter.addListener('onContentLoaded', (event) =>
|
|
137
|
-
messagingDelegate?.onContentLoaded?.(event.message)
|
|
158
|
+
eventEmitter.addListener('onContentLoaded', (event: {message: Message}) =>
|
|
159
|
+
messagingDelegate?.onContentLoaded?.(new Message(event.message))
|
|
138
160
|
);
|
|
139
161
|
}
|
|
140
162
|
|
package/src/index.ts
CHANGED
|
@@ -11,25 +11,27 @@ governing permissions and limitations under the License.
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import Messaging from './Messaging';
|
|
14
|
-
import { ContentCard } from './models/ContentCard';
|
|
15
|
-
|
|
14
|
+
import { ContentCard, ContentCardData } from './models/ContentCard';
|
|
15
|
+
|
|
16
16
|
import { InAppMessage } from './models/InAppMessage';
|
|
17
|
-
import {
|
|
17
|
+
import { HTMLProposition, HTMLPropositionData } from './models/HTMLProposition';
|
|
18
|
+
import { JSONPropositionItem, JSONPropositionData } from './models/JSONProposition';
|
|
19
|
+
|
|
18
20
|
import Message from './models/Message';
|
|
19
21
|
import { MessagingDelegate } from './models/MessagingDelegate';
|
|
20
22
|
import MessagingEdgeEventType from './models/MessagingEdgeEventType';
|
|
21
23
|
import { MessagingProposition } from './models/MessagingProposition';
|
|
22
24
|
import { MessagingPropositionItem } from './models/MessagingPropositionItem';
|
|
23
25
|
import { PersonalizationSchema } from './models/PersonalizationSchema';
|
|
26
|
+
import { PropositionItem, PropositionItemData } from './models/PropositionItem';
|
|
24
27
|
import { Activity, Characteristics } from './models/ScopeDetails';
|
|
25
28
|
|
|
26
29
|
export {
|
|
27
30
|
Activity,
|
|
28
31
|
Characteristics,
|
|
29
32
|
ContentCard,
|
|
30
|
-
|
|
33
|
+
ContentCardData,
|
|
31
34
|
InAppMessage,
|
|
32
|
-
JSONPropositionItem,
|
|
33
35
|
Messaging,
|
|
34
36
|
Message,
|
|
35
37
|
MessagingDelegate,
|
|
@@ -37,4 +39,10 @@ export {
|
|
|
37
39
|
MessagingProposition,
|
|
38
40
|
MessagingPropositionItem,
|
|
39
41
|
PersonalizationSchema,
|
|
42
|
+
PropositionItem,
|
|
43
|
+
PropositionItemData,
|
|
44
|
+
HTMLProposition,
|
|
45
|
+
HTMLPropositionData,
|
|
46
|
+
JSONPropositionItem,
|
|
47
|
+
JSONPropositionData,
|
|
40
48
|
};
|
|
@@ -11,11 +11,12 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import { PersonalizationSchema } from './PersonalizationSchema';
|
|
14
|
+
import { PropositionItem, PropositionItemData } from './PropositionItem';
|
|
14
15
|
|
|
15
16
|
type ContentCardTemplate = 'SmallImage';
|
|
16
17
|
type DismissButtonStyle = 'circle' | 'none' | 'simple';
|
|
17
18
|
|
|
18
|
-
export interface
|
|
19
|
+
export interface ContentCardData extends PropositionItemData {
|
|
19
20
|
id: string;
|
|
20
21
|
data: {
|
|
21
22
|
contentType: 'application/json';
|
|
@@ -45,3 +46,13 @@ export interface ContentCard {
|
|
|
45
46
|
};
|
|
46
47
|
schema: PersonalizationSchema.CONTENT_CARD;
|
|
47
48
|
}
|
|
49
|
+
|
|
50
|
+
export class ContentCard extends PropositionItem {
|
|
51
|
+
declare data: ContentCardData['data']; // Override data type for better typing
|
|
52
|
+
|
|
53
|
+
constructor(contentCardData: ContentCardData) {
|
|
54
|
+
super(contentCardData);
|
|
55
|
+
this.data = contentCardData.data;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
}
|
|
@@ -11,11 +11,20 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import { PersonalizationSchema } from './PersonalizationSchema';
|
|
14
|
+
import { PropositionItem, PropositionItemData } from './PropositionItem';
|
|
14
15
|
|
|
15
|
-
export interface
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
schema: PersonalizationSchema.HTML_CONTENT;
|
|
16
|
+
export interface HTMLPropositionData extends PropositionItemData {
|
|
17
|
+
data: {
|
|
18
|
+
content: string;
|
|
19
|
+
};
|
|
20
|
+
schema: PersonalizationSchema.HTML_CONTENT;
|
|
21
21
|
}
|
|
22
|
+
|
|
23
|
+
export class HTMLProposition extends PropositionItem {
|
|
24
|
+
declare data: HTMLPropositionData['data'];
|
|
25
|
+
|
|
26
|
+
constructor(htmlData: HTMLPropositionData) {
|
|
27
|
+
super(htmlData);
|
|
28
|
+
this.data = htmlData.data;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -11,11 +11,20 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import { PersonalizationSchema } from './PersonalizationSchema';
|
|
14
|
+
import { PropositionItem, PropositionItemData } from './PropositionItem';
|
|
14
15
|
|
|
15
|
-
export interface
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
schema: PersonalizationSchema.JSON_CONTENT;
|
|
16
|
+
export interface JSONPropositionData extends PropositionItemData {
|
|
17
|
+
data: {
|
|
18
|
+
content: any;
|
|
19
|
+
};
|
|
20
|
+
schema: PersonalizationSchema.JSON_CONTENT;
|
|
21
21
|
}
|
|
22
|
+
|
|
23
|
+
export class JSONPropositionItem extends PropositionItem {
|
|
24
|
+
declare data: JSONPropositionData['data'];
|
|
25
|
+
|
|
26
|
+
constructor(jsonData: JSONPropositionData) {
|
|
27
|
+
super(jsonData);
|
|
28
|
+
this.data = jsonData.data;
|
|
29
|
+
}
|
|
30
|
+
}
|
package/src/models/Message.ts
CHANGED
|
@@ -10,9 +10,23 @@ OF ANY KIND, either express or implied. See the License for the specific languag
|
|
|
10
10
|
governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import { NativeModules } from 'react-native';
|
|
13
|
+
import { NativeEventEmitter, NativeModules } from 'react-native';
|
|
14
|
+
|
|
14
15
|
const RCTAEPMessaging = NativeModules.AEPMessaging;
|
|
15
16
|
|
|
17
|
+
// Registery to store inAppMessage callbacks for each message in Message.handleJavascriptMessage
|
|
18
|
+
// Record - {messageId : {handlerName : callback}}
|
|
19
|
+
const jsMessageHandlers: Record<string, Record<string, (content: string) => void>> = {};
|
|
20
|
+
const handleJSMessageEventEmitter = new NativeEventEmitter(RCTAEPMessaging);
|
|
21
|
+
|
|
22
|
+
// invokes the callback registered in Message.handleJavascriptMessage with the content received from the inAppMessage webview
|
|
23
|
+
handleJSMessageEventEmitter.addListener('onJavascriptMessage', (event) => {
|
|
24
|
+
const {messageId, handlerName, content} = event;
|
|
25
|
+
if (jsMessageHandlers[messageId] && jsMessageHandlers[messageId][handlerName]) {
|
|
26
|
+
jsMessageHandlers[messageId][handlerName](content);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
16
30
|
class Message {
|
|
17
31
|
id: string;
|
|
18
32
|
autoTrack: boolean;
|
|
@@ -67,6 +81,42 @@ class Message {
|
|
|
67
81
|
clear() {
|
|
68
82
|
RCTAEPMessaging.clear(this.id);
|
|
69
83
|
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Adds a handler for named JavaScript messages sent from the message's WebView.
|
|
87
|
+
* The parameter passed to handler will contain the body of the message passed from the WebView's JavaScript.
|
|
88
|
+
* @param {string} handlerName: The name of the message that should be handled by the handler
|
|
89
|
+
* @param {function} handler: The method or closure to be called with the body of the message created in the Message's JavaScript
|
|
90
|
+
*/
|
|
91
|
+
handleJavascriptMessage(handlerName: string, handler: (content: string) => void) {
|
|
92
|
+
// Validate parameters
|
|
93
|
+
if (!handlerName) {
|
|
94
|
+
console.warn('[AEP Messaging] handleJavascriptMessage: handlerName is required');
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (typeof handler !== 'function') {
|
|
99
|
+
console.warn('[AEP Messaging] handleJavascriptMessage: handler must be a function');
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// cache the callback
|
|
104
|
+
if (!jsMessageHandlers[this.id]) {
|
|
105
|
+
jsMessageHandlers[this.id] = {};
|
|
106
|
+
}
|
|
107
|
+
jsMessageHandlers[this.id][handlerName] = handler;
|
|
108
|
+
RCTAEPMessaging.handleJavascriptMessage(this.id, handlerName);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* @internal - For internal use only.
|
|
113
|
+
* Clears all the javascript message handlers for the message.
|
|
114
|
+
* This function must be called if the callbacks registered in handleJavascriptMessage are no longer needed.
|
|
115
|
+
* Failure to call this function may lead to memory leaks.
|
|
116
|
+
*/
|
|
117
|
+
_clearJavascriptMessageHandlers() {
|
|
118
|
+
delete jsMessageHandlers[this.id];
|
|
119
|
+
}
|
|
70
120
|
}
|
|
71
121
|
|
|
72
122
|
export default Message;
|
|
@@ -10,12 +10,54 @@
|
|
|
10
10
|
language governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import { MessagingPropositionItem } from './MessagingPropositionItem';
|
|
14
13
|
import { ScopeDetails } from './ScopeDetails';
|
|
14
|
+
import { PersonalizationSchema } from './PersonalizationSchema';
|
|
15
|
+
import { ContentCard } from './ContentCard';
|
|
16
|
+
import { HTMLProposition } from './HTMLProposition';
|
|
17
|
+
import { JSONPropositionItem } from './JSONProposition';
|
|
18
|
+
import { PropositionItem } from './PropositionItem';
|
|
15
19
|
|
|
16
|
-
export
|
|
20
|
+
export class MessageProposition {
|
|
17
21
|
id: string;
|
|
18
22
|
scope: string;
|
|
19
23
|
scopeDetails: ScopeDetails;
|
|
20
|
-
items:
|
|
24
|
+
items: PropositionItem[];
|
|
25
|
+
|
|
26
|
+
constructor(raw: { id: string; scope: string; scopeDetails: ScopeDetails; items?: any[] }) {
|
|
27
|
+
this.id = raw?.id ?? '';
|
|
28
|
+
this.scope = raw?.scope ?? '';
|
|
29
|
+
this.scopeDetails = (raw?.scopeDetails as ScopeDetails) ?? ({} as ScopeDetails);
|
|
30
|
+
|
|
31
|
+
// Mirror activity.id into activity.activityID for convenience
|
|
32
|
+
const activityIdFromScope = this.scopeDetails?.activity?.id ?? '';
|
|
33
|
+
if (this.scopeDetails?.activity) {
|
|
34
|
+
(this.scopeDetails.activity as any).activityID = activityIdFromScope;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const rawItems = Array.isArray(raw?.items) ? raw.items : [];
|
|
38
|
+
this.items = rawItems.map((itemData: any) => {
|
|
39
|
+
const activityId = this.scopeDetails?.activity?.id ?? '';
|
|
40
|
+
let instance: any;
|
|
41
|
+
switch (itemData?.schema) {
|
|
42
|
+
case PersonalizationSchema.CONTENT_CARD:
|
|
43
|
+
instance = new ContentCard(itemData as any);
|
|
44
|
+
(instance as any).activityID = activityId;
|
|
45
|
+
return instance;
|
|
46
|
+
case PersonalizationSchema.HTML_CONTENT:
|
|
47
|
+
instance = new HTMLProposition(itemData as any);
|
|
48
|
+
(instance as any).activityID = activityId;
|
|
49
|
+
return instance;
|
|
50
|
+
case PersonalizationSchema.JSON_CONTENT:
|
|
51
|
+
instance = new JSONPropositionItem(itemData as any);
|
|
52
|
+
(instance as any).activityID = activityId;
|
|
53
|
+
return instance;
|
|
54
|
+
default:
|
|
55
|
+
instance = new PropositionItem(itemData as any);
|
|
56
|
+
(instance as any).activityID = activityId;
|
|
57
|
+
return instance;
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
}
|
|
21
61
|
}
|
|
62
|
+
|
|
63
|
+
export { MessageProposition as MessagingProposition };
|
|
@@ -12,11 +12,15 @@
|
|
|
12
12
|
|
|
13
13
|
import { ContentCard } from './ContentCard';
|
|
14
14
|
import { HTMLProposition } from './HTMLProposition';
|
|
15
|
-
import { JSONPropositionItem } from './
|
|
15
|
+
import { JSONPropositionItem } from './JSONProposition';
|
|
16
16
|
import { InAppMessage } from './InAppMessage';
|
|
17
|
+
import { PropositionItem } from './PropositionItem';
|
|
17
18
|
|
|
19
|
+
// Union type for all possible proposition item types
|
|
20
|
+
// All items now extend PropositionItem and have unified tracking capabilities
|
|
18
21
|
export type MessagingPropositionItem =
|
|
19
22
|
| ContentCard
|
|
20
23
|
| HTMLProposition
|
|
21
24
|
| InAppMessage
|
|
22
|
-
| JSONPropositionItem
|
|
25
|
+
| JSONPropositionItem
|
|
26
|
+
| PropositionItem;
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2025 Adobe. All rights reserved.
|
|
3
|
+
This file is licensed to you under the Apache License, Version 2.0 (the
|
|
4
|
+
"License"); you may not use this file except in compliance with the License.
|
|
5
|
+
You may obtain a copy of the License at
|
|
6
|
+
http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
|
|
7
|
+
or agreed to in writing, software distributed under the License is
|
|
8
|
+
distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF
|
|
9
|
+
ANY KIND, either express or implied. See the License for the specific
|
|
10
|
+
language governing permissions and limitations under the License.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { NativeModules } from 'react-native';
|
|
14
|
+
import { PersonalizationSchema } from './PersonalizationSchema';
|
|
15
|
+
import MessagingEdgeEventType from './MessagingEdgeEventType';
|
|
16
|
+
|
|
17
|
+
const RCTAEPMessaging = NativeModules.AEPMessaging;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Base PropositionItem interface that all proposition items implement
|
|
21
|
+
*/
|
|
22
|
+
export interface PropositionItemData {
|
|
23
|
+
id: string;
|
|
24
|
+
uuid: string;
|
|
25
|
+
schema: PersonalizationSchema;
|
|
26
|
+
activityID: string;
|
|
27
|
+
data: {
|
|
28
|
+
[key: string]: any;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* A PropositionItem represents a personalization JSON object returned by Konductor.
|
|
34
|
+
* This is the base class that provides tracking functionality for all proposition items
|
|
35
|
+
* including ContentCards, InApp messages, and code-based experiences.
|
|
36
|
+
*
|
|
37
|
+
* This mirrors the native Android PropositionItem class functionality.
|
|
38
|
+
*/
|
|
39
|
+
export class PropositionItem {
|
|
40
|
+
id: string;
|
|
41
|
+
uuid: string;
|
|
42
|
+
activityID: string;
|
|
43
|
+
schema: PersonalizationSchema;
|
|
44
|
+
data: { [key: string]: any };
|
|
45
|
+
|
|
46
|
+
constructor(propositionItemData: PropositionItemData) {
|
|
47
|
+
this.id = propositionItemData.id;
|
|
48
|
+
this.schema = propositionItemData.schema;
|
|
49
|
+
this.data = propositionItemData.data;
|
|
50
|
+
this.uuid = propositionItemData.uuid;
|
|
51
|
+
this.activityID = propositionItemData.activityID;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Gets the PropositionItem identifier.
|
|
56
|
+
*
|
|
57
|
+
* @returns {string} The PropositionItem identifier
|
|
58
|
+
*/
|
|
59
|
+
getItemId(): string {
|
|
60
|
+
return this.id;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Gets the PropositionItem content schema.
|
|
65
|
+
*
|
|
66
|
+
* @returns {PersonalizationSchema} The PropositionItem content schema
|
|
67
|
+
*/
|
|
68
|
+
getSchema(): PersonalizationSchema {
|
|
69
|
+
return this.schema;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Gets the PropositionItem data.
|
|
74
|
+
*
|
|
75
|
+
* @returns {object} The PropositionItem data
|
|
76
|
+
*/
|
|
77
|
+
getItemData(): { [key: string]: any } {
|
|
78
|
+
return this.data;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Tracks interaction with this proposition item.
|
|
83
|
+
* This is the core tracking method that all proposition items use.
|
|
84
|
+
*
|
|
85
|
+
* @param {MessagingEdgeEventType} eventType - The MessagingEdgeEventType specifying event type for the interaction
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* propositionItem.track(MessagingEdgeEventType.DISPLAY);
|
|
89
|
+
*/
|
|
90
|
+
track(eventType: MessagingEdgeEventType): void;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Tracks interaction with this proposition item.
|
|
94
|
+
*
|
|
95
|
+
* @param {string | null} interaction - String describing the interaction
|
|
96
|
+
* @param {MessagingEdgeEventType} eventType - The MessagingEdgeEventType specifying event type for the interaction
|
|
97
|
+
* @param {string[] | null} tokens - Array containing the sub-item tokens for recording interaction
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* // Track display
|
|
101
|
+
* propositionItem.track(null, MessagingEdgeEventType.DISPLAY, null);
|
|
102
|
+
*
|
|
103
|
+
* // Track interaction
|
|
104
|
+
* propositionItem.track("button_clicked", MessagingEdgeEventType.INTERACT, null);
|
|
105
|
+
*
|
|
106
|
+
* // Track with tokens
|
|
107
|
+
* propositionItem.track("click", MessagingEdgeEventType.INTERACT, ["token1", "token2"]);
|
|
108
|
+
*/
|
|
109
|
+
track(interaction: string | null, eventType: MessagingEdgeEventType, tokens: string[] | null): void;
|
|
110
|
+
|
|
111
|
+
// Implementation
|
|
112
|
+
track(
|
|
113
|
+
interactionOrEventType: string | null | MessagingEdgeEventType,
|
|
114
|
+
eventType?: MessagingEdgeEventType,
|
|
115
|
+
tokens?: string[] | null
|
|
116
|
+
): void {
|
|
117
|
+
// Handle overloaded method signatures
|
|
118
|
+
if (typeof interactionOrEventType === 'number' && eventType === undefined) {
|
|
119
|
+
// First overload: track(eventType)
|
|
120
|
+
this.trackWithDetails(null, interactionOrEventType, null);
|
|
121
|
+
} else if (typeof interactionOrEventType === 'string' || interactionOrEventType === null) {
|
|
122
|
+
// Second overload: track(interaction, eventType, tokens)
|
|
123
|
+
this.trackWithDetails(interactionOrEventType, eventType!, tokens || null);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Internal method that performs the actual tracking
|
|
129
|
+
*/
|
|
130
|
+
private trackWithDetails(interaction: string | null, eventType: MessagingEdgeEventType, tokens: string[] | null): void {
|
|
131
|
+
const nativeIdentifier = this.activityID ?? null;
|
|
132
|
+
RCTAEPMessaging.trackPropositionItem(nativeIdentifier, interaction, eventType, tokens);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Native handling of JavaScript events
|
|
2
|
+
|
|
3
|
+
You can handle events from in-app message interactions natively within your application by completing the following steps:
|
|
4
|
+
- [Implement and assign a `Messaging Delegate`](#implement-and-assign-a-messaging-delegate)
|
|
5
|
+
- [Register a JavaScript handler for your In-App Message](#register-a-javascript-handler-for-your-in-app-message)
|
|
6
|
+
- [Post the JavaScript message from your In-App Message](#post-the-javascript-message-from-your-in-app-message)
|
|
7
|
+
|
|
8
|
+
## Implement and assign a `Messaging Delegate`
|
|
9
|
+
|
|
10
|
+
To register a JavaScript event handler with a Message object, you will first need to implement and set a MessagingDelegate.
|
|
11
|
+
Please read the [documentation](../README.md/#programmatically-control-the-display-of-in-app-messages) for more detailed instructions on implementing and using a MessagingDelegate.
|
|
12
|
+
|
|
13
|
+
## Register a JavaScript handler for your In-App Message
|
|
14
|
+
|
|
15
|
+
In the `onShow` function of `MessagingDelegate`, call `handleJavascriptMessage(handlerName: string, handler: (content: string) => void)` to register your handler.
|
|
16
|
+
|
|
17
|
+
The name of the message you intend to pass from the JavaScript side should be specified in the first parameter.
|
|
18
|
+
|
|
19
|
+
### Example
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
Messaging.setMessagingDelegate({
|
|
23
|
+
onShow: msg => {
|
|
24
|
+
console.log('show', msg);
|
|
25
|
+
msg.handleJavascriptMessage(
|
|
26
|
+
'myInappCallback',
|
|
27
|
+
(content) => {
|
|
28
|
+
console.log('Received webview content:', content);
|
|
29
|
+
}
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Post the JavaScript message from your In-App Message
|
|
36
|
+
|
|
37
|
+
Now that the in-app message has been displayed, the final step is to post the JavaScript message.
|
|
38
|
+
|
|
39
|
+
Continuing from the previous example, the developer is going to post the `myInappCallback` message from their HTML, which will in turn call the handler previously configured:
|
|
40
|
+
|
|
41
|
+
```html
|
|
42
|
+
<html>
|
|
43
|
+
<head>
|
|
44
|
+
<script type="text/javascript">
|
|
45
|
+
function callNative(action) {
|
|
46
|
+
try {
|
|
47
|
+
// the name of the message handler is the same name that must be registered in react native code.
|
|
48
|
+
// in this case the message name is "myInappCallback"
|
|
49
|
+
webkit.messageHandlers.myInappCallback.postMessage(action);
|
|
50
|
+
} catch(err) {
|
|
51
|
+
console.log('The native context does not exist yet'); }
|
|
52
|
+
}
|
|
53
|
+
</script>
|
|
54
|
+
</head>
|
|
55
|
+
<body>
|
|
56
|
+
<button onclick="callNative('callbacks are cool!')">Native callback!</button>
|
|
57
|
+
</body>
|
|
58
|
+
</html>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Note: (The above HTML is not representative of a valid in-app message, and is intended only to demonstrate how to post the JavaScript message).
|
|
62
|
+
|
|
63
|
+
When the user clicks the button inside of this in-app message, the handler configured in the previous step will be called. The handler will send an Experience Event tracking the interaction, and print the following message to the console:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
JavaScript body passed to react native callback: callbacks are cool!
|
|
67
|
+
```
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"JSONPropositionItem.js","sourceRoot":"","sources":["../../src/models/JSONPropositionItem.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;EAUE"}
|