Ethnio iOS SDK
Preview: The Ethnio iOS SDK is a preview. It is not ready for production apps yet. The SDK will be available soon. Until then, use the WebView implementation in App intercepts implementation using WebView or WKWebView.
What the iOS SDK does
An app intercept shows a study as a card inside your iOS app. The participant answers the study in the card and does not leave your app. For the basic idea, read The basic idea of app intercepts (iOS, Android).
The Ethnio SDK is a native library that your developer adds to the app one time. The SDK asks Ethnio if the card can show, loads the study and shows the card. It also counts the views and opens the preview links.
Your app decides when the card can show. Ethnio decides if the card shows. The card shows only when all of these conditions are true:
- The study is turned on.
- The targeting rules of the study match.
- The sampling picks the phone.
- The show-once cookie does not stop the card.
- The request does not look like a robot's request.
Quick start
- Copy the code and the SDK key from the Publish page. Read Find the code and the SDK key on the Publish page.
- Add the SDK to your app with Swift Package Manager. Read Install the SDK.
- Set the SDK key one time when the app starts. Read Set the SDK key.
- Register the app intercept and show the card. Read Register the app intercept and show the card.
- Add the URL scheme of your app for the QR code preview. Read Preview a study in your app with a QR code.
- Do a test with a test study that is turned on. Read Check the installation.
- Release a new version of your app. Read Release the app.
Before you start
What the researcher needs
- App intercepts need the Enterprise plan.
- The study must use the Beta Editor. A study in the legacy editor cannot use the SDK.
- The developer of your app must add the SDK and release a new version of the app.
What the developer needs
- iOS 15 or later.
- Swift and Swift Package Manager. The SDK has no Objective-C interface, so call it from Swift code.
- Ethnio does not publish a CocoaPods package.
Find the code and the SDK key on the Publish page
The SDK key is the key of your organization. Every study of your organization uses the same key. Each request of the SDK needs it.
- Open the study in Ethnio.
- Go to the Publish page.
- Find the section "App intercept".
- Under "How your app shows the intercept", select "iOS SDK".
- Click "Copy" to copy the code for this study.
- Click "Copy key" to copy only the SDK key.
The code on the Publish page has the id of the study and the SDK key of your organization. Give the code or the key to your developer.
Install the SDK
When the SDK is available, add it with Swift Package Manager:
- In Xcode, select File, then Add Package Dependencies.
- Paste
https://github.com/ethnio/ethnio-iosinto the search field. - Select "Up to Next Major Version" from 1.0.0.
- Add the product
EthnioSDKto your app target.
If you add packages in a Package.swift file, add the SDK to the dependencies of the package and of your target. Use the same version rule, from 1.0.0:
dependencies: [
.package(url: "https://github.com/ethnio/ethnio-ios", from: "1.0.0"),
],
targets: [
.target(
name: "MyApp",
dependencies: [
.product(name: "EthnioSDK", package: "ethnio-ios"),
]
),
]
Set the SDK key
Main thread: Call the SDK on the main thread. The type Ethnio is @MainActor . From code that runs on another thread, put the calls in Task { @MainActor in ... } .
Set the SDK key one time, before the first call to the SDK:
Ethnio.sdkKey = "<key>"
Replace <key> with the key from "Copy key". The SDK removes spaces and line breaks at the start and at the end of the key. An empty key counts as no key. A key with a space or a line break inside it also counts as no key.
If the key is not set, the SDK sends no request and shows no card. Every call except hide does nothing. The SDK writes an error in the Xcode console.
Register the app intercept and show the card
The SDK shows the card in two steps:
- Call
registerInterceptto ask Ethnio if the card can show now. - If the answer is yes, call
displayto show the card.
import EthnioSDK
// At launch, or when you know who the user is.
Task { @MainActor in
// Set your organization's SDK key once, before the first call.
Ethnio.sdkKey = "<key>"
if await Ethnio.registerIntercept(studyId: 1, embeddedData: ["plan": "pro"]) {
Ethnio.display(studyId: 1)
}
}
// Later, on any screen.
if Ethnio.isActive(studyId: 1) { Ethnio.display(studyId: 1) }
Ethnio.onEvent = { event in print(event) }
Replace 1 with the id of your study. The code on the Publish page shows the id.
The calls
| Call | What it does |
|---|---|
Ethnio.registerIntercept(studyId:embeddedData:language:preview:) |
Sends the status request to Ethnio. Returns true if the card can show now. The SDK keeps the answer for isActive. If the request fails, the call returns false. |
Ethnio.isActive(studyId:) |
Gives the last answer of the status request. It sends no request. Before the first answer, it gives false. |
Ethnio.statusReason(studyId:) |
Gives the reason for the last "no" answer, such as turned_off. It gives nil while the study can show. |
Ethnio.display(studyId:) |
Loads the study and shows the card when the page is ready. Returns true when the load starts. Returns false when the card cannot show. A failed event then gives the reason. |
Ethnio.hide() |
Closes the card, or stops a card that still loads. The app gets the event closed(reason: .app). |
Ethnio.clearCookie(studyId:) |
Removes the show-once cookie of the study from the phone. Use it only for tests. After this call, call registerIntercept again. |
Ethnio.handleLink(_:) |
Opens a preview link from the QR code on the Publish page. Returns true for an Ethnio link and false for the other links of your app. |
If your app does not use Swift concurrency, use registerIntercept with a completion closure. The closure runs on the main thread:
Ethnio.registerIntercept(studyId: 1, embeddedData: ["plan": "pro"]) { active in
if active { Ethnio.display(studyId: 1) }
}
If you call registerIntercept again for the same study, the new embedded data replaces the old data. The SDK then asks Ethnio again.
Where to call the SDK
The card shows in its own window over the window scene of your app. Thus, display needs no view controller. It needs a window scene that is on screen. If no window scene is on screen, the failed event has the reason noWindow .
SwiftUI: Set the key in the init() of your App . Call registerIntercept and display in a .task modifier on the root view.
import EthnioSDK
import SwiftUI
@main
struct MyApp: App {
init() {
// Set your organization's SDK key once, before the first call.
Ethnio.sdkKey = "<key>"
}
var body: some Scene {
WindowGroup {
ContentView()
.task {
if await Ethnio.registerIntercept(studyId: 1) {
Ethnio.display(studyId: 1)
}
}
.onOpenURL { url in _ = Ethnio.handleLink(url) }
}
}
}
UIKit: Set the key in application(_:didFinishLaunchingWithOptions:) . Call registerIntercept and display after a screen of your app is visible, for example in viewDidAppear(_:) .
// In application(_:didFinishLaunchingWithOptions:)
Ethnio.sdkKey = "<key>"
// In viewDidAppear(_:) of a view controller
Task {
if await Ethnio.registerIntercept(studyId: 1) {
Ethnio.display(studyId: 1)
}
}
Ethnio has no React Native or Flutter package. Such an app uses the WebView implementation.
Check the installation
Do this check with a debug build of your app before you release it.
- Set
Ethnio.logLevel = .debugbefore the first call to the SDK. - Ask the researcher for the id of a test study that is turned on.
- Call
registerInterceptwith the id of the test study. Do not setpreview: true. - Find the status line in the Xcode console. If the card can show, the line is
[Ethnio] status 1: true. - If the answer is no, the line has the status reason in parentheses, for example
[Ethnio] status 1: false (turned_off). - If the request failed, the line is
[Ethnio] status 1 failed:and the system error. - If the answer is no, read
Ethnio.statusReason(studyId:). Find the reason in Status reasons and failure reasons. - If the answer is yes, call
display. - Answer the questions in the card and submit.
- Find the
submittedevent in the Xcode console, for example[Ethnio] event submitted(studyId: 1, qualified: "qualified"). - Open the responses page of the study in Ethnio.
- Find the new response. Its referrer is "App Intercept (iOS)".
A card from a preview gives a response with the referrer "Preview". If the Cookie setting of the study is on, the card does not show again on this phone. For a new test, call Ethnio.clearCookie(studyId:) .
Test without real participants
Use one of these two methods:
- Preview: Open a test study with the QR code preview, or call
registerInterceptwithpreview: true. A preview ignores the turned-off state, the targeting rules, the sampling, the cookie and the robot check. A preview card writes no cookie. - Turned-on test study: Turn on a test study and set its Cookie setting to off. Then the card can show again after each close or submission. The targeting rules and the sampling still apply.
A turned-on study can also show to the people who use your app. Thus, give the test study targeting rules that match only your test phones.
Release the app
The card shows only in the versions of your app that include the SDK. A phone with an older version of your app shows no card.
- Remove the line that sets
Ethnio.logLevel = .debug. - Remove
preview: truefrom your calls. - Release the new version of your app.
- Tell the researcher which version of the app has the SDK.
Embedded data and language
Embedded data
The embeddedData parameter is a dictionary of text keys and text values. Ethnio uses it in two places:
- The targeting rules of the study.
- The embedded data questions of the study.
A value can contain any character, also + and ; . A targeting rule cannot read a key with brackets, such as user[plan] .
Some keys have a special meaning:
email,nameandphonefill the contact questions of the study. If a contact question has "Hide question if prepopulated" on, the participant does not see it.- The SDK does not send
preview,sdk_keyandl. Use the parameterspreviewandlanguageofregisterInterceptinstead. Set the key inEthnio.sdkKey. - The SDK does not send keys that start with
ethnio_. The SDK uses this prefix for its own parameters.
Language
The language parameter sets the language of the study texts. Use a BCP 47 code, such as fr or pt-BR .
What the SDK sends about the app
The SDK adds these parameters to the status request and to the page:
| Parameter | Value |
|---|---|
ethnio_platform |
Always ios. |
ethnio_os_version |
The iOS version, such as 17.5. |
ethnio_device |
The model identifier of the phone, such as iPhone16,1. |
ethnio_app_version |
The version of your app. |
ethnio_app_build |
The build number of your app. |
ethnio_sdk_version |
The version of the SDK. |
ethnio_app_sessions |
The number of app sessions on this phone. |
A targeting rule can use these seven names. The rule compares exact values. The response keeps the seven values, unless the Ethnio account has "Disable Metadata" on.
The page also gets the text size of the participant. The card follows the text size (Dynamic Type) up to 200%. The participant can also zoom with two fingers.
Events
Set Ethnio.onEvent to receive the events of the card. Each event comes on the main thread and has the studyId .
| Event | What it means |
|---|---|
displayed(studyId:) |
The card is on screen. |
submitted(studyId:qualified:) |
Ethnio saved the answers of the participant. qualified is "qualified", "disqualified" or "neutral". |
closed(studyId:reason:) |
The card closed. The reason is participant, app, ending or system. |
failed(studyId:reason:) |
The card did not show. The reason tells why. See the next section. |
Close reasons
participant: The participant closed the card with the close X, with "No thanks" on the invite or with a tap on the overlay.app: Your app calledEthnio.hide(), or a preview link closed the card.ending: The participant closed the ending page.system: The system ended the card. For example, the app went to the background before the card showed.
If a researcher turns off the study while the card is open, the card shows the ending. In this case, the app gets no submitted event.
Status reasons and failure reasons
If the answer is no, Ethnio.statusReason(studyId:) gives the status reason. If your app then calls display , the failed event gives the same reason as a case.
| Status reason | Failure case | What it means | What to do |
|---|---|---|---|
turned_off |
turnedOff |
The study is turned off. | Ask the researcher to turn on the study. |
not_targeted |
notTargeted |
The targeting rules do not match. | Examine the targeting rules and the embedded data that your app sends. |
outside_of_sample |
outsideOfSample |
The sampling ("Show to this share of visitors") did not pick this phone. | Nothing. The phone always gets the same answer for this study. |
already_displayed |
alreadyDisplayed |
The participant closed the card or submitted on this phone in the last 30 days. The Cookie setting of the study is on. | Nothing. For a test, call Ethnio.clearCookie(studyId:). |
robot |
robot |
The request looked like a robot's request. | Nothing. |
legacy_editor |
legacyEditor |
The study does not use the Beta Editor. | Use a study that uses the Beta Editor. |
not_found |
notFound |
No study has this id. | Copy the study id from the Publish page. |
wrong_key |
wrongKey |
The SDK key belongs to another organization. | Copy the key with "Copy key" on the Publish page of the study. |
no_sdk_key |
noSdkKey |
The app set no SDK key. | Set Ethnio.sdkKey before the first call. |
network |
network |
The status request failed. The case holds the system error. | Examine the error and the network connection. Then call registerIntercept again. |
The failed event can also have these cases:
| Failure case | What it means | What to do |
|---|---|---|
notActive |
The study does not show now, and Ethnio gave no reason. For example, the first answer did not arrive yet. | Wait for the result of registerIntercept before you call display. |
notRegistered |
The app called display for a study id that registerIntercept never got. |
Call registerIntercept for the study first. |
busy |
Another card is on screen or still loads. | Wait for the closed event of the other card. |
noWindow |
The app has no window scene, so the SDK cannot show the card. | Call display when your app is on screen. |
network |
The status request failed, or the page did not load. | Examine the system error in the case. |
timeout |
The page did not get ready within 30 seconds. | Examine the network connection. Also read "App-Bound Domains" under Troubleshooting. |
Publish page settings that apply to the card
The Options tab of the Publish page has three settings for the app intercept:
- Show to this share of visitors: The part of the matching people in your app who can see the card. The phone keeps one random number for each study. Thus, a person is always in the share or always out of it.
- Delay after the app asks for the card: The SDK waits this long after your app calls
display. If your app callshide()or goes to the background, the SDK cancels the waiting card. - Cookie: If the participant closes the card or submits, the card writes a cookie. Then the card does not show again on this phone for 30 days. A card that only shows writes no cookie. A call to
hide()writes no cookie. For more about the cookie, read How our cookie works.
The "App intercept design" tab of the Design page sets the look of the card. Position puts the card at the Bottom, the Center or the Top of the screen, or uses Full screen. The tab also has Overlay, "Tap outside the card closes it", Card shadow, Card corner radius and the card size.
Preview a study in your app with a QR code
A researcher can see a study inside your app before participants see it. The preview also shows a study that is turned off. The preview ignores the targeting rules, the sampling, the cookie and the robot check.
For the researcher
- On the Publish page, go to the section "Preview in your app".
- Enter the URL scheme of your app in "App link scheme". The scheme is the part before
://in the links of your app. - Scan the QR code with your phone.
Each study keeps its own scheme. The QR code holds the link <scheme>://ethnio/preview/<study id> . Your app opens and shows the study in preview. A system scheme such as https does not work. Enter the scheme of your own app.
For the developer
- Add your URL scheme to the app target. In Xcode, select the target, then Info, then URL Types.
- Set
Ethnio.sdkKeybefore your app gives a link to the SDK. - Give each link that your app opens to
Ethnio.handleLink.
In SwiftUI, add this modifier to the root view:
.onOpenURL { url in _ = Ethnio.handleLink(url) }
With UIKit, call Ethnio.handleLink(url) in application(_:open:options:) . A UIKit app with scenes gets links in two places:
// In scene(_:willConnectTo:options:)
connectionOptions.urlContexts.forEach { _ = Ethnio.handleLink($0.url) }
// In scene(_:openURLContexts:)
URLContexts.forEach { _ = Ethnio.handleLink($0.url) }
The SDK key of your app proves your organization. Thus, your app shows only the studies of your organization in preview. Without the key, the SDK ignores the link and writes an error in the Xcode console. If the key belongs to another organization, the failed event has the reason wrongKey .
A preview card sends the same events as the card of a participant. Do not reward or count a submission while you test.
To preview a study from your own code, call registerIntercept with preview: true . Use it only to test the study.
Camera and microphone questions
Some questions need the camera or the microphone:
- If the study records video, has a tech check or has an image upload question, add
NSCameraUsageDescriptionto your Info.plist. - For video and for the tech check, also add
NSMicrophoneUsageDescription.
Settings
Ethnio.sdkKey: The SDK key of your organization.Ethnio.logLevel: The SDK messages in the Xcode console:.none,.errorsor.debug. The default is.errors. With.debug, Safari can also inspect the page of the card.Ethnio.baseURL: The default ishttps://ethn.io. Do not change it.
Troubleshooting
The card never shows
- Set
Ethnio.logLevel = .debugand read the Xcode console. - Read
Ethnio.statusReason(studyId:)afterregisterIntercept. - Find the reason in the table of status reasons above.
The failed event has the reason timeout
The SDK does not work in an app that uses App-Bound Domains (the key WKAppBoundDomains in its Info.plist). WebKit then blocks the messages from the page to the SDK. The card does not show, also when the list includes the Ethnio host.
The card showed one time and then never again
If the Cookie setting is on, the card does not show again for 30 days after a close or a submission. For a test, call Ethnio.clearCookie(studyId:) . Then call registerIntercept again.
Xcode shows "No such module 'EthnioSDK'"
The app target does not have the product EthnioSDK .
- In Xcode, select the app target, then General.
- Under "Frameworks, Libraries, and Embedded Content", click "+".
- Select
EthnioSDK.
In a Package.swift file, add .product(name: "EthnioSDK", package: "ethnio-ios") to the dependencies of your target.
The QR code does not open the app
- The "App link scheme" on the Publish page can be wrong. Enter the URL scheme of your app, without
://. - The app can be without the scheme. In Xcode, select the target, then Info, then URL Types. Add the scheme there.
The app opens, but no card shows
- The link does not get to
handleLink. Give each link that your app opens toEthnio.handleLink. A UIKit app with scenes gets links in two places. - The app calls
handleLinkbefore it sets the SDK key. The SDK then ignores the link. The Xcode console shows[Ethnio] Ethnio.sdkKey is not present (handleLink). Set the key before the first call.SetEthnio.sdkKeybefore the first call. - The SDK key belongs to another organization. The
failedevent then has the reasonwrongKey. Copy the key with "Copy key" on the Publish page.
The test phone has an older build of the app
A build without the SDK shows no card and no preview. Install a build that includes the SDK and the URL scheme on the test phone.
The tech check shows "Could not start devices"
The camera and the microphone work only on an https page. Use the default server address of the SDK.
Your app does not use the SDK
Your app can show the study in its own WebView. Read App intercepts implementation using WebView or WKWebView.