--- title: "Custom message handling" slug: "mobile-message-custom-handling" updated: 2026-06-09T22:56:21Z published: 2026-06-09T22:56:21Z canonical: "docs.xtremepush.com/mobile-message-custom-handling" stale: true --- > ## Documentation Index > Fetch the complete documentation index at: https://docs.xtremepush.com/llms.txt > Use this file to discover all available pages before exploring further. # Custom message handling With the Xtremepush SDK you, as a developer, have a unified callback to all the user interactions with messages. You can use it to implement any business logic if having the standard deeplinking mechanism is not enough. ## iOS ### Objective-C User interaction is described with the `XPMessageResponse` model. It contains: - XPMessage *message - XPAction *action XPMessage contains: - XPMessageType *type - message type, one of: - XPMessageType_Push - XPMessageType_Inapp - XPMessageType_Inbox - NSString *identifier - message ID - NSString *campaignIdentifier - campaign ID - NSString *title - message title - NSString *text - message text - NSDictionary *data - custom payloads - NSDictionary *payload - raw message payload XPAction contains: - XPActionType *type - response type, one of: - XPActionType_Click - XPActionType_Dismiss - XPActionType_Present - NSString *identifier - action identifier (like button ID, optional) Here is how to register the handler: ```objectivec [XPush registerMessageResponseHandler:^(XPMessageResponse *response) {    switch (response.action.type) {        case XPActionType_Click:            // Logic when message is clicked            break;        case XPActionType_Dismiss:            // Logic when message is dismissed            break;        case XPActionType_Present:            // Logic when message is received in foreground            break;    } }]; ``` > [!NOTE] > If you use interactive notifications and want to handle button clicks in the background you need to make sure to use a method with completion handler instead: ```objectivec [XPush registerMessageResponseHandlerWithCompletion:^(XPMessageResponse * _Nonnull x, XPMessageCompletionBlock  _Nonnull completionHandler) {    if (response.action.type == XPActionType_Click) {            if (response.action.identifier == @"like") {                   // Like article asynchronously and call completionHandler when finished                   [self likeArticle: response.message.data[@"articleId"] completionHandler: completionHandler];                   return;            }    }    // If nothing to be done    completionHandler(); }]; ``` Below is a complete example of custom notification handling. It does multiple things: - Shows a custom dialog when a push message is received in the foreground - Opens an article page when a message is clicked - Saves information when one of the message buttons is clicked ```objectivec [XPush registerMessageResponseHandlerWithCompletion: ^(XPMessageResponse * _Nonnull response, XPMessageCompletionBlock  _Nonnull completionHandler) {                switch (response.action.type) {            // When message is received in foreground            case XPActionType_Present:                // Show an article dialog with "View" button                [self showArticleDialog: response.message viewButtonCallback: ^{                    // Report message as clicked                    [XPush reportMessageClicked:response.message];                    // Navigate to article page                    [self openArticle: x.message.data[@"articleId"]];                }];                break;                            // When message is clicked            case XPActionType_Click:                // Default click action                if (response.action.identifier == nil) {                    // Navigate to the article page                    [self openArticle: response.message.data[@"articleId"]];                }                // Action for a certain button click                else {                    switch(response.action.identifier) {                        case "like":                              // Like article asynchronously and call completionHandler when finished                              [self likeArticle: response.message.data[@"articleId"] completionHandler: completionHandler];                              return;                    }                }                break;        }            completionHandler(); }]; ``` ### Mark a message as opened The`reportMessageOpened`and `reportMessageClickedfunction` are additions to the SDK that enable developers to implement the feature of marking a message as opened or clicked when a user opens or clicks on it within their application. This function is particularly useful for enhancing user engagement and providing real-time feedback on message interactions. When called, it triggers an event within the SDK that records the message as opened or clicked, depending on the function used, for tracking and analytics purposes. Developers can easily integrate this function into their application's message-handling workflow to improve user experience and gain insights into user engagement patterns.ift **Swift** ```swift reportMessageOpened(_ message: XPMessage!, actionIdentifier: String!) reportMessageOpened(_ message: XPMessage!, context: [AnyHashable : Any]!) ``` **Objective-C** ```objectivec + (void)reportMessageOpened:(XPMessage *)message context:(NSDictionary *)context + (void)reportMessageOpened:(XPMessage *)message actionIdentifier:(NSString*)actionIdentifier                                                           ``` **Swift** ```swift reportMessageClicked(_ message: XPMessage!, actionIdentifier: String!) reportMessageClicked(_ message: XPMessage!, context: [AnyHashable : Any]!) ``` **Objective-C** ```objectivec + (void)reportMessageClicked:(XPMessage *)message context:(NSDictionary*)context; + (void)reportMessageClicked:(XPMessage *)message actionIdentifier:(NSString*)actionIdentifier; ``` > [!TIP] > Messages clicked will be considered opened > > Marking a message as clicked using the described method automatically marks it as open, as a user cannot click on the message without first opening it. However, marking a message as opened will not automatically update the click value, as a user may open a message and then not engage with any of the CTAs within it. ### Swift User interaction is described with the XPMessageResponse model. It contains: - message: XPMessage - action: XPAction XPMessage contains: - type: XPMessageType- message type, one of: - XPMessageType_Push - XPMessageType_Inapp - XPMessageType_Inbox - identifier: String - message ID - campaignIdentifier: String - campaign ID - title: String - message title - text: String - message text - data: [AnyHashable : Any]? - custom payloads - payload: [AnyHashable : Any] - raw message payload XPAction contains: - type: XPActionType - response type, one of: - XPActionType_Click - XPActionType_Dismiss - XPActionType_Present - identifier: String - action identifier (like button ID, optional) Here is how to register the handler: ```swift XPush.registerMessageResponseHandler({(_ response: XPMessageResponse) -> Void in    switch response.action.type {        case XPActionType_Click:            // Logic when message is clicked        case XPActionType_Dismiss:            // Logic when message is dismissed        case XPActionType_Present:            // Logic when message is received in foreground    } }) ``` > [!NOTE] > If you use interactive notifications and want to handle button clicks in background you need to make sure to use a method with completion handler instead: ```swift XPush.registerMessageResponseHandler(withCompletion: {(_ x: XPMessageResponse, _ completionHandler: XPMessageCompletionBlock) -> Void in    if response.action.type == XPActionType_Click {        if response.action.identifier == "like" {            // Like article asynchronously and call completionHandler when finished            self.likeArticle(response.message.data["articleId"], completionHandler: completionHandler)            return        }    }    // If nothing to be done    completionHandler() }) ``` Below is a complete example of custom notification handling. It does multiple things: - Shows a custom dialog when a push message is received in the foreground - Opens an article page when a message is clicked - Saves information when one of the message buttons is clicked ```swift XPush.registerMessageResponseHandler(withCompletion: {(_ x: XPMessageResponse, _ completionHandler: XPMessageCompletionBlock) -> Void in   if response.action.type == XPActionType_Present {                showArticleDialog(response.message, viewButtonCallback: {() -> Void in                    // Report message as clicked                    XPush.reportMessageClicked(response.message)                    // Navigate to article page                    self.openArticle(x.message.data["articleId"])                })            }            else if response.action.type == XPActionType_Click {                // Default click action                if response.action.identifier == nil {                    // Navigate to the article page                    openArticle(response.message.data["articleId"])                }                    // Action for a certain button click                else {                    if response.action.identifier == "like" {                        // Like article asynchronously and call completionHandler when finished                        self.likeArticle(response.message.data["articleId"], completionHandler: completionHandler)                    }                }            }                        // If nothing to be done            completionHandler() }) ``` ## Android User interaction is described with the objects - Message messagePayload - HashMap responsePayload Message contains: - String type - message type, one of: - "push" - "inapp" - "inbox" - String id- message ID - String campaignId - campaign ID - String title - message title - String text- message text - HashMap data - custom payloads the responsePayload HashMap contains: - String type - response type, one of: - "present" - "click" - "dismiss" - String action- action identifier (like button ID, optional) Implement the MessageResponseListener in your Application.java class ```java public class YOUR_APPLICATION_CLASS extends Application implements MessageResponseListener { ``` Then implement the method ```plaintext @Override    public void messageResponseReceived(Message messagePayload,            HashMap responsePayload,            WeakReference uiReference) {            } ``` Then add the `setMessageResponseListener` option to your initialisation of the `PushConnector`: ```java new PushConnector.Builder(XPUSH_APP_KEY, GOOGLE_PROJECT_NUMBER)            .setMessageResponseListener(this)            ...            .create(this); ``` Below is a complete example of custom notification handling. It does multiple things: - Shows a custom dialog when a push message is received in the foreground - Opens an article page when a message is clicked - Saves information when one of the message buttons is clicked ```java @Override    public void messageResponseReceived(final Message messagePayload,            HashMap responsePayload,            final WeakReference uiReference) {        switch (responsePayload.get("type")) {            // When app is received in the foreground show a custom notification            case "present":                if (uiReference != null && uiReference.get() != null) {                    ((Activity) uiReference.get()).runOnUiThread(new Runnable() {                        @Override                        public void run() {                            AlertDialog.Builder builder = new AlertDialog.Builder((Activity) uiReference.get());                            builder.setPositiveButton("View", new DialogInterface.OnClickListener() {                                public void onClick(DialogInterface dialog, int id) {                                    //go to article id                                    openArticle(messagePayload.data.get("articleId"));                                }                            });                            builder.setMessage(messagePayload.text);                            builder.setTitle(messagePayload.title);                            AlertDialog dialog = builder.create();                            dialog.show();                        }                    });                }                break;            //when message is clicked            case "click":                //default click action                if (!(responsePayload.containsKey("action"))) {                    //navigate to article                    openArticle(messagePayload.data.get("articleId"));                }                //action for a certain button click                else {                    switch (responsePayload.get("action")) {                        case "like":                            //like article                            likeArticle(messagePayload.data.get("articleId"));                            break;                    }                }                break;        }    } ``` ### Mark a message as opened As with iOS, the`reportMessageOpened`and `reportMessageClickedfunction` are additions to the SDK that enable developers to implement the feature of marking a message as opened or clicked when a user opens or clicks on it within their application. This function is particularly useful for enhancing user engagement and providing real-time feedback on message interactions. When called, it triggers an event within the SDK that records the message as opened or clicked, depending on the function used, for tracking and analytics purposes. Developers can easily integrate this function into their application's message-handling workflow to improve user experience and gain insights into user engagement patterns. ```java reportMessageOpened(message, action, null); reportMessageOpened(Message message, String action, JSONObject message_context) ``` ```java reportMessageClicked(message, action, null); reportMessageClicked(Message message, String action, JSONObject message_context) ``` > [!TIP] > Messages clicked will be considered opened > > Marking a message as clicked using the described method automatically marks it as open, as a user cannot click on the message without first opening it. However, marking a message as opened will not automatically update the click value, as a user may open a message and then not engage with any of the CTAs within it.