Building a Message Stream

Retrieving messages for a user

Marigold Messages have several properties which you should familiarize yourself with before building a stream or displaying messages.

Property nameCan be blankDescriptionPlugin SDK name
titleNoThe title of the messagetitle
textYesThe body of the messagetext
htmlTextYesThe body of the message rendered into an HTML stringhtml_text
imageURLYesA URL pointing to an imagecard_image_url
videoURL (iOS)
mediaURL (Android)
YesA URL pointing to a videocard_media_url
URL (iOS)
contentURL (Android)
YesA URL pointing to a generic page or resourceurl
readNoWhether or not the message has been readis_read
createdAtNoThe date and time when the message was createdcreated_at
messageIDNoAn alphanumeric unique ID for the messageid
attributesYesA dictionary of string keys and values set on the messageattributes

You can use the MessageStream interface to asynchronously request an array of messages for that device. Once returned you can use these objects to construct your own Message Stream interface.

//On iOS, using Objective-C

[[MARMessageStream new] messages:^(NSArray *messages, NSError *error) {
	//Do something with the array of messages
}];
MARMessageStream().messages { (theMessages, anError) -> Void in
	//Do something with the array of messages
}
new MessageStream().getMessages(new MessageStream.MessagesHandler() {
  @Override
  public void onSuccess(ArrayList<Message> messages) {
    //Do something with the array of messages
  }

  @Override
  public void onFailure(Error error) {
  }
});
MessageStream().getMessages(object : MessageStream.MessagesHandler {
    override fun onSuccess(messages: ArrayList<Message>?) {
      //Do something with the array of messages
    }

    override fun onFailure(error: Error?) {
    }
})
SailthruMobile.getMessages().then(messages => {
  //Do something with the array of messages
}).catch(e => {
  //Handle error
});
MessageStream.OnMessagesReceivedEvent += (object sender, MessagesReceivedEventArgs e) => {
};

new MessageStream().GetMessages();

Showing full screen content

After a user taps on message, you can can show the full screen content with the following method.

[[MARMessageStream new] presentMessageDetailForMessage:self.latestMessage];
MARMessageStream().presentDetailForMessage(message)
Intent intent = MessageActivity.intentForMessage(context, bundle, message);
startActivity(intent);
val intent = MessageActivity.intentForMessage(context, bundle, message)
startActivity(intent)
SailthruMobile.presentMessageDetail(message);
new MessageStream().ShowMessageDetail(message);

Supporting Impressions

In order to support impression analytics from your Message Stream you will need to ensure you register an impression event for relevant messages when your Message Stream is shown to the user.

Marigold supports tracking three types of impressions:

  • In App Notification Impression
  • Message Viewed in Stream Impression
  • Message Viewed in Detail Impression

If you didn't customize Marigold's default in-app notification or full-screen detail user interface, there is no need to register an impression event as these will be captured automatically.

[[MARMessageStream new] registerImpressionWithType:
    STMImpressionTypeInAppNotificationView forMessage:message];

[[MARMessageStream new] registerImpressionWithType:
    STMImpressionTypeStreamView forMessage:message];

[[MARMessageStream new] registerImpressionWithType:
    STMImpressionTypeDetailView forMessage:message];
MARMessageStream().registerImpressionWithType(.inAppNotificationView, forMessage: message)
    
MARMessageStream().registerImpressionWithType(.streamView, forMessage: message)        
    
MARMessageStream().registerImpressionWithType(.detailView, forMessage: message)
new MessageStream().registerMessageImpression(ImpressionType.IMPRESSION_TYPE_IN_APP_VIEW, message);

new MessageStream().registerMessageImpression(ImpressionType.IMPRESSION_TYPE_STREAM_VIEW, message);

new MessageStream().registerMessageImpression(ImpressionType.IMPRESSION_TYPE_DETAIL_VIEW, message);
MessageStream().registerMessageImpression(ImpressionType.IMPRESSION_TYPE_IN_APP_VIEW, message)

       MessageStream().registerMessageImpression(ImpressionType.IMPRESSION_TYPE_STREAM_VIEW, message)

       MessageStream().registerMessageImpression(ImpressionType.IMPRESSION_TYPE_DETAIL_VIEW, message)
SailthruMobile.registerMessageImpression(SailthruMobile.MessageImpressionType.InAppView, message);

SailthruMobile.registerMessageImpression(SailthruMobile.MessageImpressionType.StreamView, message);

SailthruMobile.registerMessageImpression(SailthruMobile.MessageImpressionType.DetailView, message);
new MessageStream().RegisterImpression(message, ImpressionType.InAppNotificationView);

new MessageStream().RegisterImpression(message, ImpressionType.StreamView);

new MessageStream().RegisterImpression(message, ImpressionType.DetailView);

Marking As Read

You might also want to track which messages have been read or not with your Message Stream, so you could show a number badge or unread indicator. You can mark a collection or single message as read.

[[MARMessageStream new] markMessageAsRead:message withResponse:NULL];
// or
[[MARMessageStream new] markMessagesAsRead:@[message1, message2, message3] withResponse:NULL];
MARMessageStream().markMessageAsRead(message, withResponse: nil)
// or 
MARMessageStream().markMessagesAsRead(messages, withResponse: nil)
new MessageStream().setMessageRead(message, messageReadHandler);
// or 
new MessageStream().setMessagesRead(messageList, messageReadHandler);
MessageStream().setMessageRead(message, messageReadHandler)
// or 
MessageStream().setMessagesRead(messageList, messageReadHandler)
SailthruMobile.markMessageAsRead(message).then(result => {
  // Handle success
}).catch(e => {
  // Handle error
});
new MessageStream().MarkMessageAsRead(message);
// or
new MessageStream().MarkMessagesAsRead(messages);

Deleting Messages

Messages can be deleted from a user's stream.

[[MARMessageStream new] removeMessage:message withResponse:^(NSError *error) {
	//Do something with any errors
}];
MARMessageStream().removeMessage(message, withResponse: nil)
new MessageStream().deleteMessage(message, messageDeletedHandler);
MessageStream().deleteMessage(message, messageDeletedHandler)
SailthruMobile.removeMessage(message).then(result => {
  // Handle success
}).catch(e => {
  // Handle error
});
new MessageStream().RemoveMessage(message);

Clearing the Message Stream

All the messages can be cleared from the user's stream at once.

[[MARMessageStream new] clearMessagesWithResponse:^(NSError *error) {
	//Do something with any errors
}];
MARMessageStream().clearMessages { error in
  //Do something with any errors
}
new MessageStream().clearMessages(new MessageStream.MessageStreamHandler<>() {
  @Override
  public void onSuccess(Void value) {
    // Handle success
  }
  @Override
  public void onFailure(@NonNull Error error) {
    // Handle error
  }
});
MessageStream().clearMessages(object : MessageStreamHandler<Void?> {
  override fun onSuccess(value: Void?) {
    // Handle success
  }
  override fun onFailure(error: Error) {
    // Handle error
  }
})
new MessageStream().ClearMessages();

Custom In-App Message Notifications

You can customize the look and feel of In-App Message Notifications by following the instructions here.

πŸ“˜

While testing, you can reinstall the app to get a fresh set of messages, as impressions and deletions do not persist between same-device installs.

Custom Message Attributes

You can use a dictionary or hash of custom attributes to further customize the display of your message stream and messages. These may include:

  • Pinned messages
  • Categories on the Stream
  • Custom CTAs or card design

HTML Support

Since you can include markdown in messages sent via Marigold, we expose this markdown rendered into HTML with the htmlText property.

bodyLabel.attributedText = [[NSAttributedString alloc] initWithData:[message.htmlText dataUsingEncoding:NSUTF8StringEncoding]
                            options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
                                 NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding)}
                 documentAttributes:nil error:nil];
do {
    try bodyLabel.attributedText = NSAttributedString.init(
        data: message.htmlText.dataUsingEncoding(NSUnicodeStringEncoding)!,
        options: [
            NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
            NSCharacterEncodingDocumentAttribute: NSUTF8StringEncoding
        ],
        documentAttributes: nil);
} catch {
    
}
TextView textView = ...;
textView.setText(Html.fromHtml(message.getHtmlText()));
val textView = ...
textView.text = Html.fromHtml(message.htmlText, Html.FROM_HTML_MODE_COMPACT)

HTML Text will always be populated, even if no markdown was used in the original message.

Unread messages count

You can get the number of unread messages from the SDK, without the need to request a message stream and iterate over each individual message.

Marigold will deliver an in-app message in two occasions: after launch with app is in foreground or if the user has the app open and the device has a valid push token. Therefore, you may want to obtain the unread message count when the user opens the app, or when it becomes active after being backgrounded.

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    [[MARMessageStream new] unreadCount:^(NSUInteger unreadCount, NSError * _Nullable error) {
        // Add your logic here
    }];
}
func applicationDidBecomeActive(_ application: UIApplication) {
    MARMessageStream().unreadCount { (count, error) in
        // Add your logic here
    }
}
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onResume() {
        super.onResume();
        new MessageStream().getUnreadMessageCount(new MessageStream.MessageStreamHandler<Integer>() {
            @Override
            public void onSuccess(Integer value) {
                // Handle count
            }

            @Override
            public void onFailure(@Nullable Error error) {
								// Handle error
            }
        });

        // Add your logic here
    }
}
class MainActivity : AppCompatActivity() {
    override fun onResume() {
        super.onResume()
        MessageStream().getUnreadMessageCount(object: MessageStream.MessageStreamHandler<Int?> {
            override fun onSuccess(count: Int?) {
                // Handle count
            }

            override fun onFailure(error: Error?) {
               // Handle error 
            }
        })

        // Add your logic here
    }
}
SailthruMobile.getUnreadCount().then(function(count) {
	// Handle unread message count
}, function(e){
	// Handle error
});
public class MessageStreamScene : MonoBehaviour {
  
  void Start() {
    MessageStream.OnUnreadCountReceivedEvent += (object sender, UnreadCountReceivedEventArgs e) => {
			// Add your logic here
		};
    
    new MessageStream().UnreadCount();
  }
}