Mobile App Testing
Overview
Mobile app testing uses the same server-side testing system covered in Set Up Server-Side Testing - experiment variations are determined on the server and delivered directly to your app, rather than being applied client-side after the fact. This eliminates flicker and enables deeper, more complex experiments within your app.
This guide walks through setting up A/B tests in an iOS application using Swift. A Kotlin SDK is also available for Android.
Step 1 - Create the experiment
From the top left menu, open A/B Testing and select Server-Side Testing, then press Create an A/B test.

Fill in:
-
Title - the experiment's name.
-
URL - the page you're targeting.
-
Experiment Slug - a code-friendly identifier, useful for finding this experiment in your codebase.
-
Hypothesis - what you expect to happen.
Step 2 - Define variables and variations
Variables
In the Variables tab, define the information you want to transmit to your application - for example, product_title. Choose a Type for each variable.
Variations
As with a regular A/B test, create as many variations as you need. For each, specify a value for the variable(s) you've defined, and set a slug for the variation (via the pencil icon) - this is best practice, since you'll reference it in code.
Step 3 - Set the audience and segmentation
Choosing pages
Manage the pages where the experiment runs using the same URL conditions as a standard A/B test: URL is, URL is not, URL starts with, URL ends with, URL contains, URL does not contain, URL RegEx, or Page contains keyword. See Create an A/B Test for the full explanation of each.
Segment
By default, a new server-side experiment has no segment - press Select or create segment to set one.
To target all your traffic, create a segment using Count pageviews in current session → Greater than → 0.
Segments for server-side experiments are entirely separate from segments used in client-side experiments. To find them, switch from the Web section to the Server Side section under Advanced → Segments.
Device type
You can also filter by Device Type, so only visitors on a specific device are included.
Step 4 - Traffic allocation and goals
Traffic allocation
In Traffic Allocation & Goals, choose the percentage of your segment's visitors to include, then split that traffic between Control and Variation using the slider.
Goals
There are 3 default goal options: Sale, Engagement, and Bounce Rate, with Sale selected by default. Some goals require integration on your website before they'll record data. Add existing goals, create custom ones, or delete any you don't need.
You can also set a Goal Timeout - the window after which conversions stop being counted for this experiment.
Step 5 - Schedule and publish
Set the timeframe under Scheduling, with an option to be notified by email when it ends, and Excluded hours intervals for specific days or times.
Scheduling dates and times are interpreted using your account's Display Timezone setting.
Choose Save & Continue or Publish.
Once your experiment is created, an API Settings section appears with an example of how to use the SDK. This example uses PHP; the same concepts apply across the other supported languages.

Step 6 - Install the SDK
Install via Swift Package Manager
Add the SDK dependency to your Package.swift file:
dependencies: [
.package(url: "https://bitbucket.org/mktz/server-side-testing-swift", from: "1.0.0")
]
Alternatively, in Xcode go to File → Add Package Dependencies and enter the repository URL.
Generate and configure your API key
-
Navigate to Settings → API Keys in your Explore dashboard.
-
Press Generate API Key.
-
Copy the key - you'll need it to initialize the SDK.

Step 7 - Define your app configuration
Import the SDK and configure your client:
import OmniconvertSDK
var sessionParams = SessionParams()
sessionParams.setReferrerUrl("https://yourapp.com")
.setDeviceType("mobile")
let client = OmniconvertSDK.createClient(
apiKey: "your_api_key_here",
userId: "unique_user_id",
sessionParams: sessionParams
)
let context = ContextBuilder.create()
.url("https://yourapp.com/checkout")
.deviceType("mobile")
.custom("user_type", "premium")
.build()
SessionParams
Defines session-level information that persists throughout the user's visit:
-
setReferrerUrl()- where the user came from (e.g. a marketing campaign URL). -
setDeviceType()- the device type:"mobile","tablet", or"desktop".
For detailed information on all session parameters, please refer to this link.
createClient parameters
-
apiKey- your API key from the Explore dashboard (Step 6). -
userId- a unique identifier for the user, ensuring they always see the same variation. Use your app's own user ID, or generate a UUID for anonymous users. -
sessionParams- the session configuration defined above.
ContextBuilder methods
The context tells the SDK about the current state when requesting a decision:
-
url()- the current screen or page URL, matched against your experiment's URL targeting rules. -
deviceType()- the device type for device-specific targeting. -
custom()- custom key-value pairs for advanced targeting - use these to pass user attributes like subscription tier, app version, or any property configured in your experiment's segmentation rules. -
build()- finalizes and returns the context object.
Step 8 - Request a decision from the SDK
let decisions = await client.decide(context)
for decision in decisions {
if decision.experimentKey == "checkout_button_test" {
let buttonColor = decision.getVariationVariable("button_color") ?? "blue"
// Apply the variation to your UI
}
}
client.decide(context) evaluates all your active experiments and determines which ones apply to this user, based on audience segmentation, traffic allocation, and user bucketing.
decisions is an array of Decision objects - you may receive multiple decisions if the user qualifies for several experiments. If no experiments match, the array is empty.
Finding your experiment
decision.experimentKey is the Experiment Slug you defined when creating the experiment in the dashboard (Step 1). Use it to identify which experiment each decision belongs to:
if decision.experimentKey == "checkout_button_test" {
// This decision is for your checkout button experiment
}
Getting variation variables
decision.getVariationVariable("variable_name") retrieves the value of a variable defined in the Variation Editor (Step 2). The variable name must match exactly what you configured in the dashboard:
// "button_color" is the variable name from your experiment's Variables tab
let buttonColor = decision.getVariationVariable("button_color") ?? "blue"
The ?? "blue" fallback ensures your app always has a valid value to work with, even if the variable isn't found.
Step 9 - Track conversions
When a user completes a goal (like making a purchase), track it so Explore can measure your experiment's success.
Custom events
Track any custom goal you've configured in the dashboard:
try await client.getTracker().track("button_click")
The first parameter is the event name, which must match your goal configuration in the dashboard.
Purchases
Track completed transactions using the "sale" event:
let details: [String: Any] = [
"transaction": "txn_789",
"skus": ["PROD123", "PROD456", "PROD789"],
"currency": "USD"
]
try await client.getTracker().track("sale", value: 1499.97, details: details)
-
sale- the event name for purchase tracking. -
value- total transaction value. -
transaction- your unique transaction/order ID. -
skus- array of product SKUs in the order. -
currency- currency code (e.g."USD","EUR","RON").
The event names used in track() must match the custom goals configured in Step 4 - this is how Explore connects user actions to your experiment results.
Further resources
-
Swift SDK API Reference - can be found here.