In-App Messages in Mobile App

TRUETECH is engaged in the development, support and maintenance of iOS, Android, PWA mobile applications. We have extensive experience and expertise in publishing mobile applications in popular markets like Google Play, App Store, Amazon, AppGallery and others.
Development and support of all types of mobile applications:
Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Showing 1 of 1 servicesAll 1735 services
In-App Messages in Mobile App
Medium
~2-3 business days
FAQ
Our competencies:
Development stages
Latest works
  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    756
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1054
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    862
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    445

Implementing In-App Messages in Mobile Apps

In-App Messages — these are not push notifications. They display only when the app is open, don't require permissions, don't go to notification center. A modal window on app launch, a banner at the bottom when needed, fullscreen offer after first purchase — all of this is IAM. The main technical task: show them at the right moment without annoying the user.

Platform Solutions vs Custom Implementation

Two paths: use an SDK (OneSignal IAM, Firebase In-App Messaging, Braze, Intercom, Appcues) or implement your own mechanism. SDK — quick start but limited UI customization. Custom solution — full control over appearance and display logic.

Firebase In-App Messaging — free, integrates with Firebase Analytics events:

// iOS — automatically shows IAM when logging specified event
Analytics.logEvent("checkout_started", parameters: [
    "cart_value": 450.0
])
// In Firebase Console: IAM trigger = event "checkout_started", condition cart_value > 200
// Android
FirebaseAnalytics.getInstance(context).logEvent("checkout_started") {
    param("cart_value", 450.0)
}

Firebase IAM shows message automatically — the app doesn't need to do anything else. Limitation: UI is only edited through Firebase Console (templates), no full control over animations and styles.

Custom Implementation: Architecture

For full control, implement your own IAM engine. Components:

  1. Campaign Manager — fetches list of active campaigns from backend (or Remote Config).
  2. Trigger Engine — tracks app events, matches with campaign conditions.
  3. Display Controller — manages display queue, anti-spam rules.
  4. UI Layer — renders specific message type.
// Android — Display Controller
class InAppMessageController(
    private val campaignRepo: CampaignRepository,
    private val displayHistory: DisplayHistoryDao
) {
    suspend fun onEvent(eventName: String, params: Map<String, Any> = emptyMap()) {
        val campaigns = campaignRepo.getActiveCampaigns()
        val eligible = campaigns.filter { campaign ->
            campaign.trigger.eventName == eventName &&
            matchesConditions(campaign, params) &&
            !wasShownRecently(campaign.id)
        }

        // Show only one message at a time — priority by score
        eligible.maxByOrNull { it.priority }?.let { campaign ->
            displayHistory.record(campaign.id, System.currentTimeMillis())
            showMessage(campaign)
        }
    }

    private suspend fun wasShownRecently(campaignId: String): Boolean {
        val lastShown = displayHistory.getLastShownTime(campaignId) ?: return false
        val cooldownMs = 24 * 60 * 60 * 1000L // 24 hours
        return System.currentTimeMillis() - lastShown < cooldownMs
    }
}

UI Types and How to Display Them

Modal (central popup). On iOS — through UIViewController with modalPresentationStyle = .overCurrentContext and transparent background:

let iamVC = InAppMessageViewController(campaign: campaign)
iamVC.modalPresentationStyle = .overCurrentContext
iamVC.modalTransitionStyle = .crossDissolve
topViewController?.present(iamVC, animated: true)

Finding topViewController in complex navigation (TabBar + NavigationController + modals) — a separate task. Recursive helper through presentedViewController and children.

Bottom Sheet / Banner. On Android — BottomSheetDialogFragment or custom View added through WindowManager over current content. Second option works even in fragments without knowing the current screen, but requires SYSTEM_ALERT_WINDOW permission — undesirable.

Better — BottomSheet through supportFragmentManager:

class InAppBottomSheet : BottomSheetDialogFragment() {
    // ... campaign data binding
    override fun onCreateView(...) = InAppBottomSheetBinding.inflate(inflater).also {
        binding = it
    }.root
}

InAppBottomSheet.newInstance(campaign).show(supportFragmentManager, "iam_bottom_sheet")

Fullscreen. Separate Activity with FLAG_FULLSCREEN — most reliable on Android. On iOS — UIViewController with modalPresentationStyle = .fullScreen.

Targeting and Display Conditions

Condition Type Example
Trigger event screen_viewed = "home", purchase_completed
Session count session_count >= 3
User attribute subscription = "free", days_since_install >= 7
Time window only 10:00–22:00
Frequency cap no more than once per 48 hours

Without frequency cap, IAM becomes annoying. Store last shown time of each campaign — in Room (Android) or Core Data / UserDefaults (iOS, if data is small).

Analytics

Minimal set of events for IAM analytics:

  • iam_displayed — message shown
  • iam_dismissed — closed without action
  • iam_action_clicked — action button clicked (with action_id)
  • iam_converted — target event after display (purchase, signup)
Analytics.logEvent("iam_action_clicked", parameters: [
    "campaign_id": campaign.id,
    "action_id": "upgrade_now",
    "screen": currentScreenName
])

Timeframe

Firebase IAM integration with event triggers — 2–3 days. Custom IAM engine with Campaign Manager, Trigger Engine, three UI types (modal, banner, fullscreen), analytics and frequency caps — 10–15 working days.