Skip to main content
Beta. In-App Messaging is in beta and open to every Gameball account. Send questions and feedback to support@gameball.co.

Display In-App Messages

Add one call after you identify the customer and the Gameball SDK shows your dashboard campaigns inside the app: slide-ups, modals, and full screens, triggered by session start or by the events you already send. In-app messaging needs Gameball Flutter SDK 4.0.0 or later. It is opt-in: until you call startInAppMessaging, the module makes no requests and draws nothing. For campaign options, triggers, filters, priority, cooldown, quiet hours, and how the analytics are defined, see In-App Messaging Campaigns.

Requirements

No extra dependencies are added for in-app messaging. The SDK already ships firebase_messaging, url_launcher, and shared_preferences, which is what the module uses.

Install

pubspec.yaml
Upgrading from 3.x? SDK 4.0.0 raises the minimum platforms for the whole SDK to iOS 15.0 and Android API 24. Set minSdk = 24 in android/app/build.gradle, set platform :ios, '15.0' in ios/Podfile and IPHONEOS_DEPLOYMENT_TARGET = 15.0 for the Runner target, then run pod install. No Dart changes are needed: every 3.x call keeps its signature. See Migration Notes.
Call init first: until the API key is set, startInAppMessaging is ignored. Then identify the customer with initializeCustomer. For a new customer, start messaging from its callback, so the customer exists in Gameball before the first sync.

Start Messaging

Give your MaterialApp a navigator key and pass the same key to startInAppMessaging. Call it as soon as the customer is known. It is safe to call before the first frame, once runApp or WidgetsFlutterBinding.ensureInitialized() has run.
onNavigate and sessionTimeout are read the first time messaging starts in the app process. Later calls, including after stopInAppMessaging(), keep the original values unless you pass a different navigatorKey. Call stopInAppMessaging() when the customer logs out. It dismisses anything on screen, flushes pending analytics, clears the module’s state, and deletes stored personalization values from the device. Check isInAppMessagingStarted if you need to know whether it is running. App lifecycle is observed automatically. If messaging is running and you call initializeCustomer with a different customer ID, messaging switches to that customer: it dismisses anything on screen, syncs that customer’s campaigns, and attributes analytics to them.

Control Display and Actions

beforeDisplay

To keep messages off screen for a whole flow such as checkout, return discard: a message held with later can appear as soon as another message is dismissed. The hook is synchronous. If it throws, the SDK logs and shows the message.

onAction

Called for every tap with the message, the button (or null for the surface), and the parsed action. Return true to take over, or false for built-in handling. In both cases the click is reported and the message is dismissed before the action runs, so a navigation transition is never covered by the overlay. If onAction throws, the SDK logs it and runs its built-in action. Before a built-in open-URL or navigate action, the SDK spends up to 800 ms sending queued analytics.

onNavigate

When supplied, every navigate action is handed to you with its route name and optional arguments map. When absent, the SDK calls Navigator.pushNamed on your navigator. A route that is not registered is logged, never thrown, and so is an exception thrown by onNavigate.

Actions

GameballClickAction is a sealed class, so an exhaustive switch is safe.

Observe Messages

onInAppMessage is a broadcast stream of every campaign that wins a trigger, emitted before beforeDisplay is consulted, whatever happens to it next. A runner-up waiting behind another message is not emitted. It is observation only, and subscribing does not affect analytics. Subscribe any time, including before startInAppMessaging.
GameballInAppMessage exposes id, type, header, body, imageUrl, iconUrl, buttons, clickAction, extras, style, layout, orientation, slidePosition, showCloseButton, dismissOnScrimTap, and autoDismissAfter. id is a diagnostic string: the campaign ID, or campaignId/variationId. extras holds the campaign’s custom key-value pairs as strings. An exhaustive switch on type must handle unsupported, although the SDK never selects such messages. The message on the stream, and the one passed to beforeDisplay and onAction, carries the campaign text before personalization, so it can contain {token} placeholders.

Events and Purchases

Campaigns trigger on the events you already send with sendEvent. Triggers are evaluated on the device as soon as you call sendEvent or logPurchase, whether or not the request to Gameball succeeds. The event name must match the campaign’s event name exactly, including letter case. The event’s properties are what the campaign’s filters read, and every filter must pass. Equals compares numbers numerically and other values as exact text; contains ignores letter case. Numeric comparisons accept numbers or numeric strings such as "100.5", and a property the event does not carry never matches. logPurchase sends a regular purchase event to Gameball through sendEvent, with productId, price, currency, and quantity as properties, so it is recorded even when messaging is not running:
Entries in properties are added to the event and replace productId, price, currency, or quantity when they use the same key. callback and sessionToken behave as they do for sendEvent. If you already send purchase events yourself, switch to logPurchase rather than sending both.

Language

There is no separate language setting for messages. Each sync requests the language you set most recently with setLanguage or as preferredLanguage in initializeCustomer, and otherwise the lang given to init. Any code outside the supported list (en, ar, fr, es, de, pt, pl, it, hu, zh-tw, nl, sv, no, dk, ja) falls back to en, including regional variants such as ar-EG. The value is read at sync time, so a change takes effect at the next session. Layout direction follows your app’s Directionality, not the message language: when your app runs right to left, messages mirror automatically.

Personalization

Campaign text can include placeholders such as {player_name} in the header, body, and button labels. See In-App Messaging Campaigns for the list. Just before a message with placeholders displays, the SDK fetches the customer’s current values and fills them in. It waits at most 2 seconds, reuses the values for up to 1 minute, and fetches again after every event you send, so a message triggered by that event quotes current values. If the request fails, the SDK uses the last values it stored for the customer. Any placeholder still without a value, including every placeholder when the request times out, is removed, and the message still shows. Messages without placeholders skip the fetch.

Push Permission

The request push permission button action closes the message, then calls FirebaseMessaging.instance.requestPermission() and treats authorized and provisional as granted. It needs Firebase initialized in your app; if it is not, the SDK logs could not request push permission (…).
To use your own permission flow, handle the action in onAction and return true.

Behavior Reference

The campaign rules themselves are described in In-App Messaging Campaigns. This is what they mean in a Flutter app.

Logging and Troubleshooting

The SDK logs each decision with its reason and the campaign ID, prefixed [GameballIAM], through debugPrint. Filter your flutter run or flutter logs output on that prefix. Logging is on in debug builds and off in profile and release builds. To turn it on in a release build while you reproduce an issue, set it before startInAppMessaging, and remove it before you ship:
Nothing shows at all? Check in order: logging is on (a debug build, or gameballInAppMessagingLogging = true), init ran before startInAppMessaging, the customer is initialized, you are running on iOS or Android, the navigator key is the one on MaterialApp, the campaign is live and the customer is in its audience and platform, its artwork uses https://, the account cooldown or quiet hours are not suppressing it, and the campaign has not already been shown to this customer. A fresh customer ID is the quickest way to reset frequency history while testing.

API Reference


Launch Checklist

1

Raise platform minimums

iOS deployment target 15.0 and Android minSdk 24, with gameball_sdk at 4.0.0 or later.
2

Initialize and identify

init with the production API key, then initializeCustomer with a preferredLanguage.
3

Wire the navigator key

The navigatorKey passed to startInAppMessaging is the one on MaterialApp, or on GoRouter if you use go_router.
4

Register your routes

Every route name your campaigns use is registered, or onNavigate routes it.
5

Stop on logout

Call stopInAppMessaging() when the customer logs out.
6

Initialize Firebase if needed

Firebase is initialized if any campaign asks for push permission.
7

Test end to end

Events use the exact event names your campaigns expect and carry numeric properties as numbers where campaigns filter on them. Run one campaign on a fresh customer ID in a debug build and watch the [GameballIAM] log. Do not ship with gameballInAppMessagingLogging = true.

In-App Messaging Campaigns

Campaign options, triggers, delivery rules, and analytics definitions.

Track Events

Send the events your campaigns are triggered by.

Push Notifications

Reach customers when the app is closed.

Go-Live Checklist

Verify the full Flutter integration before release.