The Radar iOS SDK enables you to display rich in-app messages to users based on their location and behavior. These messages appear within your app, providing a native and non-intrusive way to engage users.
Overview
In-app messages support:
Location-triggered messaging : Show messages when users enter geofences or approach destinations
Rich content : Display titles, body text, images, and call-to-action buttons
Custom styling : Customize colors, fonts, and layout
Deep linking : Navigate users to specific screens in your app
Conversion tracking : Automatically track message displays, dismissals, and button clicks
Setup
The SDK automatically manages in-app messages when location events occur. No additional setup is required beyond initializing the SDK.
import RadarSDK
Radar. initialize ( publishableKey : "YOUR_PUBLISHABLE_KEY" )
In-app messages require iOS 13.0 or later and are available starting with SDK version 3.10+.
Create in-app messages in the Radar dashboard by adding message metadata to your geofences or campaigns:
{
"title" : {
"text" : "Welcome to Our Store!" ,
"color" : "#000000"
},
"body" : {
"text" : "Check out our latest deals and save 20% today." ,
"color" : "#666666"
},
"button" : {
"text" : "View Deals" ,
"color" : "#FFFFFF" ,
"backgroundColor" : "#0066FF" ,
"deepLink" : "myapp://deals"
},
"image" : {
"name" : "store-banner" ,
"url" : "https://example.com/images/store-banner.png"
},
"metadata" : {
"radar:campaignId" : "store-entry-2024" ,
"radar:campaignName" : "Store Entry Campaign" ,
"radar:geofenceId" : "store-123"
}
}
Message structure
An in-app message consists of:
Property Type Required Description titleTextYes Message title with text and color bodyTextYes Message body with text and color buttonButtonNo Optional call-to-action button imageImageNo Optional banner image metadataDictionaryNo Additional metadata for tracking
Text properties
struct Text {
var text: String // The text content
var color: UIColor // Hex color (e.g., "#000000")
}
struct Button {
var text: String // Button label
var color: UIColor // Text color
var backgroundColor: UIColor // Button background color
var deepLink: String ? // Optional deep link URL
}
Image properties
struct Image {
var name: String // Image identifier
var url: String // Image URL
}
Customize message presentation
Implement the RadarInAppMessageProtocol to customize message presentation:
import RadarSDK
@available ( iOS 13.0 , * )
class CustomInAppMessageDelegate : RadarInAppMessageDelegate {
// Called when a new message is received
override func onNewInAppMessage ( _ message : RadarInAppMessage) {
print ( "New in-app message received" )
// Automatically show the message
Task { @MainActor in
await RadarInAppMessageManager. shared . showInAppMessage (message)
}
}
// Called when a message is dismissed
override func onInAppMessageDismissed ( _ message : RadarInAppMessage) {
print ( "In-app message dismissed" )
}
// Called when a button is clicked
override func onInAppMessageButtonClicked ( _ message : RadarInAppMessage) {
print ( "In-app message button clicked" )
// Handle deep link
if let button = (message as? RadarInAppMessage_Swift) ? .button,
let deepLink = button.deepLink,
let url = URL ( string : deepLink) {
handleDeepLink (url)
}
}
// Customize the message view
override func createInAppMessageView (
_ message : RadarInAppMessage,
onDismiss : @escaping () -> Void ,
onInAppMessageClicked : @escaping () -> Void ,
completionHandler : @escaping (UIViewController) -> Void
) {
// Return your custom view controller
let customViewController = CustomMessageViewController ( message : message)
customViewController. onDismiss = onDismiss
customViewController. onButtonClicked = onInAppMessageClicked
completionHandler (customViewController)
}
}
// Set the custom delegate
if #available ( iOS 13.0 , * ) {
Task { @MainActor in
RadarInAppMessageManager. shared . setDelegate ( CustomInAppMessageDelegate ())
}
}
Show messages programmatically
Manually display in-app messages:
import RadarSDK
@available ( iOS 13.0 , * )
func showMessage ( _ message : RadarInAppMessage) {
Task { @MainActor in
await RadarInAppMessageManager. shared . showInAppMessage (message)
}
}
Conversion tracking
The SDK automatically tracks in-app message conversions:
Event Description user.displayed_in_app_messageMessage was shown to the user user.dismissed_in_app_messageUser dismissed the message user.clicked_in_app_messageUser clicked the message button
Conversions include metadata:
displayDuration: How long the message was shown (seconds)
campaignId: Campaign identifier
campaignName: Campaign name
geofenceId: Triggering geofence ID
View conversion analytics in the Radar dashboard under Analytics > Conversions.
Handle deep links
Process deep links from message buttons:
func handleDeepLink ( _ url : URL) {
// Parse the URL and navigate
if url.scheme == "myapp" {
switch url.host {
case "deals" :
showDealsScreen ()
case "product" :
if let productId = url.pathComponents. last {
showProductDetails (productId)
}
default :
break
}
}
}
Message display rules
The SDK follows these rules for displaying messages:
Only one message is shown at a time
New messages are ignored while a message is currently displayed
Messages are shown on the app’s key window
Messages are displayed with a semi-transparent background overlay
Users can dismiss messages by tapping outside the message view
Best practices
Keep messages concise Use short, actionable text that users can quickly read and understand.
Test on different devices Verify messages display correctly on various screen sizes and iOS versions.
Use high-quality images Optimize images for mobile and provide appropriate resolutions for retina displays.
Implement deep links Always provide a button with a deep link to make messages actionable.
Example: Complete implementation
import RadarSDK
import UIKit
@available ( iOS 13.0 , * )
class AppDelegate : UIResponder , UIApplicationDelegate {
func application ( _ application : UIApplication,
didFinishLaunchingWithOptions launchOptions : [UIApplication.LaunchOptionsKey: Any ] ? ) -> Bool {
// Initialize Radar
Radar. initialize ( publishableKey : "YOUR_PUBLISHABLE_KEY" )
// Set up in-app message delegate
Task { @MainActor in
let delegate = MyInAppMessageDelegate ()
RadarInAppMessageManager. shared . setDelegate (delegate)
}
// Start tracking
Radar. startTracking ( trackingOptions : . presetResponsive )
return true
}
}
@available ( iOS 13.0 , * )
class MyInAppMessageDelegate : RadarInAppMessageDelegate {
override func onNewInAppMessage ( _ message : RadarInAppMessage) {
// Show the message when received
Task { @MainActor in
await RadarInAppMessageManager. shared . showInAppMessage (message)
}
}
override func onInAppMessageButtonClicked ( _ message : RadarInAppMessage) {
// Handle button click
if let swiftMessage = message as? RadarInAppMessage_Swift,
let button = swiftMessage.button,
let deepLink = button.deepLink,
let url = URL ( string : deepLink) {
// Open deep link
UIApplication. shared . open (url)
}
}
}
Troubleshooting
Verify iOS version is 13.0 or later
Check that messages are configured correctly in the dashboard
Ensure the app has a key window available
Verify the delegate is set on the main thread
Check that no other message is currently being displayed
Custom delegate not being called
Ensure the delegate is set using RadarInAppMessageManager.shared.setDelegate()
Verify the delegate is set on the main thread with @MainActor
Check that the delegate is retained (not deallocated)
Verify the deep link URL format is correct
Ensure your app’s URL scheme is registered in Info.plist
Check that you’re handling the deep link in onInAppMessageButtonClicked