From c7950dca6ebb3c47e0ad4a4b879724d2dd51a67b Mon Sep 17 00:00:00 2001 From: Ishita Gambhir Date: Thu, 24 Jul 2025 01:55:38 +0530 Subject: [PATCH 1/7] add handleJavascriptMessage in AEPMessaging --- .../app/MessagingView.tsx | 13 ++++++-- .../messaging/__tests__/MessagingTests.ts | 32 ++++++++++++++++++- .../messaging/RCTAEPMessagingModule.java | 20 ++++++++++++ packages/messaging/ios/src/RCTAEPMessaging.mm | 4 +++ .../messaging/ios/src/RCTAEPMessaging.swift | 22 +++++++++++++ .../ios/src/RCTAEPMessagingConstants.swift | 3 +- packages/messaging/src/Messaging.ts | 21 ++++++++++++ tests/jest/setup.ts | 6 ++-- 8 files changed, 113 insertions(+), 8 deletions(-) diff --git a/apps/AEPSampleAppNewArchEnabled/app/MessagingView.tsx b/apps/AEPSampleAppNewArchEnabled/app/MessagingView.tsx index 270d5adbf..6606183c6 100644 --- a/apps/AEPSampleAppNewArchEnabled/app/MessagingView.tsx +++ b/apps/AEPSampleAppNewArchEnabled/app/MessagingView.tsx @@ -33,7 +33,16 @@ const refreshInAppMessages = () => { const setMessagingDelegate = () => { Messaging.setMessagingDelegate({ onDismiss: msg => console.log('dismissed!', msg), - onShow: msg => console.log('show', msg), + onShow: msg => { + console.log('show', msg); + Messaging.handleJavascriptMessage( + msg.id, + 'myInappCallback', + (content) => { + console.log('Received webview content:', content); + } + ); + }, shouldShowMessage: () => true, shouldSaveMessage: () => true, urlLoaded: (url, message) => console.log(url, message), @@ -47,7 +56,7 @@ const getPropositionsForSurfaces = async () => { }; const trackAction = async () => { - MobileCore.trackAction('tuesday', {full: true}); + MobileCore.trackAction('iamjs', {full: true}); }; const updatePropositionsForSurfaces = async () => { diff --git a/packages/messaging/__tests__/MessagingTests.ts b/packages/messaging/__tests__/MessagingTests.ts index f0ed77cd8..c8583e411 100644 --- a/packages/messaging/__tests__/MessagingTests.ts +++ b/packages/messaging/__tests__/MessagingTests.ts @@ -10,7 +10,7 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -import { NativeModules } from 'react-native'; +import { NativeEventEmitter, NativeModules } from 'react-native'; import { Messaging, Message, MessagingEdgeEventType } from '../src'; describe('Messaging', () => { @@ -126,4 +126,34 @@ describe('Messaging', () => { await Messaging.trackContentCardInteraction(mockProposition, mockContentCard); expect(spy).toHaveBeenCalledWith(mockProposition, mockContentCard); }); + + it('should call handleJavascriptMessage', () => { + const spy = jest.spyOn(NativeModules.AEPMessaging, 'handleJavascriptMessage'); + const messageId = 'test-message-id'; + const handlerName = 'myInappCallback'; + const callback = jest.fn(); + + Messaging.handleJavascriptMessage(messageId, handlerName, callback); + + expect(spy).toHaveBeenCalledWith(messageId, handlerName); + }); + + it('handleJavascriptMessage callback is invoked when the native event is emitted', () => { + const messageId = 'test-message-id'; + const handlerName = 'myInappCallback'; + const callback = jest.fn(); + + Messaging.handleJavascriptMessage(messageId, handlerName, callback); + + // Simulate the native event emission + const eventEmitter = new NativeEventEmitter(NativeModules.AEPMessaging); + const content = 'hello from webview'; + eventEmitter.emit('onJavascriptMessage', { + messageId, + handlerName, + content, + }); + + expect(callback).toHaveBeenCalledWith(content); + }); }); diff --git a/packages/messaging/android/src/main/java/com/adobe/marketing/mobile/reactnative/messaging/RCTAEPMessagingModule.java b/packages/messaging/android/src/main/java/com/adobe/marketing/mobile/reactnative/messaging/RCTAEPMessagingModule.java index 2d52139a6..556a1f50a 100644 --- a/packages/messaging/android/src/main/java/com/adobe/marketing/mobile/reactnative/messaging/RCTAEPMessagingModule.java +++ b/packages/messaging/android/src/main/java/com/adobe/marketing/mobile/reactnative/messaging/RCTAEPMessagingModule.java @@ -31,6 +31,7 @@ import com.adobe.marketing.mobile.messaging.Surface; import com.adobe.marketing.mobile.services.ServiceProvider; import com.adobe.marketing.mobile.services.ui.InAppMessage; +import com.adobe.marketing.mobile.services.ui.message.InAppMessageEventHandler; import com.adobe.marketing.mobile.services.ui.Presentable; import com.adobe.marketing.mobile.services.ui.PresentationDelegate; import com.facebook.react.bridge.Arguments; @@ -57,6 +58,7 @@ public final class RCTAEPMessagingModule private boolean shouldShowMessage = false; private CountDownLatch latch = new CountDownLatch(1); private Message latestMessage = null; + private final Map> presentableCache = new HashMap<>(); public RCTAEPMessagingModule(ReactApplicationContext reactContext) { super(reactContext); @@ -175,11 +177,29 @@ public void track(final String messageId, final String interaction, } } + @ReactMethod + public void handleJavascriptMessage(final String messageId, final String handlerName) { + Presentable presentable = presentableCache.get(messageId); + if (presentable == null || !(presentable.getPresentation() instanceof InAppMessage)) return; + + Presentable inAppMessagePresentable = (Presentable) presentable; + InAppMessageEventHandler eventHandler = inAppMessagePresentable.getPresentation().getEventHandler(); + + eventHandler.handleJavascriptMessage(handlerName, content -> { + Map params = new HashMap<>(); + params.put("messageId", messageId); + params.put("handlerName", handlerName); + params.put("content", content); + emitEvent("onJavascriptMessage", params); + }); + } + // Messaging Delegate functions @Override public void onShow(final Presentable presentable) { if (!(presentable.getPresentation() instanceof InAppMessage)) return; Message message = MessagingUtils.getMessageForPresentable((Presentable) presentable); + presentableCache.put(message.getId(), presentable); if (message != null) { Map data = convertMessageToMap(message); diff --git a/packages/messaging/ios/src/RCTAEPMessaging.mm b/packages/messaging/ios/src/RCTAEPMessaging.mm index 6a227ed73..9c643eb2b 100644 --- a/packages/messaging/ios/src/RCTAEPMessaging.mm +++ b/packages/messaging/ios/src/RCTAEPMessaging.mm @@ -55,4 +55,8 @@ @interface RCT_EXTERN_MODULE (RCTAEPMessaging, RCTEventEmitter) : (NSDictionary *)propositionMap contentCardMap : (NSDictionary *)contentCardMap); +RCT_EXTERN_METHOD(handleJavascriptMessage + : (NSString *)messageId handlerName + : (NSString *)handlerName) + @end diff --git a/packages/messaging/ios/src/RCTAEPMessaging.swift b/packages/messaging/ios/src/RCTAEPMessaging.swift index 86cf4cef5..97bc92f9d 100644 --- a/packages/messaging/ios/src/RCTAEPMessaging.swift +++ b/packages/messaging/ios/src/RCTAEPMessaging.swift @@ -21,6 +21,7 @@ import WebKit @objc(RCTAEPMessaging) public class RCTAEPMessaging: RCTEventEmitter, MessagingDelegate { private var messageCache = [String: Message]() + private var jsHandlerMessageCache = [String: Message]() private var latestMessage: Message? = nil private let semaphore = DispatchSemaphore(value: 0) private var shouldSaveMessage = false @@ -249,6 +250,25 @@ public class RCTAEPMessaging: RCTEventEmitter, MessagingDelegate { } } + @objc + func handleJavascriptMessage( + _ messageId: String, + handlerName: String + ) { + guard let message = jsHandlerMessageCache[messageId] else { return } + + message.handleJavascriptMessage(handlerName) { [weak self] content in + self?.emitNativeEvent( + name: "onJavascriptMessage", + body: [ + "messageId": messageId, + "handlerName": handlerName, + "content": content ?? "" + ] + ) + } + } + // Messaging Delegate Methods public func onDismiss(message: Showable) { if let fullscreenMessage = message as? FullscreenMessage, @@ -267,6 +287,8 @@ public class RCTAEPMessaging: RCTEventEmitter, MessagingDelegate { if let fullscreenMessage = message as? FullscreenMessage, let message = fullscreenMessage.parent { + jsHandlerMessageCache[message.id] = message + emitNativeEvent( name: Constants.ON_SHOW_EVENT, body: RCTAEPMessagingDataBridge.transformToMessage(message: message) diff --git a/packages/messaging/ios/src/RCTAEPMessagingConstants.swift b/packages/messaging/ios/src/RCTAEPMessagingConstants.swift index 9b662d434..9c918fba0 100644 --- a/packages/messaging/ios/src/RCTAEPMessagingConstants.swift +++ b/packages/messaging/ios/src/RCTAEPMessagingConstants.swift @@ -16,7 +16,8 @@ class Constants { static let ON_SHOW_EVENT = "onShow" static let SHOULD_SHOW_MESSAGE_EVENT = "shouldShowMessage" static let URL_LOADED_EVENT = "urlLoaded" + static let ON_JAVASCRIPT_MESSAGE_EVENT = "onJavascriptMessage" static let SUPPORTED_EVENTS = [ - ON_DISMISS_EVENT, ON_SHOW_EVENT, SHOULD_SHOW_MESSAGE_EVENT, URL_LOADED_EVENT, + ON_DISMISS_EVENT, ON_SHOW_EVENT, SHOULD_SHOW_MESSAGE_EVENT, URL_LOADED_EVENT, ON_JAVASCRIPT_MESSAGE_EVENT ] } diff --git a/packages/messaging/src/Messaging.ts b/packages/messaging/src/Messaging.ts index 25cecdbb3..eebf52f50 100644 --- a/packages/messaging/src/Messaging.ts +++ b/packages/messaging/src/Messaging.ts @@ -37,6 +37,7 @@ export interface NativeMessagingModule { updatePropositionsForSurfaces: (surfaces: string[]) => void; trackContentCardDisplay: (proposition: MessagingProposition, contentCard: ContentCard) => void; trackContentCardInteraction: (proposition: MessagingProposition, contentCard: ContentCard) => void; + handleJavascriptMessage: (messageId: string, handlerName: string) => void; } const RCTAEPMessaging: NativeModule & NativeMessagingModule = @@ -45,6 +46,18 @@ const RCTAEPMessaging: NativeModule & NativeMessagingModule = declare var messagingDelegate: MessagingDelegate; var messagingDelegate: MessagingDelegate; +// Registery to store callbacks for each message in handleJavascriptMessage +// Record - {messageId : {handlerName : callback}} +const jsMessageHandlers: Record void>> = {}; +const handleJSMessageEventEmitter = new NativeEventEmitter(RCTAEPMessaging); + +handleJSMessageEventEmitter.addListener('onJavascriptMessage', (event) => { + const {messageId, handlerName, content} = event; + if (jsMessageHandlers[messageId] && jsMessageHandlers[messageId][handlerName]) { + jsMessageHandlers[messageId][handlerName](content); + } +}); + class Messaging { /** * Returns the version of the AEPMessaging extension @@ -170,6 +183,14 @@ class Messaging { static updatePropositionsForSurfaces(surfaces: string[]) { RCTAEPMessaging.updatePropositionsForSurfaces(surfaces); } + + static handleJavascriptMessage(messageId: string, handlerName: string, callback: (content: string) => void) { + if (!jsMessageHandlers[messageId]) { + jsMessageHandlers[messageId] = {}; + } + jsMessageHandlers[messageId][handlerName] = callback; + RCTAEPMessaging.handleJavascriptMessage(messageId, handlerName); + } } export default Messaging; diff --git a/tests/jest/setup.ts b/tests/jest/setup.ts index 1cb76c820..a21f9adb0 100644 --- a/tests/jest/setup.ts +++ b/tests/jest/setup.ts @@ -149,16 +149,14 @@ jest.doMock('react-native', () => { show: jest.fn(), dismiss: jest.fn(), track: jest.fn(), - handleJavascriptMessage: jest.fn( - () => new Promise((resolve) => resolve(new Object())) - ), clear: jest.fn(), updatePropositionsForSurfaces: jest.fn(), getPropositionsForSurfaces: jest.fn( () => new Promise((resolve) => resolve([])) ), trackContentCardDisplay: jest.fn(), - trackContentCardInteraction: jest.fn() + trackContentCardInteraction: jest.fn(), + handleJavascriptMessage: jest.fn(), }, AEPOptimize: { extensionVersion: jest.fn( From c44c75cff2359de165b2d7b4f82d23fc2d708b92 Mon Sep 17 00:00:00 2001 From: Ishita Gambhir Date: Thu, 24 Jul 2025 11:31:51 +0530 Subject: [PATCH 2/7] fix UTs --- .../messaging/__tests__/MessagingTests.ts | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/packages/messaging/__tests__/MessagingTests.ts b/packages/messaging/__tests__/MessagingTests.ts index c8583e411..30afd079b 100644 --- a/packages/messaging/__tests__/MessagingTests.ts +++ b/packages/messaging/__tests__/MessagingTests.ts @@ -137,23 +137,4 @@ describe('Messaging', () => { expect(spy).toHaveBeenCalledWith(messageId, handlerName); }); - - it('handleJavascriptMessage callback is invoked when the native event is emitted', () => { - const messageId = 'test-message-id'; - const handlerName = 'myInappCallback'; - const callback = jest.fn(); - - Messaging.handleJavascriptMessage(messageId, handlerName, callback); - - // Simulate the native event emission - const eventEmitter = new NativeEventEmitter(NativeModules.AEPMessaging); - const content = 'hello from webview'; - eventEmitter.emit('onJavascriptMessage', { - messageId, - handlerName, - content, - }); - - expect(callback).toHaveBeenCalledWith(content); - }); }); From ec9cfd1b68dad202119d56d398d7ece8e1e98ff2 Mon Sep 17 00:00:00 2001 From: Ishita Gambhir Date: Thu, 24 Jul 2025 11:36:43 +0530 Subject: [PATCH 3/7] fix UTs --- packages/messaging/__tests__/MessagingTests.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/messaging/__tests__/MessagingTests.ts b/packages/messaging/__tests__/MessagingTests.ts index 30afd079b..28ba3913e 100644 --- a/packages/messaging/__tests__/MessagingTests.ts +++ b/packages/messaging/__tests__/MessagingTests.ts @@ -10,7 +10,7 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -import { NativeEventEmitter, NativeModules } from 'react-native'; +import { NativeModules } from 'react-native'; import { Messaging, Message, MessagingEdgeEventType } from '../src'; describe('Messaging', () => { From 71cc06e2f9449d9ba64a276b46159d612417ff4c Mon Sep 17 00:00:00 2001 From: Ishita Gambhir Date: Mon, 28 Jul 2025 14:02:12 +0530 Subject: [PATCH 4/7] clear cache when message lifecycle ends --- .../mobile/reactnative/messaging/RCTAEPMessagingModule.java | 1 + packages/messaging/ios/src/RCTAEPMessaging.swift | 2 ++ 2 files changed, 3 insertions(+) diff --git a/packages/messaging/android/src/main/java/com/adobe/marketing/mobile/reactnative/messaging/RCTAEPMessagingModule.java b/packages/messaging/android/src/main/java/com/adobe/marketing/mobile/reactnative/messaging/RCTAEPMessagingModule.java index 556a1f50a..d8bff1e45 100644 --- a/packages/messaging/android/src/main/java/com/adobe/marketing/mobile/reactnative/messaging/RCTAEPMessagingModule.java +++ b/packages/messaging/android/src/main/java/com/adobe/marketing/mobile/reactnative/messaging/RCTAEPMessagingModule.java @@ -211,6 +211,7 @@ public void onShow(final Presentable presentable) { public void onDismiss(final Presentable presentable) { if (!(presentable.getPresentation() instanceof InAppMessage)) return; Message message = MessagingUtils.getMessageForPresentable((Presentable) presentable); + presentableCache.remove(message.getId()); if (message != null) { Map data = convertMessageToMap(message); diff --git a/packages/messaging/ios/src/RCTAEPMessaging.swift b/packages/messaging/ios/src/RCTAEPMessaging.swift index 97bc92f9d..c2994af7e 100644 --- a/packages/messaging/ios/src/RCTAEPMessaging.swift +++ b/packages/messaging/ios/src/RCTAEPMessaging.swift @@ -274,6 +274,8 @@ public class RCTAEPMessaging: RCTEventEmitter, MessagingDelegate { if let fullscreenMessage = message as? FullscreenMessage, let parentMessage = fullscreenMessage.parent { + jsHandlerMessageCache.removeValue(forKey: parentMessage.id) + emitNativeEvent( name: Constants.ON_DISMISS_EVENT, body: RCTAEPMessagingDataBridge.transformToMessage( From 794688e781b878b6a12ff953a4541d5a2420653b Mon Sep 17 00:00:00 2001 From: Ishita Gambhir Date: Mon, 28 Jul 2025 23:04:15 +0530 Subject: [PATCH 5/7] update docs --- packages/messaging/src/Messaging.ts | 10 +++ .../messaging/tutorials/In-App Messaging.md | 68 +++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 packages/messaging/tutorials/In-App Messaging.md diff --git a/packages/messaging/src/Messaging.ts b/packages/messaging/src/Messaging.ts index eebf52f50..ab99d8aac 100644 --- a/packages/messaging/src/Messaging.ts +++ b/packages/messaging/src/Messaging.ts @@ -184,6 +184,16 @@ class Messaging { RCTAEPMessaging.updatePropositionsForSurfaces(surfaces); } + /** + * Registers a javascript interface for the provided handler name + * to the WebView associated with the InAppMessage presentation + * to handle Javascript messages. + * When the registered handlers are executed via the HTML + * the result will be passed back to the associated callback. + * @param messageId The id of the message to handle + * @param handlerName The name of the handler to handle + * @param callback The callback to handle the message + */ static handleJavascriptMessage(messageId: string, handlerName: string, callback: (content: string) => void) { if (!jsMessageHandlers[messageId]) { jsMessageHandlers[messageId] = {}; diff --git a/packages/messaging/tutorials/In-App Messaging.md b/packages/messaging/tutorials/In-App Messaging.md new file mode 100644 index 000000000..4be499adb --- /dev/null +++ b/packages/messaging/tutorials/In-App Messaging.md @@ -0,0 +1,68 @@ +# Native handling of JavaScript events + +You can handle events from in-app message interactions natively within your application by completing the following steps: +- [Implement and assign a `Messaging Delegate`](#implement-and-assign-a-messaging-delegate) +- [Register a JavaScript handler for your In-App Message](#register-a-javascript-handler-for-your-in-app-message) +- [Post the JavaScript message from your In-App Message](#post-the-javascript-message-from-your-in-app-message) + +## Implement and assign a `Messaging Delegate` + +To register a JavaScript event handler with a Message object, you will first need to implement and set a MessagingDelegate. +Please read the [documentation](../README.md/#programmatically-control-the-display-of-in-app-messages) for more detailed instructions on implementing and using a MessagingDelegate. + +## Register a JavaScript handler for your In-App Message + +In the `onShow` function of `MessagingDelegate`, call `handleJavascriptMessage(messageId: string, handlerName: string, callback: (content: string) => void)` to register your handler. + +The name of the message you intend to pass from the JavaScript side should be specified in the first parameter. + +### Example + +```typescript +Messaging.setMessagingDelegate({ + onShow: msg => { + console.log('show', msg); + Messaging.handleJavascriptMessage( + msg.id, + 'myInappCallback', + (content) => { + console.log('Received webview content:', content); + } + ); + } + }); +``` + +## Post the JavaScript message from your In-App Message + +Now that the in-app message has been displayed, the final step is to post the JavaScript message. + +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: + +```html + + + + + + + + +``` + +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). + +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: + +```bash +JavaScript body passed to react native callback: callbacks are cool! +``` From 404ac9096e9630001fb483777c83913a738b19a2 Mon Sep 17 00:00:00 2001 From: Ishita Gambhir Date: Tue, 29 Jul 2025 11:26:47 +0530 Subject: [PATCH 6/7] add constants --- .../messaging/RCTAEPMessagingConstants.java | 19 +++++++++++++++++++ .../messaging/RCTAEPMessagingModule.java | 8 ++++---- .../messaging/ios/src/RCTAEPMessaging.swift | 13 ++++++++----- .../ios/src/RCTAEPMessagingConstants.swift | 4 ++++ 4 files changed, 35 insertions(+), 9 deletions(-) create mode 100644 packages/messaging/android/src/main/java/com/adobe/marketing/mobile/reactnative/messaging/RCTAEPMessagingConstants.java diff --git a/packages/messaging/android/src/main/java/com/adobe/marketing/mobile/reactnative/messaging/RCTAEPMessagingConstants.java b/packages/messaging/android/src/main/java/com/adobe/marketing/mobile/reactnative/messaging/RCTAEPMessagingConstants.java new file mode 100644 index 000000000..445c19c0f --- /dev/null +++ b/packages/messaging/android/src/main/java/com/adobe/marketing/mobile/reactnative/messaging/RCTAEPMessagingConstants.java @@ -0,0 +1,19 @@ +/* + Copyright 2025 Adobe. All rights reserved. + This file is licensed to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law + or agreed to in writing, software distributed under the License is + distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF + ANY KIND, either express or implied. See the License for the specific + language governing permissions and limitations under the License. + */ +package com.adobe.marketing.mobile.reactnative.messaging; + +class RCTAEPMessagingConstants { + static final String MESSAGE_ID_KEY = "messageId"; + static final String HANDLER_NAME_KEY = "handlerName"; + static final String CONTENT_KEY = "content"; + static final String ON_JAVASCRIPT_MESSAGE_EVENT = "onJavascriptMessage"; + } diff --git a/packages/messaging/android/src/main/java/com/adobe/marketing/mobile/reactnative/messaging/RCTAEPMessagingModule.java b/packages/messaging/android/src/main/java/com/adobe/marketing/mobile/reactnative/messaging/RCTAEPMessagingModule.java index d8bff1e45..dad52af23 100644 --- a/packages/messaging/android/src/main/java/com/adobe/marketing/mobile/reactnative/messaging/RCTAEPMessagingModule.java +++ b/packages/messaging/android/src/main/java/com/adobe/marketing/mobile/reactnative/messaging/RCTAEPMessagingModule.java @@ -187,10 +187,10 @@ public void handleJavascriptMessage(final String messageId, final String handler eventHandler.handleJavascriptMessage(handlerName, content -> { Map params = new HashMap<>(); - params.put("messageId", messageId); - params.put("handlerName", handlerName); - params.put("content", content); - emitEvent("onJavascriptMessage", params); + params.put(RCTAEPMessagingConstants.MESSAGE_ID_KEY, messageId); + params.put(RCTAEPMessagingConstants.HANDLER_NAME_KEY, handlerName); + params.put(RCTAEPMessagingConstants.CONTENT_KEY, content); + emitEvent(RCTAEPMessagingConstants.ON_JAVASCRIPT_MESSAGE_EVENT, params); }); } diff --git a/packages/messaging/ios/src/RCTAEPMessaging.swift b/packages/messaging/ios/src/RCTAEPMessaging.swift index c2994af7e..22596aa22 100644 --- a/packages/messaging/ios/src/RCTAEPMessaging.swift +++ b/packages/messaging/ios/src/RCTAEPMessaging.swift @@ -255,15 +255,18 @@ public class RCTAEPMessaging: RCTEventEmitter, MessagingDelegate { _ messageId: String, handlerName: String ) { - guard let message = jsHandlerMessageCache[messageId] else { return } + guard let message = jsHandlerMessageCache[messageId] else { + print("[RCTAEPMessaging] handleJavascriptMessage: No message found in cache for messageId: \(messageId)") + return + } message.handleJavascriptMessage(handlerName) { [weak self] content in self?.emitNativeEvent( - name: "onJavascriptMessage", + name: Constants.ON_JAVASCRIPT_MESSAGE_EVENT, body: [ - "messageId": messageId, - "handlerName": handlerName, - "content": content ?? "" + Constants.MESSAGE_ID_KEY: messageId, + Constants.HANDLER_NAME_KEY: handlerName, + Constants.CONTENT_KEY: content ?? "" ] ) } diff --git a/packages/messaging/ios/src/RCTAEPMessagingConstants.swift b/packages/messaging/ios/src/RCTAEPMessagingConstants.swift index 9c918fba0..dbf92a37d 100644 --- a/packages/messaging/ios/src/RCTAEPMessagingConstants.swift +++ b/packages/messaging/ios/src/RCTAEPMessagingConstants.swift @@ -20,4 +20,8 @@ class Constants { static let SUPPORTED_EVENTS = [ ON_DISMISS_EVENT, ON_SHOW_EVENT, SHOULD_SHOW_MESSAGE_EVENT, URL_LOADED_EVENT, ON_JAVASCRIPT_MESSAGE_EVENT ] + static let MESSAGE_ID_KEY = "messageId" + static let HANDLER_NAME_KEY = "handlerName" + static let CONTENT_KEY = "content" + static let ON_JAVASCRIPT_MESSAGE_EVENT = "onJavascriptMessage" } From 8d36cdca11e2eb97c4be3eea6554e755b42a4434 Mon Sep 17 00:00:00 2001 From: Ishita Gambhir Date: Tue, 29 Jul 2025 14:50:36 +0530 Subject: [PATCH 7/7] update docs --- .../app/MessagingView.tsx | 2 +- packages/messaging/README.md | 16 +++++++++++++++- .../ios/src/RCTAEPMessagingConstants.swift | 1 - 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/apps/AEPSampleAppNewArchEnabled/app/MessagingView.tsx b/apps/AEPSampleAppNewArchEnabled/app/MessagingView.tsx index 6606183c6..c513e79e4 100644 --- a/apps/AEPSampleAppNewArchEnabled/app/MessagingView.tsx +++ b/apps/AEPSampleAppNewArchEnabled/app/MessagingView.tsx @@ -56,7 +56,7 @@ const getPropositionsForSurfaces = async () => { }; const trackAction = async () => { - MobileCore.trackAction('iamjs', {full: true}); + MobileCore.trackAction('tuesday', {full: true}); }; const updatePropositionsForSurfaces = async () => { diff --git a/packages/messaging/README.md b/packages/messaging/README.md index 1c05aa3de..ee4ac358c 100644 --- a/packages/messaging/README.md +++ b/packages/messaging/README.md @@ -156,6 +156,20 @@ const messagingDelegate = { }; ``` +### handleJavascriptMessage + +Registers a javascript interface for the provided handler name to the WebView associated with the InAppMessage presentation to handle Javascript messages. When the registered handlers are executed via the HTML the result will be passed back to the associated callback. + +**Syntax** + +```javascript +handleJavascriptMessage(messageId: string, handlerName: string, callback: (content: string) => void) +``` + +**Example** + +It can be used for the native handling of JavaScript events. Please refer to the [tutorial](./tutorials/In-App%20Messaging.md#native-handling-of-javascript-events) for more information. + ### updatePropositionsForSurfaces Dispatches an event to fetch propositions for the provided surfaces from remote. @@ -459,4 +473,4 @@ Messaging.trackContentCardInteraction(proposition, contentCard); ## Tutorials [Content Cards](./tutorials/ContentCards.md) - +[In App Messaging](./tutorials/In-App%20Messaging.md) diff --git a/packages/messaging/ios/src/RCTAEPMessagingConstants.swift b/packages/messaging/ios/src/RCTAEPMessagingConstants.swift index dbf92a37d..64f26aa03 100644 --- a/packages/messaging/ios/src/RCTAEPMessagingConstants.swift +++ b/packages/messaging/ios/src/RCTAEPMessagingConstants.swift @@ -23,5 +23,4 @@ class Constants { static let MESSAGE_ID_KEY = "messageId" static let HANDLER_NAME_KEY = "handlerName" static let CONTENT_KEY = "content" - static let ON_JAVASCRIPT_MESSAGE_EVENT = "onJavascriptMessage" }