Docs
grovs.io Start for free

In-app messages

Show in-app messages from the Grovs dashboard in your React Native app, hold them back on some screens, and react to taps and answers.

Requires React Native SDK 3.1.0

In-app messages are dashboard campaigns: a banner, modal, full-screen cover, system alert, question or your own HTML. The native SDKs download live campaigns, pick one on the device for each app open, screen view or event, and draw it above your React Native views. To create campaigns, see In-app messages.

No code is required. Once the SDK is configured, campaigns show. Use the calls below to keep messages off some screens, pause them during a flow, or react to what the user did.

In-app messages need the next react-native-grovs-wrapper release (iOS SDK 3.1, Android SDK 3.1.0).

Triggers

A campaign triggers on app open, a screen view or a custom event from track. React Native apps turn native screen tracking off (autoTrackScreenViews: false), so screen triggers and excluded screens use the names you send with startScreenTracking or trackScreenView.

Sync, frequency caps, priority and offline behaviour are native: see How messages reach the device.

React to messages

onInAppMessage gets an event for each step of a message:

typescript
import Grovs from 'react-native-grovs-wrapper';
 
const subscription = Grovs.onInAppMessage((event) => {
    switch (event.type) {
        case 'clicked':
            // payload is set for a key-value action
            if (event.payload?.screen === 'refill') {
                navigation.navigate('Refill');
            }
            break;
        case 'answered':
            console.log(event.campaignId, event.value, event.comment);
            break;
    }
});
 
// When you no longer need it
subscription.remove();
typeFieldsWhen
showncampaignIdThe message is on screen.
clickedcampaignId, buttonId?, payload?A button or the message was tapped. payload carries the pairs of a key-value action.
dismissedcampaignId, reasonThe message closed. reason is close_button, backdrop, swipe, app or orientation. Other values may be added later.
answeredcampaignId, value, comment?A question was answered. value is a number for stars, or the chosen option's ID (string).
failedmessage, campaignId?The message couldn't be shown. campaignId is set on Android only.

Events that happen before your first onInAppMessage call, such as a message shown on app open, are kept (up to 20, oldest dropped first) and delivered when you subscribe. After a JavaScript reload they're kept again until the next subscription.

The wrapper owns the native in-app delegate (Grovs.inAppDelegate on iOS) and listener (Grovs.setInAppListener on Android). Don't set them in native code, or onInAppMessage stops receiving events.

There's no way to veto a single message from JavaScript, unlike the native grovsShouldShowInAppMessage. Use pause, discard and excluded screens.

Button actions

Each button, and the message itself, has one action. The native SDK performs it, reports the click and sends a clicked event.

ActionWhat happens
CloseCloses the message.
Open URLOpens the URL.
Key-valueCloses the message and sends the pairs as payload. Route in your own code.
Request push permissionShows the system prompt, or opens your app's notification settings if the person declined before. On Android 13+ it needs POST_NOTIFICATIONS in your manifest; without it, campaigns with this action aren't shown.
Request app ratingiOS shows the system review prompt. Android needs the Play review library in your app; without it, campaigns with this action aren't shown.
Open storeOpens your app's store page if the project has one configured. Otherwise campaigns with this action aren't shown.

For ratings on Android, add to android/app/build.gradle:

Groovy
implementation 'com.google.android.play:review-ktx:2.0.2'

Hold messages back

typescript
// Pause during checkout or a video. The newest highest priority message waits.
Grovs.pauseInAppMessages();
 
// Show messages again, starting with the one that waited, if it still qualifies.
Grovs.resumeInAppMessages();
 
// Drop the waiting message. dismissCurrent also closes the one on screen. Defaults to false.
Grovs.discardInAppMessages({ dismissCurrent: true });
 
// No message shows on these screens.
Grovs.setInAppExcludedScreens(['Checkout', 'Onboarding']);

Excluded screens match the names sent through trackScreenView or startScreenTracking. Each call replaces the list. Non-string entries are dropped.

Questions and HTML messages

Star ratings, single-choice questions, comment boxes and custom HTML (window.grovs, data attributes, {{user.*}} placeholders) are drawn by the native SDKs. See Questions and Custom HTML messages. An answer arrives as an answered event.

Test messages

Send test on a dashboard campaign sends it to every device of one person, matched by the identifier from setIdentifier. Without setIdentifier, test messages don't reach the device. The device shows the test at its next sync, ignoring triggers, conditions and limits. To see it sooner, background the app and return after a minute.

Debugging

typescript
Grovs.setDebug('info');
Grovs.setInAppDebugLogging(true);

setInAppDebugLogging(true) logs each campaign considered for an event and why it was skipped. Logs go to Xcode and Logcat, not the Metro console.

Reserved event names

The SDK reports message views, clicks, dismissals and answers as events. track refuses these names:

in_app_viewed, in_app_clicked, in_app_dismissed, in_app_answered, in_app_commented, in_app_held, push_open, push_delivered, push_held, journey_entered, journey_held, journey_path.

The old inbox

displayMessages() and numberOfUnreadMessages() are deprecated. They resolve without showing anything, and the count is always 0. Remove inbox buttons and unread badges. See Deprecated.

See also

Last updated 2026-10-26
Was this page helpful?