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 callstartInAppMessaging, 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
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 yourMaterialApp 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 (ornull 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, everynavigate 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 withsendEvent. 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:
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 withsetLanguage 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 callsFirebaseMessaging.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 (…).
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.Related Articles
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.