Choose Variations Using Kotlin SDK

The Choose Variations call activates one or more Dynamic Yield campaigns by name and retrieves data necessary to render personalized content. Learn more about the Choose call in the Experience API guide.

Note: All Choose Variations calls are asynchronous.

Parameters

Note: Either selectorNames or selectorGroups must be provided in the request body.

ParameterData Structure TypeMandatoryDescription
selectorNames
required if selectorGroups is not used
List<String>NoA list of campaigns to choose variations for. A selector represents a technical name for a campaign.
Learn more about using selectors in your campaigns.
selectorGroups
required if selectorNames is not used
List<String>NoCall a group of selectors instead of listing each selector individually.
Learn more about working with selector groups.
selectorPreviewsList<String>NoCampaigns to generate previews for.
Learn more about enabling preview mode.
pagePageYesAn object containing information about the currently viewed page.
cartList<CartItem>NoA list of all items currently in the cart.
For Restaurant Recommendations campaigns only.
branchIdStringNoThe unique identifier of the branch.
Applies only when branch context exists and must match the IDs in the branch feed.
dayPart
(Restaurants only)
DayPartNoDefines the period of the day the request relates to.
For Restaurant Recommendations campaigns only.
orderFulfillmentOrderFulfillmentNoThe fulfillment type of the order the request relates to.
Applies only when branch context exists and must match the IDs in the branch feed.</span
pageAttributesMap<String, PageAttribute>NoKey-value pairs that can be used for targeting. Values can be strings or numbers.
listedItemsList<String>NoA list of SKUs to be presented on the page to be sorted by a Sorting Optimizer campaign.
cuidStringNoUser identifier value.
Applies only when the SDK is initialized with sharedDevice as true
cuidTypeStringNoUse this identifier type to identify users across devices (for example, customer_id, account_id, or he for SHA-256 hashed email). Note: Do not include any personal information in this ID.
Applies only when the SDK is initialized with sharedDevice as true
optionsChooseOptionsNoRequest configuration parameters (report a new pageview/impression, return additional metadata).
recsProductDataRecsProductDataNoAn object with 2 parameters:
* fieldFilter to specify the fields to be included in the recommendation campaign response
* skusOnly to fetch only the SKUs to reduce the size of the response.
See the Choose API reference for more information.

Example

private suspend fun chooseVariationsWithAllParameters() { 
    var result = DYSdk.getInstance().chooseVariations( 
        page = Page.homePage(pageLocation = "ScreenName", pageReferrer = "otherScreenName"), 
        selectorNames = listOf("example-campaign-1", "example-campaign-2"), 
        selectorGroups = listOf("example-group"), 
        selectorPreviews = listOf("example-previews"), 
        branchId = "example-branch-id", 
        options = ChooseOptions(), 
        pageAttributes = mapOf( 
            "Attr1" to PageAttribute("value-1"), 
            "Attr2" to PageAttribute(5), 
        ), 
        recsProductData = RecsProductDataOptions(), 
    ) 
} 
private suspend fun chooseVariationsWithAllParameters() { 
    var result = DYSdk.getInstance().chooseVariations( 
        page = Page.homePage(pageLocation = "ScreenName", pageReferrer = "otherScreenName"), 
        selectorNames = listOf("example-campaign-1", "example-campaign-2"), 
        selectorGroups = listOf("example-group"), 
        selectorPreviews = listOf("example-previews"), 
        dayPart = DayPart.DINNER, 
        cart = listOf( 
            CartItem( 
                productId = "example-id", quantity = 1u, itemPrice = 5f, innerProducts = listOf( 
                    CartInnerItem(productId = "example-id", quantity = 1u, itemPrice = 3f) 
                ) 
            ) 
        ), 
        branchId = "example-branch-id", 
        options = ChooseOptions(), 
        pageAttributes = mapOf( 
            "Attr1" to PageAttribute("value-1"), 
            "Attr2" to PageAttribute(5), 
        ), 
        recsProductData = RecsProductDataOptions(), 
    ) 
} 

Return Values

class DYChooseResult(
    val choices: List<Choice>? = null,
    val status: ResultStatus,
    val warnings: List<Warning>? = null,
    val error: Exception? = null,
    val rawNetworkData: RawNetworkData? = null,
) 

DYChooseResult

inherits from DYResult

private suspend fun chooseVariationResult() { 
     var chooseResult = DYSdk.getInstance().chooseVariations( 
        page = Page.homePage("ScreenName"), 
        selectorNames = listOf("example-campaign-1", "example-campaign-2") 
    ) 
    when (chooseResult.status) { 
        ResultStatus.SUCCESS -> { 
            chooseResult.choices?.forEach { choice -> 
                //Search for your campaign by name 
            } 
        } 
        ResultStatus.WARNING -> { 
            chooseResult.choices?.forEach { choice -> 
                //Search for your campaign by name
            } 
            chooseResult.warnings?.let { 
                 //Log the warnings  
            } 
        } 
        ResultStatus.ERROR -> { 
            chooseResult.error?.let { exception -> 
                //Obtain the exception object here 
            } 
            chooseResult.rawNetworkData?.let { rawNetworkData -> 
                //Log rawNetworkData to further investigate the error 
            } 
        } 
    } 
} 

Choice

PropertyDescriptionData Structure Type
idThe choice’s IDInt
decisionIdThe decision’s ID as returned from the serverString
nameThe name of the campaign (selector)String
typeThe choice’s typeChoiceType (DECISION, RECS_DECISION, STORE_RECS_DECISION, SORTING_DECISION, NO_DECISION)
variationsThe campaign’s chosen variationsList<Variation>
groupsThe groups the requested campaigns belong toList<String>

Variation

PropertyDescriptionData Structure Type
idThe variation IDInt
analyticsMetadataReturns additional metadata. Useful for debugging and reporting to analytics tools.AnalyticsMetadata
payloadPossible values: CustomJsonPayload, RecsPayload, StoreRecsPayload, SortingRecsPayload.Payload
titleThe title of the tray served in the variation
For Restaurant Recommendations campaigns only.
String

Handling the DYResult

PropertyDescriptionData Structure Type
statusThe Choose call's status. If the type is "WARNING," it indicates that the request was successful, but there are warnings associated with the response.ResultStatus:
SUCCESS, ERROR, WARNING
warningsList of warnings returned from the server. Each warning item has a code and message.List<Warning>?
errorErrors and exceptionsException?
choicesThe chosen variations returnedList<Choice>?
rawNetworkDataNetwork-related data (for debugging purposes)RawNetworkData?

Dealing with partial success

The Dynamic Yield SDK chooseVariations call supports multiple campaigns in the same call. In a scenario where results for some of the campaigns return successfully, while there is an error for others, the result status returned is “WARNING”.

The Choice return object will contain values only for the campaigns that have returned successfully.

Campaign types

The available campaign types are: API Custom Code, API Recommendations, and Restaurant Recommendations. Each variation in the return value matches the campaign type that was determined in the campaign creation process in ExperienceOS.

API Custom Code campaigns

Custom API campaigns let you use the power of Dynamic Yield A/B testing and automatic allocation, while fully controlling how the campaigns are rendered on your app.

CustomJsonPayload

PropertyDescriptionData Structure Type
typeThe decision typeDecisionType=DECISION
dataThe variation dataString (JSON format)

Example

private suspend fun chooseCustomJsomVariationExample() { 
    var chooseResult = DYSdk.getInstance().chooseVariations( 
        page = Page.homePage("ScreenName"), 
        selectorNames = listOf("custom-json-campaign") 
    ) 
    when (chooseResult.status) { 
        ResultStatus.SUCCESS, ResultStatus.WARNING -> { 
            chooseResult.choices?.firstOrNull { it.name == "custom-json-campaign" } 
                ?.let { choice -> 
                    if (choice.type == ChoiceType.DECISION) 
                    //Assumming there is only one variation 
                        (choice.variations.firstOrNull()?.payload as? CustomJsonPayload)?.let { payload -> 
                            var data = payload.data
                        } 
                } 
        } 
        ResultStatus.ERROR -> TODO() 
    } 
} 

API Recommendations campaigns

Recommendations enable you to automatically display the most relevant items to each user.

RecsPayload

PropertyDescriptionData Structure Type
typeThe decision typeDecisionType=RECS_DECISION
dataThe variation dataRecsData

RecsData

PropertyDescriptionData Structure Type
customThe variation custom dataString (JSON format)
slotsA list of objects containing data for each slotList<RecsSlot>

Example

private suspend fun chooseRecsVariationExample() { 
    var chooseResult = DYSdk.getInstance().chooseVariations( 
        page = Page.homePage("ScreenName"), 
        selectorNames = listOf("recs-campaign") 
   			 ) 
    when (chooseResult.status) { 
        ResultStatus.SUCCESS, ResultStatus.WARNING -> { 
            chooseResult.choices?.firstOrNull { it.name == "recs-campaign" }?.let { choice -> 
                if (choice.type == ChoiceType.RECS_DECISION) 
                //Assuming there is only one variation 
                    (choice.variations.firstOrNull()?.payload as? RecsPayload)?.let { payload -> 
                        var slots = payload.data.slots
                        var custom = payload.data.custom 
                    } 
            } 
        } 
        ResultStatus.ERROR -> TODO() 
    } 
} 

Sorting Optimizer API campaigns

Sorting optimizer enables you to sort your category pages on your app, based on personalization criteria and business logic, to help users more easily find products that match their needs and preferences for an enhanced shopping experience that increases the likelihood of purchase.

SortingPayload

PropertyDescriptionData Structure Type
typeThe decision typeDecisionType=SORTING_DECISION
dataThe variation dataSortingData

SortingData

PropertyDescriptionData Structure Type
slotsA list of objects containing data for each slotList<SortingRecsSlot>

Example

private suspend fun chooseRecsVariationExample() { 
    var chooseResult = DYSdk.getInstance().chooseVariations( 
        page = Page.homePage("ScreenName"), 
        selectorNames = listOf("recs-campaign") 
   			 ) 
    when (chooseResult.status) { 
        ResultStatus.SUCCESS, ResultStatus.WARNING -> { 
            chooseResult.choices?.firstOrNull { it.name == "recs-campaign" }?.let { choice -> 
                if (choice.type == ChoiceType.RECS_DECISION) 
                //Assuming there is only one variation 
                    (choice.variations.firstOrNull()?.payload as? RecsPayload)?.let { payload -> 
                        var slots = payload.data.slots
                        var custom = payload.data.custom 
                    } 
            } 
        } 
        ResultStatus.ERROR -> TODO() 
    } 
} 

Restaurant Recommendations campaigns

StoreRecsPayload

PropertyDescriptionData Structure Type
typeThe decision typeDecisionType=STORE_RECS_DECISION
dataThe variation dataStoreRecsData

StoreRecsData

PropertyDescriptionData Structure Type
customThe variation dataString (JSON format)
slotsA list of objects containing data for each slotList<StoreRecsSlot>

Example

private suspend fun chooseRestaurantsRecsVariationExample() { 
    var chooseResult = DYSdk.getInstance().chooseVariations( 
        page = Page.homePage("ScreenName"), 
        selectorNames = listOf("qsr-recs-campaign") 
    ) 
    when (chooseResult.status) { 
        ResultStatus.SUCCESS, ResultStatus.WARNING -> { 
            chooseResult.choices?.firstOrNull { it.name == "qsr-recs-campaign" }?.let { choice -> 
                if (choice.type == ChoiceType.STORE_RECS_DECISION) 
                //Assumming there is only one variation 
                    (choice.variations.firstOrNull()?.payload as? StoreRecsPayload)?.let { payload -> 
                        var slots = payload.data.slots 
                    } 
            } 
        } 
        ResultStatus.ERROR -> TODO() 
    } 
}