iOS transformation guide

This page documents the JSON mark-up used to change UIKit elements for your test variants. It is assumed that you have integrated the iOS SDK(LINK) are using this information in conjunction with the App Testing From Site Creation to Live Publish(LINK) guide.

The no store update approach is a way to build A/B tests for native applications whereby variants of the user experience are injected into the app remotely using a JSON mark-up. This approach allows campaigns and updates of variants to be published from Maxymiser rather than code changes within the app followed by a release cycle. In contrast the manual approach uses variants that are coded into the app and released to users through a general release. In this case Maxymiser is used as a decision and reporting engine.

The no store update approach is supported only for iOS 8.0 onwards. On iOS 7 and earlier, the SDK will not apply variant transformations or track actions.

iOS version No store update Manual approach
v8.x onwards Supported Supported
v7.x Not supported (SDK inactive) Supported
v6.x and earlier Not supported (SDK inactive) Not supported (SDK inactive)

JSON schema reference

{

"MMTApp": [

{

"scope": {

"device": ["iphone", "ipad"],

"orientation": ["landscape", "portrait"],

"scale": ["@1x", "@2x", "@3x"]

},

"config": [

{

"id": "DemoViewController/UIView[0]/UILabel[0]",

"props": {

"text": "Hello",

"background-color": "#008B7D"

}

},

{

"id": "DemoViewController/UIView[0]/UIButton[0]",

"props": {

"background-color": "#008B7D"

}

}

],

"constraints": {

"update": [

{

"item1": "DemoViewController/UIView/UIButton",

"attribute1": "Top",

"relation": "Equal",

"item2": "DemoViewController/UIView/UITextView",

"attribute2": "Bottom",

"priority": 1000,

"multiplier": 1.0,

"values": {

"constant": 100

}

}

]

},

"actions": [

{

"id": "DemoViewController/UIView/UIButton",

"type": "TouchUpInside",

"name": "Click_through"

}

]

}

]

}

Element IDs

IDs are used to select UI Elements on-screen. The ID is a path to a UI element that starts from ViewController's root view. For example:

"id": "DemoViewController/UIView[0]/UIButton[1]"

is the ID of a second Button on a first UIView of a DemoViewController's root view. By default, DemoViewController's root view has an ID that is equal to controller's class name.

It is possible to assign a custom ID to any UI Element from code. This will allow you to target elements depending on their exact context. The example below sets "Product-123" ID to a root view of a ProductDetailsViewController.

This will allow you to target ProductDetailsViewController's UI elements for a specific product.

"id": "Product-123/UIButton[0]"

Note: The Custom ID does not override the auto generated ID and you can use both custom and auto generated IDs in your campaign.

To get all UI element IDs visible on screen enable element ID output and navigate to this page.

[MMTApp setPrintElementsIDs:YES];

The SDK will output all element IDs to the application log.

Scope

Scope is an optional block that allows the use of different transformations or actions for different device configurations. Configuration is a set of parameters like device type, orientation and scale.

Scope contains objects that define different scope parameters.

"device" is an enumeration of devices on which transformations are applied. The possible values are

  • "iphone"
  • "ipad"

For example, when enumeration includes only "iphone", the transformations for this scope will only be applied on iPhones.

If "device" is not set explicitly, it will be considered as ["iphone", "ipad"], where all devices are included.

"orientation" is an enumeration of orientations in which transformations are applied. The possible values are

  • "landscape"
  • "portrait"

For example, when enumeration includes only "landscape", the transformations for this scope will only be applied when orientation changes to landscape.

If "orientation" is not set explicitly, it will be considered as ["landscape", "portrait"], where all orientations are included.

Important: Transformations applied for a specific scope will not rollback on an orientation change. So please make sure you describe your transformations for both orientations.

"scale" is an enumeration of screen scales in which transformations are applied. The possible values are

  • "@1x" for non-Retina screen
  • "@2x" for Retina screen (iPhone 4-5s, iPads with Retina screens)
  • "@3x" for iPhone 6 Plus screen

For example, when enumeration includes only "@3x", the transformations for this scope will be applied only on iPhone 6 Plus

If "scale" is not set explicitly, it will be considered as ["@1x", "@2x", "@3x"], where all scales are included.

Constraints

Constraints block describes constraints to change.

You have to specify the following properties to select constraint you want to change:

  • "item1 - ID of the first item of the constraint. Order is important. This object is mandatory, without it the change will not be applied."
  • "attribute1" - attribute of the first item. Object is optional, if it does not exist it will be ignored during constraint searching. Receives a string with attribute name as a parameter. All possible attribute names are described below.
  • "relation" - relation between two attributes. Optional. Parameter is a string with relation name. All possible variants of the parameter are described below.
  • "item2" - ID of the second item. This object is mandatory only if a second element is included. In some cases only one element exists in the constraint. In these cases the "item2" object can be omitted.
  • "attribute2" - attribute of the second item. Optional.
  • "priority" - constraint priority. Receives a float value as a parameter. Optional.
  • "multiplier" - constraint multiplier. Receives a float value as a parameter. Optional.
  • "constant" - constraint constant. Receives a float value as a parameter. Optional.

These properties should explicitly define a constraint to change, if multiple constraints match the specified properties they will not be updated.

In the "update" block you specify values to change.

Only "constant" property is supported at the moment.

The following values can be used for the "attribute1" or "attribute2":

  • "left" - left coordinate of the view (x)
  • "right" - right coordinate of the view (x + width)
  • "top" - top coordinate of the view (y)
  • "bottom" - bottom coordinate of the view (y + height)
  • "leading" - depends on interface, for English equals to "left", for Arabic (or other RTL language) - to "right"
  • "trailing" - depends on interface, for English equals to "right", for Arabic (or other RTL language) - to "left";
  • "width" - view width
  • "height" - view height
  • "centerX" - view center on X coordinate
  • "centerY" - view center on Y coordinate
  • "baseline" - text baseline (in case of multiple lines - last line baseline)
  • "lastBaseline" - see previous
  • "firstBaseline" - text baseline (in case of multiple lines - first line baseline)
  • "leftMargin" - left view margin
  • "rightMargin" - right view margin
  • "topMargin" - top view margin
  • "bottomMargin" - bottom view margin
  • "leadingMargin" - depends on interface, for English equals to "leftMargin", for Arabic (or other RTL language) - to "rightMargin"
  • "trailingMargin" - depends on interface, for English equals to "rightMargin", for Arabic (or other RTL language) - to "leftMargin"
  • "centerXWithinMargins" - X center of the view considering margins
  • "centerYWithinMargins" - Y center of the view considering margins
  • "notAnAttribute" - reserved keyword, used as a second attribute if it does not exist (and second view is nil)

The following values can be used for the "relation":

  • "lessThanOrEqual"
  • "equal"
  • "greaterThanOrEqual"

Actions

Each action should have the following parameters:

  • "id" - ID of the element, which will be used for tracking the action
  • "type" - type of action
  • "name" - name of action in Maxymiser

Currently, the following action types can be used:

  • "ElementView" - supported by any element. Triggered every time an element appears in the views tree
  • "TouchUpInside" - supported by UIButton elements. Triggered when the user taps a button
  • "DidSelectCell" - supported by UITableView or UITableViewCell. Triggered when user selects table cell

Important: Do not bind 'ElementView' actions to table cells as each cell will cause action tracking.

Supported UI Element transformations

Important: As some transformations do not have any checks on minimum or maximum values therefore please test your variants carefully before publishing to live.

UIView Transformations