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 Dynamic Yield 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 Dynamic Yield console.
-
Call Choose to get the desired variations for these campaigns. If the Dynamic Yield script isn't running on the page, you may also wish to report a new pageview together with the request for variations. Alternatively, you can report on the pageview in a separate call.
-
Now that 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 Variations response.
Recommended use
Even before you have a full view of which campaigns should be integrated in your application, it's best to integrate a Choose call in all page types in your application with the proper page context, without referring to any campaign.
Now, here's the fun part: Along with those responsible for creating and managing campaigns (marketers, product managers, merchandisers, or other stakeholders in your organization), identify the places in your application 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.
Making a Choose request
The following table includes the structure and parameters of Choose calls.
Request from:
In the US:
https://dy-api.com/v2/serve/user/choose
https://dy-api.com/v2/collect/user/pageview
In the EU:
https://dy-api.eu/v2/serve/user/choose
https://dy-api.eu/v2/collect/user/pageview
Note: When using client-side keys from a browser use the sub-domain direct, which supports CORS headers (for example, https://direct.dy-api.com/v2/serve/user/choose; in the EU use direct.dy-api.eu). This also applies to using browser-based REST clients. For collection endpoints (pageviews, user engagement, or events) from within a browser, use https://direct-collect.dy-api.com/v2/collect/...
See also the API Reference for Choosing Variations and Reporting Pageviews.
HTTP Method |
|
Headers |
|
Body Parameters |
In API-only mode, you are responsible for generating IDs for new users, and persisting them to existing ones. Use this parameter:
In API-only mode, the identifier is for you to generate and persist:
There are additional options for Recommendation campaigns. |
Sample code
Here's a sample request. The context is a Product Details Page (aka PDP) in an imaginary
e-commerce website, at sugoi-ne.com:
curl --request POST \
--url https://dy-api.com/v2/serve/user/choose \
--header 'content-type: application/json' \
--header 'DY-API-Key: baadc6ba740a352c9106dc7857a7eb9c' \
--data '{
"user": {
"dyid": "-4350463893986789401",
"dyid_server": "-4350463893986789401"
},
"session": { "dy": "ohyr6v42l9zd4bpinnvp7urjjx9lrssw" },
"selector": { "names": ["PDP Top Banner", "PDP Recs"] },
"context": {
"page": {
"type": "PRODUCT",
"data": ["7383723-010"],
"location": "https://sugoi-ne.com/men-pants/p7383723-010",
"referrer": "https://sugoi-ne.com/men-pants",
"locale": "en_US"
},
"device": {
"userAgent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
"ip": "54.100.200.255"
},
"pageAttributes": { "customPageAttribute": "someValue" }
},
"options": { "isImplicitPageview": false }
}'
curl --request POST \
--url https://dy-api.com/v2/serve/user/choose \
--header 'content-type: application/json' \
--header 'DY-API-Key: baadc6ba740a352c9106dc7857a7eb9c' \
--data '{
"user": { "id": "yaexono4ohphania" },
"session": { "custom": "iquahngaishe2koh" },
"selector": { "names": ["PDP Top Banner", "PDP Recs"] },
"context": {
"page": {
"type": "PRODUCT",
"data": ["7383723-010"],
"location": "https://sugoi-ne.com/men-pants/p7383723-010",
"referrer": "https://sugoi-ne.com/men-pants",
"locale": "en_US"
},
"device": {
"userAgent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
"ip": "54.100.200.255"
},
"pageAttributes": { "customPageAttribute": "someValue" }
},
"options": { "isImplicitPageview": true }
}'
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 choose the same campaign name in multiple places but do not pass the same attributes anywhere, targeting might not work the way you expected it to.
Dynamic Yield does also supports the onboarding of first- and third-party data into our backend, 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 separation of concerns: The calls you make to choose in various places in your code base do not need to know or pass any attributes. New attributes can always be added and be used through the Admin UI with no changes to your code calling choose.
Using the Pageview endpoint
Use to report a pageview, without any connected campaign. Pageview is basically an alias for Choose, but without any campaign names.
Although reporting a pageview and choosing variations for a campaign are functionally different actions, when a page is rendered, whether the server is responsible for crafting the full HTML or only returning a data-only payload for an SPA or mobile app, the rendering steps are similar.
Note, however, that if you are using an API-only implementation, the pageviews are reported implicitly by default, whereas if you have the Dynamic Yield script on your site, they are not reported in the call because the script reports the pageviews.
Request from:
In the US:
https://dy-api.com/v2/collect/user/pageview
In the EU:
https://dy-api.eu/v2/collect/user/pageview
If you only want to report a pageview, with no relevant campaigns, you can also use the pageview endpoint. This is simply an alias for choose but without any campaign name.
Page context types
Here are your options for context.page.type and the appropriate data argument for each.
Type | Data | Example |
---|---|---|
Homepage | Empty | "type": "HOMEPAGE", "data": [] |
Category Page (PLP) | Full hierarchy of category names. | "type": "CATEGORY", "data": ["Men", "Shoes", "Sneakers"] |
Product Page (PDP) | Product SKU. Always a single string. | "type": "PRODUCT", "data": ["p61239"] |
Cart Page (Application page in Financial Institution sections) |
List of SKUs for products currently in the cart. A list of strings. Can be empty. For Financial Intitutions, use the cart page context for application pages with the specific productID instead of the SKU. |
"type": "CART", "data": ["p61239", "p17834"] |
Other Page Type | Empty | "type": "OTHER", "data": [] |
Sample responses
{
"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"
}
}
]
}
}
}
]
}
]
}
{
"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
Code | Meaning |
---|---|
200 | Request succeeded |
400 | Error parsing request |
401 | Invalid or missing API key |
403 | Access denied for a valid API key |
405 | Wrong HTTP method (not POST, in this case) |
422 | Request body did not match schema |
429 | Too many requests received |
451 | Wrong key type was used (server-side key used from the client-side or client-side key used from the server-side) |
499 | Internal 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. |
500 | Unspecified internal error |