Campaign Setup (Dashboard)
The SDK only renders what Engage returns. A fetch returns a message only when a campaign matches the requesting user and is authored for API-pull delivery. This page lists exactly what a pull campaign must look like. (The dashboard steps are the same for iOS and Android.)
Requirements checklist
For a fetch to return a campaign, all of the following must hold:
- ✅ Delivery mode = API pull — the campaign's
notificationJson.deliveryModeis"api". This is the single most common miss: in-app campaigns default to FCM/APNs delivery, and a push campaign is invisible to the pull endpoint. - ✅ Status = LIVE — not draft, paused, or scheduled-for-later.
- ✅ Type = In-App (
notificationType=InApp). - ✅ Audience =
EveryoneorAudience— not action/trigger-based. Action-based campaigns are not pullable. - ✅ Same project — the campaign lives under the project/source that your SDK
sdkKeyresolves to (see Environment matching below). - ✅ Time window open —
displayTimeis in the past (or unset) andexpireDateis in the future (or unset). - ✅ Screen target matches — if
condition.targetis set, the SDK's fetch must send the sametarget(see Screen targeting). Leave it empty for a campaign that may appear on any screen.
A pull campaign is delivered by the SDK polling — there is no "Send now" step. If the dashboard reports something like reason: API_DELIVERY / "manual dispatch is not used" when you try to dispatch it, that is expected and correct: the campaign is already live for the SDK to pull. Do not try to dispatch it manually.
Audience: Everyone vs Audience
| Type | Who receives it | Notes |
|---|---|---|
| Everyone | Every user that polls | No cohort lookup. Best for your first test — it removes audience matching from the equation. |
| Audience | Users in the targeted cohort(s) | The user must be resolvable as a member. An anonymous user (not yet identify()-ed), or a user whose profile lives in a different environment than the in-app source, will not match. |
For a first end-to-end test, start with Everyone. Once that renders on the device, switch to Audience to validate targeting.
Timing fields (condition)
| Field | Unit | Meaning |
|---|---|---|
displayTime | epoch milliseconds | Earliest time the message may show. Unset = show immediately. The SDK also applies a 60s tolerance. |
expireDate | epoch milliseconds | After this, the campaign is no longer returned / shown. Unset = never expires. |
delay | minutes | Extra delay before rendering after it is fetched. 0 = render as soon as possible. |
target | string | Screen name for screen targeting. Empty = any screen. |
displayTime / expireDate are epoch milliseconds, and delay is in minutes (a delay of 5 defers rendering by five minutes). For a quick test: no displayTime, expireDate far in the future, delay = 0.
Environment matching
The sdkKey your app sends must resolve to the same project/source that owns the campaign, in the same Engage environment the app fetches from.
- Key ↔ project. The public
sdkKey(your SDKapiKey, orengageInAppConfig.sdkKey) identifies a project. Create the campaign under that project — not a different one that happens to be open in the dashboard. - App ↔ environment. The campaign lives in whatever Engage environment your
fetchEndpointpoints at (e.g.api-eu). Create the campaign in the dashboard for that same environment, not a different region/instance.
A mismatch here is the usual reason a correctly-authored, LIVE campaign still returns an empty messages array — see Troubleshooting.
Rendering content
Author real in-app content (title, body, image, buttons, layout) for the campaign. A campaign that matches but has empty layout content will fetch successfully yet render an empty/blank message. Supported layouts include native banner, modal, fullscreen, and carousel.