Skip to main content
In-app messages are configured in the AppDNA Console and displayed automatically by the SDK when trigger conditions are met. No code is required to show messages — the SDK evaluates triggers on every tracked event and presents the message if conditions match.

How It Works

  1. You create an in-app message in the Console with content, layout, and trigger rules.
  2. The message definition is synced to the SDK via the config bundle.
  3. On every track() call (including auto-tracked events), the SDK evaluates all active message triggers.
  4. If conditions match, the message is presented automatically.
In-app messages are fully server-driven. You can change the message content, trigger rules, and audience without an app update.

Message Types

TypeDescription
bannerSmall bar at the top or bottom of the screen
modalCentered overlay with a dimmed background
fullscreenFull-screen takeover
tooltipSmall popup anchored to a UI element

Triggers

Messages trigger based on events and optional conditions, configured in the Console:
  • Event match — e.g., trigger on workout_completed
  • Property conditions — e.g., duration >= 30
  • Frequencyonce, once_per_session, or every_time
  • Delay — wait N seconds after the trigger event before showing

Module Access

let messages = AppDNA.inAppMessages

Module Methods

MethodSignatureDescription
suppressDisplaysuppressDisplay(_ suppress: Bool)Suppress or resume in-app messages
setDelegatesetDelegate(_ delegate: AppDNAInAppMessageDelegate?)Set a delegate for message callbacks

Suppressing Messages

Suppress messages during critical flows like checkout or onboarding to avoid interrupting the user:
// Suppress during purchase flow
AppDNA.inAppMessages.suppressDisplay(true)
startPurchaseFlow()

// Resume after purchase completes
func purchaseDidComplete() {
    AppDNA.inAppMessages.suppressDisplay(false)
}

AppDNAInAppMessageDelegate

Implement the delegate to respond to message lifecycle events:
protocol AppDNAInAppMessageDelegate {
    func onMessageShown(messageId: String, trigger: String)
    func onMessageAction(messageId: String, action: String, data: [String: Any]?)
    func onMessageDismissed(messageId: String)
    func shouldShowMessage(messageId: String) -> Bool
}

Example Implementation

class MessageHandler: AppDNAInAppMessageDelegate {
    func onMessageShown(messageId: String, trigger: String) {
        print("Message shown: \(messageId) (trigger: \(trigger))")
    }

    func onMessageAction(messageId: String, action: String, data: [String: Any]?) {
        if let url = data?["url"] as? String {
            // Handle deep link or URL action
            navigate(to: url)
        }
    }

    func onMessageDismissed(messageId: String) {
        print("Message dismissed: \(messageId)")
    }

    func shouldShowMessage(messageId: String) -> Bool {
        // Return false to prevent the message from being shown
        return true
    }
}

AppDNA.inAppMessages.setDelegate(MessageHandler())

Rich Media

In-app messages support rich media content configured in the Console:
  • Lottie animations — animated hero images or backgrounds
  • Video — inline video with optional autoplay and looping
  • Icon buttons — CTA buttons with icon references (Lucide, SF Symbols, Material, or emoji)
  • Haptic feedback — triggered on message display or button taps
  • Particle effects — confetti, sparkles, or other effects on message actions
  • Blur backdrop — glassmorphism-style blurred background for modals
See the Rich Media guide for details on supported formats and configuration.

Auto-Tracked Events

EventTrigger
message_presentedAn in-app message is displayed
message_actionUser taps an action in the message
message_dismissedMessage is closed

Full Example

import AppDNASDK

class AppCoordinator: AppDNAInAppMessageDelegate {
    func setup() {
        AppDNA.inAppMessages.setDelegate(self)
    }

    func startOnboarding() {
        // Suppress messages during onboarding
        AppDNA.inAppMessages.suppressDisplay(true)
        presentOnboardingFlow()
    }

    func onboardingDidFinish() {
        // Resume messages after onboarding
        AppDNA.inAppMessages.suppressDisplay(false)
    }

    // MARK: - AppDNAInAppMessageDelegate

    func onMessageShown(messageId: String, trigger: String) {
        // Optionally track in your own analytics
    }

    func onMessageAction(messageId: String, action: String, data: [String: Any]?) {
        switch action {
        case "deep_link":
            if let url = data?["url"] as? String { navigate(to: url) }
        case "dismiss":
            break
        default:
            break
        }
    }

    func onMessageDismissed(messageId: String) {
        // Message closed
    }

    func shouldShowMessage(messageId: String) -> Bool {
        return true
    }
}
In-app messages are created in the Console under Engagement > In-App Messages. Design the message, set trigger rules, and publish. The SDK handles everything else.