Integration (iOS)
Enabling API-pull in-app messaging is a single config object on top of your normal SDK setup. When it is nil (the default), the SDK never issues a fetch, so the feature is off until you opt in. Set the config before PaylisherSDK.shared.setup(...).
import Paylisher
let config = PaylisherConfig(
apiKey: "phc_your_public_sdk_key",
host: "https://your-datastudio-host"
)
// …your other config…
let engageConfig = PaylisherEngageInAppConfig(
// Engage usually lives on a different host/prefix than analytics ingestion,
// so set the full URL explicitly (note the `/engage` prefix in most deployments):
fetchEndpoint: "https://api-eu.paylisher.com/engage/v1/push/inapp/fetch"
)
engageConfig.autoFetchOnForeground = true // default
engageConfig.maxMessages = 5
engageConfig.debugLogging = true // turn on while integrating
config.engageInAppConfig = engageConfig
PaylisherSDK.shared.setup(config)
Manual fetch (see Scenarios):
PaylisherSDK.shared.refreshEngageInAppMessages(target: "wallet")
// or, with no screen target:
PaylisherSDK.shared.refreshEngageInAppMessages()
Config reference — PaylisherEngageInAppConfig
Every field is optional. Identity fields are resolved by the SDK / Engage; you normally set only fetchEndpoint (when Engage is on a different host) and the tuning flags.
| Field | Type | Default | Purpose |
|---|---|---|---|
fetchEndpoint | String? | nil → {host}/v1/push/inapp/fetch | Full absolute URL of the fetch endpoint. Set this when Engage is not on your analytics host (the common case). The ack endpoint is derived as the sibling …/ack. |
sdkKey | String? | nil → SDK apiKey | The public key Engage uses to resolve your project/source. Override only if the in-app source differs from analytics. |
teamId / projectId / sourceId | String? | nil | Optional explicit identity. Normally omitted — Engage reverse-resolves them from sdkKey. |
autoFetchOnForeground | Bool | true | When true, the SDK fetches automatically on foreground and on screen change. When false, the SDK never fetches on its own — you drive it with refreshEngageInAppMessages(...). |
maxMessages | Int | 1 | How many messages a single fetch may return (clamped to 1...5). |
debugLogging | Bool | false | Verbose SDK logs for the fetch / render / ack path. |
excludedActivities | [String] | ["Splash"] | View-controller class-name fragments where a message must not render. Messages are queued and shown on the next non-excluded screen. |
excludedActivities and SwiftUIexcludedActivities matches the top view controller class name. It works for UIKit apps. In a pure SwiftUI app every screen lives under one host controller, so class-name matching cannot tell screens apart — gate screens with the manual, per-screen approach in Scenarios → Don't show on login/splash instead.
Verifying the fetch without a device
Exercise the exact request the SDK makes with curl. Use a fresh distinctId each time (delivered messages are de-duplicated per user):
curl -i -X POST "https://api-eu.paylisher.com/engage/v1/push/inapp/fetch" \
-H "Content-Type: application/json" \
-H "X-SDK-Key: phc_your_public_sdk_key" \
-d '{"distinctId":"probe-1","sdkKey":"phc_your_public_sdk_key","platform":"ios","maxMessages":5}'
201 {"messages":[]}→ auth is fine, but no campaign matched → see Campaign Setup.201 {"messages":[{…}]}→ the server path works end-to-end → test on device.401 {"message":"Invalid sdkKey"}→ the key does not resolve in this environment → see Troubleshooting.