Skip to main content

In-App Messages

The SDK shows in-app messages designed in the panel and reports when they are displayed, clicked and dismissed. How in-app messages work across platforms: In-App Messages.


Requirements​

  • The SDK installed and initialized, see Installation.
  • The FCM token passed to the SDK, see Firebase and FCM Token.
  • Background Modes → Remote notifications enabled in your app target.
  • application(_:didReceiveRemoteNotification:fetchCompletionHandler:) passing the notification to handleNotification(_:).
  • A physical device for testing.

In-app messages do not need notification permission, as long as your app registers with APNs and passes the FCM token. If your app calls registerForRemoteNotifications() only after the user allows notifications, users who decline get no in-app messages.


Setup​

In-app messages are delivered as silent (data only) pushes. They carry no alert, so iOS never passes them to UNUserNotificationCenterDelegate. They arrive only in the app delegate method below.

  1. Enable Background Modes → Remote notifications in Signing & Capabilities.
  2. Forward silent pushes to the SDK:
func application(_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
UserSDK.default?.handleNotification(userInfo)
completionHandler(.noData)
}

The Swift concurrency form, application(_:didReceiveRemoteNotification:) async -> UIBackgroundFetchResult, works the same way. You can call handleNotification(_:) from any thread or task. It shows in-app messages and never counts a click.

Check

With the app open, send an in-app message to your test contact. It appears on screen and is counted as displayed in the panel.


Handling​

When a message is shown​

  • App in the foreground: the message is shown at once.
  • App in the background or inactive: the SDK keeps the newest message and shows it the next time the app becomes active, if it arrived less than 6 hours earlier. A newer message replaces an older one, and each message is shown once. logout discards a waiting message.
  • App not running: iOS does not deliver silent pushes to an app the user swiped away, and may hold them back in Low Power Mode or with Background App Refresh turned off. Those messages are not shown.

The SDK shows each message in its own window above your app. Your navigation (a splash screen, full screen presentations, sheets, a replaced root view controller) does not block it. Screens you present while a message is visible are not blocked either: they appear under the message and are available after it closes.

Changed in 1.2.0

In-app messages are shown in a separate window, and messages received in the background are shown on the next app open (within 6 hours). "Displayed" is reported only once the message is on screen, so displayed numbers in the panel can be lower than before the upgrade, and accurate.

Button taps​

A tap on a button always reports a click and closes the message. If the button has a link, the SDK passes it to your inAppMessageClickHandler first, on the main thread:

  • return true: you handled the link, the SDK does nothing more,
  • return false, or no handler: the SDK opens the link with UIApplication.open(_:), but only if iOS reports it can open it (canOpenURL). A custom URL scheme that is not listed in your app's LSApplicationQueriesSchemes is not opened.

To open screens of your own app from a button, handle the link in inAppMessageClickHandler. See Opening App Screens.

UserSDK.default?.inAppMessageClickHandler = { url in
guard url.scheme == "myapp" || url.host == "www.example.com" else {
return false // let the SDK open it
}
// route to the matching screen
return true
}

Custom fonts​

Without a fontResolver, every message uses the system font, also when the font set in the panel is built into iOS. To use the fonts from the panel, set fontResolver, and add fonts that are not built into iOS to your app. When the resolver returns nil, the SDK uses the system font.


Methods​

inAppMessageClickHandler​

Receives the link of every tapped button before the SDK opens it, on the main thread. Available in Swift only. Added in 1.3.0.

NameTypeRequiredDescription
inAppMessageClickHandler((URL) -> Bool)?NoReceives the button's URL, including custom schemes. Return true if you handled it.

The click is reported to the panel in both cases.

UserSDK.default?.inAppMessageClickHandler = { url in
router.open(url)
return true
}

inAppNotificationClickDelegate, an object implementing InAppNotificationClickDelegate, is deprecated since 1.3.0 and stays until 2.0. It has the same meaning. When both are set, inAppMessageClickHandler is used.

fontResolver​

Provides fonts for text in in-app messages. Set it after initializing the SDK.

NameTypeRequiredDescription
fontResolverFontResolving?NoImplements resolveFontFor(name:size:) -> UIFont?.

resolveFontFor(name: String, size: CGFloat) -> UIFont? receives the font name and size from the message. Return nil to use the system font. Without a resolver, the SDK always uses the system font.

final class AppFontResolver: NSObject, FontResolving {
func resolveFontFor(name: String, size: CGFloat) -> UIFont? {
UIFont(name: name, size: size)
}
}

UserSDK.default?.fontResolver = AppFontResolver()

inAppAlertCloseButtonText​

A static String property, default "Close". Has no effect. The close button is an icon without text. Kept for source compatibility.


Common errors​

SymptomCauseFix
Push notifications work, in-app messages never appearapplication(_:didReceiveRemoteNotification:fetchCompletionHandler:) is missing, is in a class iOS does not use as the app delegate, or does not call handleNotification(_:).Add the method to the real app delegate. In SwiftUI, to the class attached with UIApplicationDelegateAdaptor.
In-app messages never appear, even in the foregroundThe Remote notifications background mode is missing from the built Info.plist.Enable Background Modes → Remote notifications.
Messages sent while the app was closed never appeariOS does not deliver silent pushes to an app the user swiped away.Expected. Messages sent while the app is in the background are shown on the next open, within 6 hours.
Button does nothing except closing the messageThe link uses a custom scheme the SDK cannot open, and no handler took it.Handle the link in inAppMessageClickHandler.
Text uses the wrong fontNo fontResolver set, the font is not in the app, or fontResolver returns nil.Set fontResolver, add the font to the app and return it from fontResolver.
The app crashed in CoreAutoLayout, or messages disappeared, when notifications were handled in a Task or on a background queueVersions before 1.2.0 required the main thread.Update to 1.2.0.

More cases: iOS Troubleshooting.