Choose Variations Using Swift 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
[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
[String]NoCall a group of selectors instead of listing each selector individually.
Learn more about working with selector groups.
pagePageYesAn object containing information about the currently viewed page.
selectorPreviews[String]NoCampaigns to generate previews for.
Learn more about enabling preview mode.
dayPart
(Restaurants only)
DayPartNoDefines the period of the day the request relates to.
For Restaurant Recommendations campaigns only.
cart[CartItem]NoA list of all items currently in the cart.
branchIdStringNoThe unique identifier of the branch.
Applies only when branch context exists and must match the IDs in the branch feed.
optionsChooseOptionsNoRequest configuration parameters (report a new pageview/impression, return additional metadata).
pageAttributes[String : PageAttribute]NoKey-value pairs that can be used for targeting. Values may be strings or numbers.
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

let result = await DYSdk.shared().choose
            .chooseVariations(
                selectorNames: ["example-campaign-1", "example-campaign-2"],
                page: Page.homePage(pageLocation: "Page Location", referrer: "otherScreenName"),
                selectorGroups: ["example-group"],
                selectorPreviews: ["example-previews"],
                branchId: "example-branch-id",
                options: ChooseOptions(),
                pageAttributes: ["Attr1": PageAttribute("value-1"),
                                 "Attr2": PageAttribute(5)],
                recsProductData: RecsProductDataOptions(),
            )
let result = await DYSdk.shared().choose
            .chooseVariations(
                selectorNames: ["example-campaign-1", "example-campaign-2"],
                page: Page.homePage(pageLocation: "Page Location", referrer: "otherScreenName"),
                selectorGroups: ["example-group"],
                selectorPreviews: ["example-previews"],
                dayPart: .dinner,
                cart: [CartItem(productId: "example-id", quantity: 1, itemPrice: 5, innerProducts: [CartInnerItem(productId: "example-id", quantity: 1, itemPrice: 3)])],
                branchId: "example-branch-id",
                options: ChooseOptions(),
                pageAttributes: ["Attr1": PageAttribute("value-1"),
                                 "Attr2": PageAttribute(5)],
                recsProductData: RecsProductDataOptions(),
            )

Return Values

class DYChooseResult: DYResult {
    public let choices: [Choice]?
    public let status: ResultStatus
    public let error: Error?
    public let warnings: [Warning]?
    public let rawNetworkData: RawNetworkData?		   
}

DYChooseResult

inherits from DYResult

 func choose() async {
        let result = await DYSdk.shared().choose
            .chooseVariations(
                selectorNames: ["example-campaign-1", "example-campaign-2"],
                page: Page.homePage(pageLocation: "Page Location", referrer: "otherScreenName")
           			 )

        switch result.status {
        case .success:
            if let choices = result.choices {
                for choice in choices {
                    //                        ...
                }
            }

        case .error:
            if let error = result.error {
                print(error)
            }

        case .warning:
            if let choices = result.choices {
                for choice in choices {
                    //                        ...
                }
            }

            if let warnings = result.warnings {
                for warning in warnings {
                    print(warning)
                }
            }

        }
    }

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, recsDecision, storeRecsDecision, noDecision)
variationsThe campaign’s chosen variations[Variation]
groupsThe groups the requested campaigns belong to[String]

Variation

PropertyDescriptionData Structure Type
idThe variation IDInt
analyticsMetadataReturns additional metadata. Useful for debugging and reporting to analytics tools.AnalyticsMetadata
payloadPossible values: CustomJsonPayload, RecsPayload, StoreRecsPayloadPayload

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.[Warning]?
errorErrors and exceptionsError?
choicesThe chosen variations returned[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

 func chooseCustomJsonVariation() async throws {
        let chooseResult = await DYSdk.shared().choose.chooseVariations(
            selectorNames: ["custom-json-campaign"],
            page: Page.homePage(pageLocation: "ScreenName")
        )

        switch chooseResult.status {
        case .success, .warning:
            if let choices = chooseResult.choices,
               let customChoice = choices.first(where: { $0.name == "custom-json-campaign" }) {

                if customChoice.type == .decision {
                    // Assuming there is only one variation
                    if let firstVariation = customChoice.variations.first,
                       let payload = firstVariation.payload as? CustomJsonPayload {

                        let data = payload.data

                        // Use json data here (string)
                    }
                }
            }

        case .error:
            // Handle error case
            break
        }
    }

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 slot[RecsSlot]

Example

 func chooseRecsVariationExample() async throws {
        let chooseResult = await DYSdk.shared().choose.chooseVariations(
            selectorNames: ["recs-campaign"],
            page: Page.homePage(pageLocation: "ScreenName")
        )
        switch chooseResult.status {
        case .success, .warning:
            if let choices = chooseResult.choices,
               let recsChoice = choices.first(where: { $0.name == "recs-campaign" }) {
                if recsChoice.type == .recsDecision {
                    // Assuming there is only one variation
                    if let firstVariation = recsChoice.variations.first,
                       let payload = firstVariation.payload as? RecsPayload {
                        let slots = payload.data.slots
                        let custom = payload.data.custom
                        // Use slots and custom data here
                    }
                }
            }
        case .error:
            break
            // Handle error case
        }
    }

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 slot[StoreRecsSlot]

Example

 func chooseRestaurantsRecsVariation() async throws {
        let chooseResult = await DYSdk.shared().choose.chooseVariations(
            selectorNames: ["qsr-recs-campaign"],
            page: Page.homePage(pageLocation: "ScreenName")
        )

        switch chooseResult.status {
        case .success, .warning:
            if let choices = chooseResult.choices,
               let choice = choices.first(where: { $0.name == "qsr-recs-campaign" }) {

                if choice.type == .storeRecsDecision {
                    // Assuming there is only one variation
                    if let firstVariation = choice.variations.first,
                       let payload = firstVariation.payload as? StoreRecsPayload {

                        let slots = payload.data.slots

                        // Use slots here
                    }
                }
            }

        case .error:
            // Handle error case
            break
        }
    }