In-App Messages

To clarify the capabilities of the MoEngage SDK, our In-App messaging feature supports two distinct rendering mechanisms. The SDK allows you to display both depending on your campaign configurations:

  • Native In-Apps: These use standard Android native UI elements to construct and display the in-app message.
  • HTML In-Apps: These render a custom web-based payload (HTML/CSS/JS) inside a WebView, allowing for complete design flexibility.

Latest_Popup image.png

SDK Installation

Installing using BOM

Integration using BOM  is the recommended way of integration; refer to the Install Using BOM document. Once you have configured the BOM add the dependency in the app/build.gradle file as shown below

build.gradle
dependencies {
    ...
    implementation("com.moengage:inapp")
}

Once the BOM is configured, include the specific MoEngage modules required for the application. 
Note: Version numbers are not required for these dependencies; the BOM automatically manages them.

Requirements for displaying images and GIFs in InApp

Starting InApp version 7.0.0, SDK requires Glide to show images and GIFs in the in-apps. You need to add the below dependency in your build.gradle file.

Groovy

dependencies {
 ...
 implementation("com.github.bumptech.glide:glide:4.16.0")
}

Display InApp

MoEngage can not show the InApp by default, and the app should call the following method in the places where necessary to show the InApps to the user. We recommend adding this method in onStart() of your activity or onResume() of your fragment. MoEInAppHelper.getInstance().showInApp(context) 

Kotlin
MoEInAppHelper.getInstance().showInApp(context)

 

Display Nudges

Starting with version 7.0.0, MoEngage InApp SDK supports displaying Non-Intrusive nudges. 

MoEngage can not show the Nudges by default, and the app should call the following method in the places where necessary to show the Nudges to the user. We would recommend you add this method in onStart() of your activity or onResume() of your fragment. MoEInAppHelper.getInstance().showNudge(context)

Kotlin
MoEInAppHelper.getInstance().showNudge(context)

 

Handling Configuration change

Starting SDK version 11.4.00, in-apps are supported in both portrait and landscape modes. SDK internally handles in-app display on orientation change when the activity restart is handled by the system.

In case your activity is handling the configuration change by itself, you have to notify the SDK by invoking MoEInAppHelper.getInstance().onConfigurationChanged() API for SDK to redraw the in-app when the activity receives onConfigurationChanged() callback from the framework.

Kotlin Java
override fun onConfigurationChanged(newConfig: Configuration) {
    super.onConfigurationChanged(newConfig)
    MoEInAppHelper.getInstance().onConfigurationChanged()
}

 

Contextual InApp

You can restrict the in-apps based on the user's context in the application, apart from restricting InApp campaigns on a specific screen/activity. To set the user's context in the application, use setInAppContext() API, as shown below.

Set Context

Call the below method in the onStart() of your Activity or Fragment before calling showInApp().

Kotlin Java
MoEInAppHelper.getInstance().setInAppContext(setOf("context1", "context2", "context3"))

The context is not the same context as Android Context.  This user's context in the application flow.

Reset Context

Once the user is moving out of the context, use the restInAppContext() API to reset/clear the existing context.

Kotlin Java
MoEInAppHelper.getInstance().resetInAppContext()

Code example below:

Kotlin Java
 
      // Activity
      class MyCustomActivity: Activity() {
        override fun onStart() {
           super.onStart()
           MoEInAppHelper.getInstance().setInAppContext(setOf("context1", "context2"))
           MoEInAppHelper.getInstance().showInApp(this)
       }
        override fun onStop() {
           super.onStop()
           MoEInAppHelper.getInstance().resetInAppContext()
       }
      }
      


// Fragment class MyCustomFragment: Fragment() { override fun onStart() { super.onStart() // Fragment's onStart code // context1 and context2 can be changes as per screen/requirement MoEInAppHelper.getInstance().setInAppContext(setOf("context1", "context2")) MoEInAppHelper.getInstance().showInApp(this) } override fun onStop() { super.onStop() // Fragment's onStop code MoEInAppHelper.getInstance().resetInAppContext() } }

WebView Customization

Starting with In-App SDK version 9.6.0, the SDK supports customizing the underlying WebView used to render HTML In-App messages. This allows for modifying the WebView settings, adding custom JavaScript interfaces, and implementing other configurations to the WebView used to render HTML In-Apps.

To customize the WebView, you must invoke the MoEInAppHelper.getInstance().setInAppWebViewCustomizer() API. Any custom settings defined using this API will override the default MoEngage In-App WebView settings.

Kotlin Java
MoEInAppHelper.getInstance().setInAppWebViewCustomizer {
    addJavascriptInterface(MyBridge(), "bridge")
    settings.mediaPlaybackRequiresUserGesture = false
}

Self-Handled InApps

Self-handled In-Apps are messages that the SDK delivers to the application, and the application builds the UI using the SDK's delivered payload.

warning

Critical

Listener-based APIs are deprecated as of In-App version 9.10.0 and will be removed in version 11.0.0. MoEngage recommends migrating to the success/failure callback-based APIs.

Single Self-Handled InApps

To get the self-handled in-app, use the below API:

Success/failure callback-based APIs (Recommended)

Kotlin Java
MoEInAppHelper.getInstance().getSelfHandledInApp(
    context = this,
    onSuccess = { campaignData -
        // Success callback
    },
    onFailure = { error -
      // Failure callback
    }
)

The  onSuccess and onFailure are an instance of SuccessCallback<SelfHandledCampaignData?> and  FailureCallback.

Listener-based APIs

Kotlin Java
MoEInAppHelper.getInstance().getSelfHandledInApp(context, listener)

The listener is an instance of SelfHandledAvailableListener.

This method should be called in the onResume() of your Fragment or onStart() of your activity.
The above method is asynchronous and does not return the payload immediately, once the payload is available onSelfHandledAvailable(), the listener callback would be called with the payload.

Event-Triggered Self Handled InApps

To get a callback for an event triggered, implement SelfHandledAvailableListener and register for a listener using MoEInAppHelper.getInstance().setSelfHandledListener(). SDK will notify the registered listener once the campaign is available.

We recommend registering this listener in the onCreate() of the Application class if the trigger event can happen on multiple screens.

Multiple Self-Handled InApps

info

Information

  • This feature requires a minimum catalog version 4.5.0
  • Event-triggered multiple self-handled inapps are not supported.

Fetch Multiple Self Handled Campaigns using getSelfHandledInApps(). The MoEngage SDK will return up to 5 campaigns(in the order of campaign priority set at the time of campaign creation) in the campaigns available callback method onCampaignsAvailable().

Success/failure callback-based APIs (Recommended)

Kotlin Java
MoEInAppHelper.getInstance().getSelfHandledInApps(
    context = this,
    onSuccess = { campaignsData -
        // Success
    },
    onFailure = { 
      // Failure 
    }
)

The  onSuccess and onFailure are an instance of SuccessCallback<SelfHandledCampaignData?> and  FailureCallback.

Listener-based APIs

Kotlin Java
MoEInAppHelper.getInstance().getSelfHandledInApps(context, listener)

The listener is an instance of SelfHandledCampaignsAvailableListener.

This method should be called in the onResume() of your Fragment or onStart() of your activity.
The above method is asynchronous and does not return the payload immediately, once the payload is available onCampaignsAvailable() callback of the listener would be called with the payload.

Tracking Statistics for Multiple Self-Handled In-Apps

The onCampaignsAvailable() callback method returns SelfHandledCampaignsDatawhich contains a list of SelfHandledCampaignData objects. The statistics for each SelfHandledCampaignData object must be tracked individually below APIs.

Fetching Contextual Multiple Self-Handled InApps

To fetch contextual multiple self-handled inapps, set the inapp contexts using setInAppContext() before calling getSelfHandledInApps(). This will return a list of contextual and non-contextual inapps(in the order of campaign priority set at the time of campaign creation).

Campaign Selection Logic

  • Default Limit: By default, only 5 campaigns will be fetched. 
  • Priority-Based Selection: Campaigns are delivered based on their priority and last updated time. It checks for priority first and then checks the last updated time on conflicting priorities
  • Exclusion criteria: Campaigns are only excluded based on specific rules like frequency capping, eligibility criteria, campaign status, or priority limits.

 

Example Scenario: If you have 6 campaigns with different priorities, published time and contexts:

  • Context 1: Campaign 1 (P0, T2), Campaign 2 (P1, T3), Campaign 3 (P2, T6)
  • Context 2: Campaign 4 (P0, T1), Campaign 5 (P1, T5)
  • Context 3: Campaign 6 (P0, T4)

Following campaigns will be delivered in this order: [Campaign 4, Campaign 1, Campaign 6, Campaign 2, Campaign 5]

 

Selection Algorithm:

  1. Filter campaigns by user eligibility and targeting criteria
  2. Sort by campaign priority (P0, P1, P2, etc.)
  3. For campaigns with same priority, sort by most recent update timestamp
  4. Return top 5 campaigns 

 

Best Practices for Campaign Organization for multiple self handled campaigns

For optimal performance across multiple contexts on a single page, organize your campaigns like this:

  • Context 1 (Homepage): Campaign A (P0), Campaign B (P1)
  • Context 2 (Product): Campaign C (P0), Campaign D (P1)
  • Context 3 (Checkout): Campaign E (P0)

This ensures each context has relevant campaigns without hitting the 5-campaign limit. 

Also, make sure that you set the priority of the campaigns you want to fetch accordingly, because the method will fetch all self-handled campaigns regardless of whether they are context-based or not.

 

Tracking Statistics for Self-Handled In-Apps

The application must notify MoEngage SDK whenever the In-App messages are displayed, clicked on, or dismissed, as the application controls these actions. The following methods are called to notify the SDK. The data object SelfHandledCampaignData provided to the application in the callback for self-handled in-app should be passed as a parameter to the following APIs.

Kotlin Java
// call whenever in-app is shown
MoEInAppHelper.getInstance().selfHandledShown(context, data)
// call whenever in-app is clicked
MoEInAppHelper.getInstance().selfHandledClicked(context, data)
// call whenever in-app is dismissed
MoEInAppHelper.getInstance().selfHandledDismissed(context, data)

For more information, refer to the API documentation.

In-Apps Callback

Lifecycle callback

To get callbacks whenever an InApp campaign is shown or dismissed, implement the InAppLifeCycleListener and register for the callbacks using MoEInAppHelper.getInstance().addInAppLifeCycleListener().

Click Callback

To handle user navigation or custom action, SDK provides a callback whenever an in-app widget is clicked with either Navigation or Custom action. To get callbacks implement the OnClickActionListener interface and register for the callbacks using MoEInAppHelper.getInstance().setClickActionListener().

Blocking InApps on Screens

Additionally, you can block in-app on a specific screen or handle the status bar visibility using the InAppConfig object and pass it to the SDK using the MoEngage.Builder object. Use the configureInApps() API to pass on the configuration to the SDK.

Kotlin Java
// List of activity classes on which in-app should not be shown
val inAppOptOut = mutableListOf<String>()
inAppOptOut.add(SplashActivity::class.java.name)
val moengage = MoEngage.Builder(application, "XXXXXXXX")
    .configureInApps(InAppConfig(inAppOptOut,true))
    .build()
MoEngage.initialise(moengage)
 

Testing In-App

Refer to this link to read more about how to create and test in-apps.

 

Implementing Embedded Nudges (Deprecated)

info

Note

Starting InApp version 7.0.0, embedded nudges are no longer supported.

 

Nudges are non-disruptive messages which can be placed anywhere in the activity.

Latest Nudge image.png

Add the following code in the activity/fragment layout file.

XML
<com.moengage.widgets.NudgeView
    android:id="@+id/nudge"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >
</com.moengage.widgets.NudgeView>

Using in an Activity

Get an instance of the nudge view in the onCreate() and initialize the nudge view in the onStart() of the Activity.

Using in a Fragment

Get an instance of the nudge view in the onCreateView() and initialize the nudge view in the onResume() of the fragment.

Use the below code to get the instance of the NudgeView and initialize it.

Kotlin Java
// get instance of the view
val nudge = findViewById(R.id.nudge)
// initialize
nudge.initialiseNudgeView(activity)

FAQs

Why doesn't <input type="file"> or camera/gallery upload work in HTML In-Apps on Android?

  • For In-App SDK version 9.6.0 and above, refer to the WebView Customization.
  • If you are using In-App SDK version below 9.6.0, perform the following steps:
    • Android's default WebView does not support file inputs. To enable this functionality, trigger a Custom Action from your HTML and handle it natively with an OnClickActionListener.
      Within the listener, launch your native file picker or camera logic. Ensure your app requests the required runtime permissions, such as CAMERA and READ_EXTERNAL_STORAGE.
      HTMLGUYS.png

Example:

Kotlin
val listener = OnClickActionListener { clickData ->
  if (clickData.action.actionType == ActionType.CUSTOM_ACTION &&
  (clickData.action as CustomAction).keyValuePairs["action"] == "uploadPhoto")
  {
  openImageChooser() // Your native camera/gallery function
  true // Indicates the action was handled
  } else {
  false
  }
  }
    • For iOS, file inputs work by default. However, for a consistent cross-platform implementation, we recommend using the same Custom Action approach.

Previous

Next

Was this article helpful?
3 out of 12 found this helpful

How can we improve this article?