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

  1. Copy the code and the SDK key from the Publish page. Read Find the code and the SDK key on the Publish page.
  2. Add the SDK to your app with Swift Package Manager. Read Install the SDK.
  3. Set the SDK key one time when the app starts. Read Set the SDK key.
  4. Register the app intercept and show the card. Read Register the app intercept and show the card.
  5. Add the URL scheme of your app for the QR code preview. Read Preview a study in your app with a QR code.
  6. Do a test with a test study that is turned on. Read Check the installation.
  7. 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.

  1. Open the study in Ethnio.
  2. Go to the Publish page.
  3. Find the section "App intercept".
  4. Under "How your app shows the intercept", select "iOS SDK".
  5. Click "Copy" to copy the code for this study.
  6. 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:

  1. In Xcode, select File, then Add Package Dependencies.
  2. Paste https://github.com/ethnio/ethnio-ios  into the search field.
  3. Select "Up to Next Major Version" from 1.0.0.
  4. Add the product EthnioSDK  to 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:

  1. Call registerIntercept  to ask Ethnio if the card can show now.
  2. If the answer is yes, call display  to 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.

  1. Set Ethnio.logLevel = .debug  before the first call to the SDK.
  2. Ask the researcher for the id of a test study that is turned on.
  3. Call registerIntercept  with the id of the test study. Do not set preview: true .
  4. Find the status line in the Xcode console. If the card can show, the line is [Ethnio] status 1: true .
  5. If the answer is no, the line has the status reason in parentheses, for example [Ethnio] status 1: false (turned_off) .
  6. If the request failed, the line is [Ethnio] status 1 failed:  and the system error.
  7. If the answer is no, read Ethnio.statusReason(studyId:) . Find the reason in Status reasons and failure reasons.
  8. If the answer is yes, call display .
  9. Answer the questions in the card and submit.
  10. Find the submitted  event in the Xcode console, for example [Ethnio] event submitted(studyId: 1, qualified: "qualified") .
  11. Open the responses page of the study in Ethnio.
  12. 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 registerIntercept  with preview: 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.

  1. Remove the line that sets Ethnio.logLevel = .debug .
  2. Remove preview: true  from your calls.
  3. Release the new version of your app.
  4. 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 , name  and phone  fill 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_key  and l . Use the parameters preview  and language  of registerIntercept  instead. Set the key in Ethnio.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 called Ethnio.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 calls hide()  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

  1. On the Publish page, go to the section "Preview in your app".
  2. Enter the URL scheme of your app in "App link scheme". The scheme is the part before ://  in the links of your app.
  3. 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

  1. Add your URL scheme to the app target. In Xcode, select the target, then Info, then URL Types.
  2. Set Ethnio.sdkKey  before your app gives a link to the SDK.
  3. 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 NSCameraUsageDescription  to 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 , .errors  or .debug . The default is .errors . With .debug , Safari can also inspect the page of the card.
  • Ethnio.baseURL : The default is https://ethn.io . Do not change it.

Troubleshooting

The card never shows

  1. Set Ethnio.logLevel = .debug  and read the Xcode console.
  2. Read Ethnio.statusReason(studyId:)  after registerIntercept .
  3. 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 .

  1. In Xcode, select the app target, then General.
  2. Under "Frameworks, Libraries, and Embedded Content", click "+".
  3. 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 to Ethnio.handleLink . A UIKit app with scenes gets links in two places.
  • The app calls handleLink  before 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.  Set Ethnio.sdkKey  before the first call.
  • The SDK key belongs to another organization. The failed  event then has the reason wrongKey . 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.

Still need help? Contact Us Contact Us