In-App Messaging

In-app messages are toaster-style, foreground-only messages rendered by the SDK while the app is in the foreground. They do not require OS-level notification permission, so deliverability is close to 100% of your app install base.

This guide covers how in-app messages work, lifecycle callbacks, email collection, and how to create campaigns in ZMP. The SDK renders the in-app UI itself — your app does not wire up a view. In-app messages are a different surface from push notifications — see Push Notifications for the push surface.

On this page

How it works

The SDK uses a polling mechanism to fetch in-app messages. When a message is received, the SDK evaluates the app state to determine whether to display it. If the conditions are met, an in-app message is shown.

To monitor the lifecycle of a message (will appear, did appear, clicked, dismissed), implement the ZTInAppMessageLifeCycle interface and register it with ZetaClient.

Start and stop in-app messaging

In-app messaging is enabled by default. To stop displaying in-app messages:

ZetaClient.inApp.stop()
ZetaClient.INSTANCE.getInApp().stop();

To restart:

ZetaClient.inApp.start()
ZetaClient.INSTANCE.getInApp().start();

Note: The SDK does not persist the stop state; your app must manage this state. By default, the SDK starts displaying in-app messages on every launch.

Lifecycle callbacks

Implement ZTInAppMessageLifeCycle to react to message lifecycle events.

import net.zetaglobal.app.zetacore.inappmessage.ZTInAppMessageLifeCycle

class MyInAppListener : ZTInAppMessageLifeCycle {

    override fun willAppear(message: ZTInAppMessage) {
        // Called when the in-app message is about to be displayed
    }

    override fun didAppear(message: ZTInAppMessage) {
        // Called after the in-app message has been displayed
    }

    override fun onClicked(message: ZTInAppMessage, deeplink: String?) {
        // Called when the user clicks the in-app message
    }

    override fun onDismissed(message: ZTInAppMessage) {
        // Called when the user dismisses the in-app message
    }
}

ZetaClient.inApp.setCallBack(MyInAppListener())
import net.zetaglobal.app.zetacore.inappmessage.ZTInAppMessageLifeCycle;

ZetaClient.INSTANCE.getInApp().setCallBack(new ZTInAppMessageLifeCycle() {
    @Override
    public void willAppear(@NonNull ZTInAppMessage message) {
        // Called when the in-app message is about to be displayed
    }

    @Override
    public void didAppear(@NonNull ZTInAppMessage message) {
        // Called after the in-app message has been displayed
    }

    @Override
    public void onClicked(@NonNull ZTInAppMessage message, @Nullable String deeplink) {
        // Called when the user clicks the in-app message
    }

    @Override
    public void onDismissed(@NonNull ZTInAppMessage message) {
        // Called when the user dismisses the in-app message
    }
});

Creating an in-app message in ZMP

  1. Access the ZMP portal. Log in to ZMP.
  2. Configure the campaign.
    • Open the campaign window.
    • Select the channel Mobile InApp Push (the ZMP channel name for in-app messages).
  3. Compose the message. Click the In-App Messaging Setup content area, then:
    • Title — provide a title.
    • Body — provide the body.
    • On-click action — choose one of:
      • Deep Link — on tap, the SDK delivers the deep link URL through the lifecycle callback. Your app handles internal redirection.
      • Dismiss — no action on tap.
      • Web Link — the URL opens in one of:
        • In-App Web View — opens inside the SDK using Chrome Custom Tabs.
        • External Browser — opens in the device's default browser.
      • Email Submission — the email entered by the user in a form template is available via the form data on the message.
    • In-app message image — optional.
  4. Finalize. Click Done.
  5. Activate. Activate the campaign from the portal.

In-app email collection

In-app email collection prompts unknown users (users ZMP does not yet have email for) to submit their email via an in-app form.

  • Email collection triggers only for unknown users in ZMP.
  • Known users who already have an email identifier in ZMP skip this flow entirely.

The submitted email is available on the lifecycle callback payload:

override fun onClicked(message: ZTInAppMessage, deeplink: String?) {
    val email = message.inAppMessageFormData?.email
    if (email != null) {
        // Persist, forward to your backend, etc.
    }
}
@Override
public void onClicked(@NonNull ZTInAppMessage message, @Nullable String deeplink) {
    ZTInAppMessageFormData formData = message.getInAppMessageFormData();
    if (formData != null && formData.getEmail() != null) {
        String email = formData.getEmail();
        // Persist, forward to your backend, etc.
    }
}

Next

See also