Introduction
Server-side A/B testing is a methodology where the experiment variations are processed and determined on the server before they reach the client application. Unlike client-side testing, which relies on JavaScript execution after the page loads, server-side testing delivers the final experience directly, eliminating flicker and enabling deeper, more complex experiments.
This guide will walk you through everything you need to know to set up and run A/B tests in your iOS application. We will demonstrate the functionality using Swift. For mobile testing on Android devices, a Kotlin SDK is also available.
Step 1. Set up the experiment.
Before implementing the SDK, you’ll need to set up your experiment in the Omniconvert dashboard. This involves creating your A/B test, defining variables and variations, configuring audience targeting, setting traffic allocation and goals, and publishing your experiment.
For detailed instructions on setting up your experiment, see our complete guide: Server-Side Testing Setup.
Step 2. SDK Installation.
Step 2.1. 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.
Step 2.2. Generate and Configure API Key
1. Navigate to Settings > API Keys in your Omniconvert dashboard
2. Press Generate Api Key
3. Copy the key – you’ll need it to initialize the SDK

Step 3: Define 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 function parameters:
- apiKey – Your API key from the Omniconvert dashboard (Step 2)
- userId – A unique identifier for the user. This ensures the same user always sees the same variation. Use your app’s 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. This is 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 you’ve configured in your experiment’s segmentation rules.
- build() – Finalizes and returns the context object
Step 4. Request SDK Decision.
Request experiment decisions and apply the returned variations:
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) – The SDK evaluates all your active experiments and determines which ones apply to this user based on: Audience segmentation, Traffic allocation, User bucketing.
decisions – An array of Decision objects. You may receive multiple decisions if the user qualifies for several experiments. If no experiments match, the array will be empty.
Finding Your Experiment
decision.experimentKey — This 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.
// Match against the slug you configured in the dashboard
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 you defined in the Variation Editor (Step 1). 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" provides a fallback value in case the variable isn’t found. This ensures your app always has a valid value to work with.
Step 5. Track Conversions
When a user completes a goal (like making a purchase), track it so Omniconvert 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")- First parameter: Event name (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 trackingvalue: Total transaction valuetransaction: Your unique transaction/order IDskus: Array of product SKUs in the ordercurrency: Currency code (e.g., “USD”, “EUR”, “RON”)
Tip: Make sure the event names you use in track() match the custom goals you’ve configured in Step 1. This is how Omniconvert connects user actions to your experiment results.