Choosing Variations (the Choose endpoint)

The Choose endpoint activates one or more Dynamic Yield campaigns by name. The activation resolves targeting rules and test group allocations automatically and returns the correct variation for the user. Typically, you would make this call as part of your larger page and content rendering pipeline. The campaign settings are all controlled in the Experience OS console. 

The Choose rendering flow

Determine all campaigns that are an inherent part of the page content, such as in-line elements, variable values, and configuration settings. Each campaign has its unique API Selector Name defined in the Experience OS console.

Call Choose to get the desired variations for these campaigns. If the Dynamic Yield script isn't running on the page, you might also want to report a new pageview together with the request for variations. Alternatively, you can report on the pageview in a separate call.

When you have the chosen variations' payloads, the full page can be constructed and rendered.
Note that some content doesn't need to be rendered immediately as part of the synchronous process of displaying the page, and can be deferred to a separate asynchronous call. Typically, these are overlays or notifications that are shown over the page, recommendation widgets that are below the fold, or additional content that is lazy-loaded only when scrolling or expanding the view.
For these content types, you can make extra Choose calls to fetch the needed campaign variations, while making sure to turn off the implicit pageview in the arguments (see the arguments in Making a choose request).

📌

Note: Users attributed to a control group receive an empty variation in the Choose response.

Recommended use

Even before you have a full view of which campaigns you'll be running, it's best practice to integrate a Choose call on all page types with the proper page context, without referring to any campaign.

Work with the team responsible for creating and managing campaigns (marketers, product managers, merchandisers, or other stakeholders in your organization) to identify where Dynamic Yield-managed campaigns should run. Any campaign you run has an API Selector Name that you will use to get the chosen variation.

Now, adapt your call to Choose in each page type, so that you also pass the relevant campaign names in the selector parameter. It is perfectly valid to call campaigns that have only a single variation, containing a default payload, in preparation for allowing testing and targeting multiple variations in that component later, without the need for further code changes.

To avoid the risk of reaching our rate limit, we recommend that you group your selector names. Using selector groups is the best practice, or alternatively, you can add multiple selector names into a single request.

Using ad-hoc page attributes vs. user data onboarding

While pageAttributes is great as a quick way to enable targeting over custom data, this capability has inherent limitations. These attributes are usable only for the specific campaigns for which you passed these attributes. If you use the same campaign name in multiple places but do not pass the same attributes anywhere, targeting might not work the way you expect it to.

Dynamic Yield also supports the onboarding of first- and third-party data into our back end, which can then be used for audience building and targeting. The latter option is based on a strong schema and usually requires more work to set up. For more information, see User Data API.

The additional benefit is that you get a separation of concerns: The Choose calls you make in various places in your code base don't need to know or pass any attributes. New attributes can always be added and used through the Experience OS console with no changes to your code for calling Choose.

Rate limits and response time

For 95% of cases, we see a response time of 10-140 ms for Choose calls that include recommendation campaigns, and 10-30ms for Choose calls with custom campaigns without recommendations.

The Choose endpoint is globally limited to a rate of 22,000 requests per minute by default.
All other endpoints can be used with an unlimited rate of requests. When you reach your request limit, you get a status code of "429 - Too many requests" as your response. Contact your Technical Account Manager if your use case requires a different rate-limit enforcement configuration.

Sample responses

Response body

{  
  "choices": \[  
    {  
      "id": 5,  
      "name": "PDP Top Banner",  
      "type": "DECISION",  
      "decisionId": "aGVsbG8K",  
      "variations": [  
        {  
          "id": 52,  
          "payload": {  
            "type": "CUSTOM_JSON",  
            "data": {  
              "key1": "value1",  
              "key2": "value2"  
            }  
          }  
        }  
      ]  
    },  
    {  
      "id": 24,  
      "name": "PDP Recs",  
      "type": "RECS_DECISION",  
      "decisionId": "d29ybGQK",  
      "variations": \[  
        {  
          "id": 203,  
          "payload": {  
            "type": "RECS",  
            "data": {  
              "slots": [  
                {  
                  "slotId": "aGVsbG93b3JsZAo=",  
                  "sku": "6323723",  
                  "productData": {  
                    "name": "Plaid shirt",  
                    "price": 39.99,  
                    "url": "https://website.com/men-pants/p6323723-020"  
                  }  
                },  
                {  
                  "slotId": "d2VsY29tZWR1ZAo=",  
                  "sku": "5413764",  
                  "productData": {  
                    "name": "Khaki pants",  
                    "price": 59.99,  
                    "url": "https://website.com/men-pants/p5413764-010"  
                  }  
                }  
              ]  
            }  
          }  
        }  
      ]  
    }  
  ]  
}

Response body – control group

{  
    "choices": \[  
        {  
            "id": 652700,  
            "name": "demoBanner",  
            "type": "DECISION",  
            "variations": \[],  
            "groups": [  
                "demo"  
            ],  
            "decisionId": null  
        }  
    ],  
    "cookies": [  
        {  
            "name": "_dyid_server",  
            "value": "7282320792394869879",  
            "maxAge": "31556926"  
        },  
        {  
            "name": "_dyjsession",  
            "value": "e3xi77qrxbsxxxmi18d8kxek6tdd12qj",  
            "maxAge": "1800"  
        }  
    ]  
}

The response is always formatted as JSON and encoded as UTF-8.

A successful response (HTTP 200) returns an array of choices, containing the chosen variations (one or more) for each campaign name passed in the request. With each variation comes its payload, whose contents vary by the returned type.

Note that campaigns can be set up in the Dynamic Yield console to choose more than one variation out of the total available. Hence, variations is always returned as an array.

Returning multiple variations for a campaign

This is useful when you want to render a slider showing, for example, the best 3 out of 8 available banners. Another example is rendering a list of 3 special offers out of a longer list. Variations in such campaigns are usually updated through a Variation feed, rather than manually created in the console.

For each returned campaign, first note the type of decision. This also determines the payload type within and can be one of the following:

DECISION for custom campaigns. In this case, the only supported payload type is CUSTOM_JSON, meaning that defining the payload in the Dynamic Yield console and parsing it in the caller is completely up to you. In this case, it is important to store the unique decisionId for reporting clicks over the rendered variation.
To simplify the creation of variations in the console and prevent typing errors, you can create templates with multiple built-in variable types.

RECS_DECISION for recommendation campaigns. In this case, the payload type is always the built-in RECS, as in the sample response. In this case, you can ignore the returned decisionId, as the payload contains a slotId identifier per recommended item.

NO_DECISION for any campaign type where no targeting rule was matched and there is no default experience in the campaign. You should always be ready to handle this type, as the contents of the campaign can change at any time in the Dynamic Yield console, and it is perfectly valid in many cases not to return any variation at all, relying on hard-coded default behavior to kick in instead. For this type, there is no decisionId or payload.

The payload data

With the CUSTOM_JSON payload type, it's simple - this is totally up to you. Please check out the tutorial for examples.

For the RECS type, data contains an array of objects. Each is a single recommended item, or "slot." The number of slots returned is defined in the Dynamic Yield console.

For each slot you have its sku, plus a productData object containing all product attributes from the feed, and a slotId. This identifier represents the slot contents in this unique recommendations response, and you need to keep it for reporting clicks over that specific slot. Given this slotId, our backend knows all the details about that slot for reporting purposes, such as which recommendations strategy was used, whether there was a fallback to another strategy, and more.

HTTP response codes

CodeMeaning
200Request succeeded
400Error parsing request
401Invalid or missing API key
403Access denied for a valid API key
405Wrong HTTP method (not POST, in this case)
422Request body does not match schema
429Too many requests received
451Wrong key type was used (server-side key used from the client-side or client-side key used from the server-side)
499Internal server error
Note: If you receive 499 errors for only a low percentage of calls, this is part of the statistical expectancy when dealing with a large number of network calls.
500Unspecified internal error