A/B Tests
Create A/B Tests using the /api/experiments endpoint. An experiment or A/B test is a set of distinct push notification variants sent to subsets of an audience. You can create up to 26 notification variants and send each variant to an audience subset.
Create experiment (A/B Test)
Create an experiment. The body of the request should consist of a single experiment object. The experiment is processed and sent immediately unless a schedule is present.
POST /api/experiments
Security:
Request body:
Content-Type:
application/jsonAn experiment object describes an A/B test, including the audience and variant portions.
Responses
201
The experiment was created.
Response headers:
- Location string
The newly created experiment.
Response body:
- Content-Type:
application/jsonThe response body for an experiment request.
OBJECT PROPERTIES- experiment_id string
Unique identifier for an experiment.
- ok booleanREQUIRED
If true, the experiment was successfully created. If false, the experiment was not created.
- operation_id string
A unique string that represents a single API call, used to identify the operation or side effects in reporting and troubleshooting logs.
- push_id string
Unique identifier for a push.
400
There was a parsing or validation error in the request. Bad Request errors typically include
pathandlocationin the response to help you find the cause of the error.Response body:
- Content-Type:
application/jsonErrors returned with 4xx responses. Errors include as much information as possible to help you understand the reason for the failure.
401
Authentication information (the app key and secret or bearer token) was either incorrect or missing.
Response body:
- Content-Type:
text/plainErrors returned with 4xx responses. Errors include as much information as possible to help you understand the reason for the failure.
Examples
Example
POST /api/experiments HTTP/1.1
Authorization: Basic <authorization string>
Accept: application/vnd.urbanairship+json; version=3
Content-Type: application/json
{
"name": "Experiment 1",
"audience": {"tag": "earlyBirds"},
"device_types": [ "ios", "android" ],
"variants": [
{
"push": {
"notification": {
"alert": "message 1"
}
}
},
{
"push": {
"notification": {
"alert": "message 2"
}
}
}
]
}
HTTP/1.1 201 Created
Content-Length: 123
Location: https://go.urbanairship.com/api/experiments/0f7704e9-5dc0-4f7d-9964-e89055701b0a
Content-Type: application/vnd.urbanairship+json; version=3
{
"ok" : "true",
"operation_id" : "03ca94a3-2b27-42f6-be7e-41efc2612cd4",
"experiment_id" : "0f7704e9-5dc0-4f7d-9964-e89055701b0a",
"push_id" : "7e13f060-594c-11e4-8ed6-0800200c9a66"
}
UrbanAirshipClient client = UrbanAirshipClient.newBuilder()
.setKey("<app key>")
.setSecret("<master secret>")
.build();
Schedule schedule = Schedule.newBuilder()
.setScheduledTimestamp(DateTime.now().plusMinutes(5))
.build();
Variant variantOne = Variant.newBuilder()
.setPushPayload(VariantPushPayload.newBuilder()
.setNotification(Notification.newBuilder()
.setAlert("message 1")
.build()
)
.build())
.setSchedule(schedule)
.build();
Variant variantTwo = Variant.newBuilder()
.setPushPayload(VariantPushPayload.newBuilder()
.setNotification(Notification.newBuilder()
.setAlert("message 2")
.build()
)
.build())
.setSchedule(schedule)
.build();
Experiment experiment = Experiment.newBuilder()
.setName("Experiment 1")
.setDescription("Testing description")
.setDeviceTypes(DeviceTypeData.of(DeviceType.IOS, DeviceType.ANDROID))
.setAudience(Selectors.tag("earlyBirds"))
.addVariant(variantOne)
.addVariant(variantTwo)
.build();
ExperimentRequest request = ExperimentRequest.newRequest(experiment);
Response<ExperimentResponse> response = client.execute(request);
from urbanairship import (
BasicAuthClient, ABTest, Experiment, Variant
)
from urbanairship.push import notification
client = BasicAuthClient(
key='<app_key>',
secret='<master_secret>'
)
# Create push notifications for variants
push_1 = notification(alert='message 1')
push_2 = notification(alert='message 2')
# Create variants
variants = [
Variant(push=push_1),
Variant(push=push_2)
]
# Create experiment
experiment = Experiment(
audience={'tag': 'earlyBirds'},
device_types=['ios', 'android'],
variants=variants,
name='Experiment 1'
)
# Create and send experiment
ab_test = ABTest(airship=client)
response = ab_test.create(experiment=experiment)
require 'urbanairship'
UA = Urbanairship
airship = UA::Client.new(key: '<app key>', secret: '<master secret>')
variant_one = UA::Variant.new(client: airship)
variant_one.push = {
"notification": {
"alert": "message 1"
}
}
variant_two = UA::Variant.new(client: airship)
variant_two.push = {
"notification": {
"alert": "message 2"
}
}
experiment = UA::Experiment.new(client: airship)
experiment.name = 'Experiment 1'
experiment.description = 'Example experiment'
experiment.audience = UA.tag('earlyBirds')
experiment.device_types = ['ios','android']
experiment.variants << variant_one.payload
experiment.variants << variant_two.payload
ab_test = UA::AbTest.new(client: airship)
ab_test.experiment_object = experiment.payload
ab_test.create_ab_test
Delete experiment
Delete a scheduled experiment. You can only delete experiments before they start; attempting to delete an experiment that has already started or completed will return an HTTP 405 response (“Method not allowed”).
DELETE /api/experiments/scheduled/{experiment_id}
Security:
Path parameters:
- experiment_id stringREQUIREDThe unique identifier of the experiment.
Responses
200
Returned if the experiment has been successfully deleted.
Response body:
- Content-Type:
application/jsonThe response body for a pipeline’s deletion request.
OBJECT PROPERTIES- ok booleanREQUIRED
Success.
- operation_id string
A unique string that represents a single API call, used to identify the operation or side effects in reporting and troubleshooting logs.
401
Authentication information (the app key and secret or bearer token) was either incorrect or missing.
Response body:
- Content-Type:
text/plainErrors returned with 4xx responses. Errors include as much information as possible to help you understand the reason for the failure.
404
The requested resource doesn’t exist.
Response body:
- Content-Type:
application/vnd.urbanairship+jsonErrors returned with 4xx responses. Errors include as much information as possible to help you understand the reason for the failure.
405
Returned when a request is made using an HTTP method not supported by the endpoint. For example, sending a DELETE to /api/schedules.
Response body:
- Content-Type:
application/jsonErrors returned with 4xx responses. Errors include as much information as possible to help you understand the reason for the failure.
Examples
Example
DELETE /api/experiments/scheduled/0f7704e9-5dc0-4f7d-9964-e89055701b0a HTTP/1.1
Authorization: Basic <authorization string>
Accept: application/vnd.urbanairship+json; version=3
HTTP/1.1 200 OK
Content-Length: 123
Content-Type: application/vnd.urbanairship+json; version=3
{
"ok" : "true",
"operation_id" : "03ca94a3-2b27-42f6-be7e-41efc2612cd4"
}
UrbanAirshipClient client = UrbanAirshipClient.newBuilder()
.setKey("<app key>")
.setSecret("<master secret>")
.build();
ExperimentDeleteRequest request = ExperimentDeleteRequest.newRequest("0f7704e9-5dc0-4f7d-9964-e89055701b0a");
Response<ExperimentResponse> response = client.execute(request);
from urbanairship import (
BasicAuthClient, ABTest
)
client = BasicAuthClient(
key='<app_key>',
secret='<master_secret>'
)
ab_test = ua.ABTest(client)
ab_test.experiment_id = "0f7704e9-5dc0-4f7d-9964-e89055701b0a"
response = ab_test.delete()
require 'urbanairship'
UA = Urbanairship
airship = UA::Client.new(key: '<app key>', secret: '<master secret>')
ab_test = UA::AbTest.new(client: airship)
ab_test.experiment_id = '0f7704e9-5dc0-4f7d-9964-e89055701b0a'
ab_test.delete_ab_test
Experiment listing
List experiments, sorted by created_at date-time from newest to oldest. Responses are paginated. Use optional limit and offset parameters to navigate results.
GET /api/experiments
Security:
Query parameters:
- limit integerPositive maximum number of elements to return per page. The default
limitis 10 entries with a maximum of 100 entries.Min: 1
Max: 100
- offset integerA zero-based integer offset into the result set. If you do not use an offset, results will begin with the most recently sent experiment. If
offsetis greater than the number of queryable experiments, an empty result will be returned.
Responses
200
Returned on success, with the JSON representation of the experiments in the body of the response.
Response body:
- Content-Type:OBJECT PROPERTIES
application/json- count integer
The number of items returned in this page of results.
- experiments array
Experiment objects sorted by either
created_atfrom newest to oldest. The number of objects will never exceed the limit specified in the request. - next_page string
A relative URL leading to the next page of results. If there are no more results, next_page is absent.
- ok booleanREQUIRED
If true, the call was successful.
- total_count integer
The total number of results.
401
Authentication information (the app key and secret or bearer token) was either incorrect or missing.
Response body:
- Content-Type:
text/plainErrors returned with 4xx responses. Errors include as much information as possible to help you understand the reason for the failure.
Examples
Example
GET /api/experiments HTTP/1.1
Authorization: Basic <authorization string>
Accept: application/vnd.urbanairship+json; version=3
HTTP/1.1 200 OK
Content-Length: 123
Data-Attribute: experiments
Count: 2
Total-Count: 2
Content-Type: application/vnd.urbanairship+json; version=3
{
"ok" : "true",
"count" : 2,
"total_count" : 2,
"experiments" : [{
"name" : "Experiment 1",
"control" : 0.33,
"audience" : "all",
"device_types": [ "ios", "android" ],
"variants" : [{
"push" : {
"notification" : {
"alert" : "message 1"
}
},
"id" : 0,
},
{
"push" : {
"notification" : {
"alert" : "message 2"
}
},
"id" : 1,
}],
"id" : "b5bc3dd1-9ea4-4208-b5f1-9e7ac3fe0502",
"created_at" : "2020-03-03T21:08:05",
"push_id" : "07cec298-6b8c-49f9-8e03-0448a06f4aac"
}, {
"name" : "Experiment 2",
"description" : "The second experiment",
"audience" : "all",
"device_types": [ "ios", "android" ],
"variants" : [{
"push" : {
"notification" : {
"alert" : "message 1"
}
},
"id" : 0,
},
{
"push" : {
"notification" : {
"alert" : "message 2"
}
},
"id" : 1,
}],
"id" : "e464aa7e-be40-4994-a290-1bbada7187d8",
"created_at" : "2020-03-03T21:08:05",
"push_id" : "07cec298-6b8c-49f9-8e03-0448a06f4aac"
}]
}
from urbanairship import (
BasicAuthClient, ABTest
)
client = BasicAuthClient(
key='<app_key>',
secret='<master_secret>'
)
ab_test = ABTest(airship=client)
response = ab_test.list_experiments()
require 'urbanairship'
UA = Urbanairship
airship = UA::Client.new(key: '<app key>', secret: '<master secret>')
ab_test = UA::AbTest.new(client: airship)
ab_test.limit = 5
ab_test.list_ab_test
Experiment lookup
Look up an experiment (A/B Test).
GET /api/experiments/{experiment_id}
Security:
Path parameters:
- experiment_id stringREQUIREDThe ID of the experiment you want to look up.
Responses
200
Returned on success, with the JSON representation of the experiment in the body of the response.
Response body:
- Content-Type:OBJECT PROPERTIES
application/json- experiment object<Experiment object>
An experiment object describes an A/B test, including the audience and variant portions.
- ok booleanREQUIRED
If true, the operation completed successfully and returns a result set.
401
Authentication information (the app key and secret or bearer token) was either incorrect or missing.
Response body:
- Content-Type:
text/plainErrors returned with 4xx responses. Errors include as much information as possible to help you understand the reason for the failure.
404
The requested resource doesn’t exist.
Response body:
- Content-Type:
application/vnd.urbanairship+jsonErrors returned with 4xx responses. Errors include as much information as possible to help you understand the reason for the failure.
Examples
Example
GET /api/experiments/0f7704e9-5dc0-4f7d-9964-e89055701b0a HTTP/1.1
Authorization: Basic <authorization string>
Accept: application/vnd.urbanairship+json; version=3
HTTP/1.1 200 OK
Content-Length: 123
Data-Attribute: experiment
Content-Type: application/vnd.urbanairship+json; version=3
{
"ok" : "true",
"experiment" : {
"id" : "0f7704e9-5dc0-4f7d-9964-e89055701b0a",
"push_id": "d00f07b0-594c-11e4-8ed6-0800200c9a66",
"name" : "Experiment 1",
"audience" : "all",
"device_types": [ "ios", "android" ],
"variants" : [{
"push" : {
"notification" : {
"alert" : "message 1"
}
},
"id" : 0,
},
{
"push" : {
"notification" : {
"alert" : "message 2"
}
},
"id" : 1,
}]
}
}
from urbanairship import BasicAuthClient, ABTest
client = BasicAuthClient(
key='<app_key>',
secret='<master_secret>'
)
ab_test = ABTest(client)
response = ab_test.lookup(experiment_id='0f7704e9-5dc0-4f7d-9964-e89055701b0a')
require 'urbanairship'
UA = Urbanairship
airship = UA::Client.new(key: '<app key>', secret: '<master secret>')
ab_test = UA::AbTest.new(client: airship)
ab_test.experiment_id = '0f7704e9-5dc0-4f7d-9964-e89055701b0a'
ab_test.lookup_ab_test
Scheduled experiment listing
List scheduled experiments in order, from closest to the current date-time to farthest (i.e., the experiments scheduled to occur soonest will appear at the top of the list). Responses are paginated, using optional limit and offset parameters.
GET /api/experiments/scheduled
Security:
Query parameters:
- limit integerPositive maximum number of elements to return per page. The default
limitis 10 entries with a maximum of 100 entries.Min: 1
Max: 100
- offset integerA zero-based integer offset into the result set. If you do not use an offset, results will begin with experiment scheduled to begin at the soonest date-time. If the
offsetis greater than the number of queryable experiments, the result set will be empty.
Responses
200
Returned on success, with the JSON representation of the experiments in the body of the response.
Response body:
- Content-Type:OBJECT PROPERTIES
application/json- count integer
The number of items in this page of results.
- experiments array
Experiments listed by
scheduled_timein ascending time order. The number of objects will never exceed thelimitspecified in the request. - next_page string
A relative URL leading to the next page of results. If there are no more results, next_page is absent.
- ok booleanREQUIRED
If true, the operation completed successfully and returns an expected result set.
- total_count integer
The total number of results.
401
Authentication information (the app key and secret or bearer token) was either incorrect or missing.
Response body:
- Content-Type:
text/plainErrors returned with 4xx responses. Errors include as much information as possible to help you understand the reason for the failure.
Examples
Example
GET /api/experiments/scheduled HTTP/1.1
Authorization: Basic <authorization string>
Accept: application/vnd.urbanairship+json; version=3
HTTP/1.1 200 OK
Content-Length: 123
Data-Attribute: experiments
Content-Type: application/vnd.urbanairship+json; version=3
{
"ok": "true",
"count": 2,
"total_count": 2,
"experiments": [
{
"id": "0f7704e9-5dc0-4f7d-9964-e89055701b0a",
"name": "Experiment 1",
"audience": "all",
"device_types": [ "ios", "android" ],
"variants": [
{
"id": 0,
"schedule": {
"scheduled_time": "2020-11-17T20:58:00Z"
},
"push": {
"notification": {
"alert": "message 1"
}
}
},
{
"id": 1,
"schedule": {
"scheduled_time": "2020-11-17T20:58:00Z"
},
"push": {
"notification": {
"alert": "message 2"
}
}
}
]
},
{
"id": "29705c10-5951-11e4-8ed6-0800200c9a66",
"name": "Experiment 2",
"audience": "all",
"device_types": [ "ios", "android" ],
"variants": [
{
"id": 0,
"schedule": {
"scheduled_time": "2020-12-17T20:58:00Z"
},
"push": {
"notification": {
"alert": "message 1"
}
}
},
{
"id": 1,
"schedule": {
"scheduled_time": "2020-12-17T20:58:00Z"
},
"push": {
"notification": {
"alert": "message 2"
}
}
}
]
}
]
}
from urbanairship import (
BasicAuthClient, ABTest
)
client = BasicAuthClient(
key='<app_key>',
secret='<master_secret>'
)
ab_test = ABTest(client)
response = ab_test.list_scheduled_experiment()
require 'urbanairship'
UA = Urbanairship
airship = UA::Client.new(key: '<app key>', secret: '<master secret>')
ab_test = UA::AbTest.new(client: airship)
ab_test.list_scheduled_ab_test
Validate experiment
Accepts the same range of payloads as /api/experiments, but only parses and validates the payload without creating the experiment. This does the same amount of validation as the creation endpoint, including platform-specific validation, e.g., APNs byte limit checks. While this operation ensures the experiment is technically valid, it does not guarantee that a resulting push will succeed. An experiment may validate and still fail to be delivered. For example, you may have a valid experiment with no devices in your audience.
POST /api/experiments/validate
Security:
Request body:
A single experiment object.
Content-Type:
application/jsonAn experiment object describes an A/B test, including the audience and variant portions.
Responses
200
The experiment is valid.
Response body:
- Content-Type:OBJECT PROPERTIES
application/json- ok booleanREQUIRED
If true, the operation completed successfully and returns an expected response.
- operation_id string
A unique string that represents a single API call, used to identify the operation or side effects in reporting and troubleshooting logs.
400
There was a parsing or validation error in the request. Bad Request errors typically include
pathandlocationin the response to help you find the cause of the error.Response body:
- Content-Type:
application/jsonErrors returned with 4xx responses. Errors include as much information as possible to help you understand the reason for the failure.
401
Authentication information (the app key and secret or bearer token) was either incorrect or missing.
Response body:
- Content-Type:
text/plainErrors returned with 4xx responses. Errors include as much information as possible to help you understand the reason for the failure.
Examples
Example
POST /api/experiments/validate HTTP/1.1
Authorization: Basic <authorization string>
Accept: application/vnd.urbanairship+json; version=3
Content-Type: application/json
{
"name": "Experiment 1",
"audience": {"tag": "earlyBirds"},
"device_types": [ "ios", "android" ],
"variants": [
{
"push": {
"notification": {
"alert": "message 1"
}
}
},
{
"push": {
"notification": {
"alert": "message 2"
}
}
}
]
}
HTTP/1.1 200 OK
Content-Length: 123
Content-Type: application/vnd.urbanairship+json; version=3
{
"ok" : "true",
"operation_id" : "03ca94a3-2b27-42f6-be7e-41efc2612cd4"
}
UrbanAirshipClient client = UrbanAirshipClient.newBuilder()
.setKey("<app key>")
.setSecret("<master secret>")
.build();
Schedule schedule = Schedule.newBuilder()
.setScheduledTimestamp(DateTime.now().plusMinutes(5))
.build();
Variant variantOne = Variant.newBuilder()
.setPushPayload(VariantPushPayload.newBuilder()
.setNotification(Notification.newBuilder()
.setAlert("message 1")
.build()
)
.build())
.setSchedule(schedule)
.build();
Variant variantTwo = Variant.newBuilder()
.setPushPayload(VariantPushPayload.newBuilder()
.setNotification(Notification.newBuilder()
.setAlert("message 2")
.build()
)
.build())
.setSchedule(schedule)
.build();
Experiment experiment = Experiment.newBuilder()
.setName("Experiment 1")
.setDescription("Testing description")
.setDeviceTypes(DeviceTypeData.of(DeviceType.IOS, DeviceType.ANDROID))
.setAudience(Selectors.tag("earlyBirds"))
.addVariant(variantOne)
.addVariant(variantTwo)
.build();
ExperimentRequest request = ExperimentRequest.newRequest(experiment).setValidateOnly(true);
Response<ExperimentResponse> response = client.execute(request);
from urbanairship import (
BasicAuthClient, ABTest, Experiment, Variant
)
from urbanairship.push import notification
client = BasicAuthClient(
key='<app_key>',
secret='<master_secret>'
)
# Create push notifications for variants
push_1 = notification(alert='message 1')
push_2 = notification(alert='message 2')
# Create variants
variants = [
Variant(push=push_1),
Variant(push=push_2)
]
# Create experiment
experiment = Experiment(
audience={'tag': 'earlyBirds'},
device_types=['ios', 'android'],
variants=variants,
name='Experiment 1'
)
# Validate experiment
ab_test = ABTest(airship=client)
response = ab_test.validate(experiment=experiment)
require 'urbanairship'
UA = Urbanairship
airship = UA::Client.new(key: '<app key>', secret: '<master secret>')
variant_one = UA::Variant.new(client: airship)
variant_one.push = {
"notification": {
"alert": "message 1"
}
}
variant_two = UA::Variant.new(client: airship)
variant_two.push = {
"notification": {
"alert": "message 2"
}
}
experiment = UA::Experiment.new(client: airship)
experiment.name = 'Experiment 1'
experiment.description = 'Example experiment'
experiment.audience = UA.tag('earlyBirds')
experiment.device_types = ['ios','android']
experiment.variants << variant_one.payload
experiment.variants << variant_two.payload
ab_test = UA::AbTest.new(client: airship)
ab_test.experiment_object = experiment.payload
ab_test.validate_ab_test