The custom analytics integration allows you to analyze Dynamic Yield campaigns in your analytics platform. This article details how to set it up for Adobe Analytics.
The most common use case for integrating with a 3rd party Analytics platform is to record information about which Dynamic Yield Experiences (e.g. Campaigns, Variations, Product Recommendations) visitors were exposed to.
There are three moving parts to the integration:
- A live Dynamic Yield Campaign, with the Execute Custom Integrations toggle turned on, which enables the Campaign to expose its metadata (eg.. Campaign, Experience and Variation Names) whenever it is served to a user.
- A Custom Integration Function, which acts as a translation layer between Dynamic Yield and your analytics stack, and defines how the exposed data is transformed and stored. We will use these functions to create a data layer object.
- A call to Adobe Analytics. Depending on your implementation, this can be done directly from Dynamic Yield or from your Tag Manager.
Setting Up The Integration
Setting up the integration has 3 steps:
- Configure Adobe Analytics to receive the integration data, using a List Variable.
- Set up a global data layer object using Dynamic Yield’s Custom Analytics Integration functions
- Populate the adobe list variable with the contents of the data layer, and send a call to Adobe. This can be done via Dynamic Yield or your tag manager solution.
Step 1: Configure a List Variable in Adobe Analytics
Adobe Analytics’ list variables allow you to use a single delimiter-separated string to store multiple values, which can then be split and analyzed independently. Each value will represent a different campaign, experience, and variation combination.
To set up a list variable, navigate to its configuration page following this documentation, and configure one of your variables as recommended below:
- Name: “Dynamic Yield”
- Expiration: this is the equivalent of Dynamic Yield’s Attribution Window. If Attribution IQ is part of your Adobe package, you will be able to edit expiration on demand when analyzing your results. If you don’t, you will have to make a choice upfront. In this case, we recommend selecting the most common attribution window you use in Dynamic Yield. If Dynamic Yield experiences are set up with:
-
- 7-Day attribution, set expiration to Custom attribution = 7 days.
-
- Session attribution, set expiration to Visit. Note that sessions/visits are defined differently in Dynamic Yield and Adobe. When choosing this expiration, you might notice higher discrepancies across platforms than when using time-based expiration. Learn more about Session definition in Dynamic Yield.
-
- Post-Event or Post-Click Attribution, replicating this in Adobe Analytics will require you to additionally create Sequential Segments, which include Visits or Visitors who also triggered the Adobe Analytics analog of the conditional event utilized for Post-Event attribution in Dynamic Yield.
- Value Delimiter: set it to “|” (pipe). Changing it to a different delimiter requires adjustments to the script in step 2 of the integration.
- Allocation: Set it to “Full” to mimic Dynamic Yield’s attribution logic, so that each individual test receives full conversion credit.
- Max Values: 250
Step 2: Set up a Global Data Layer Object
Once Adobe Analytics is ready to receive data from Dynamic Yield, we will create a data layer object, via Dynamic Yield’s Custom Analytics integration.
The data layer object will be called dyGlobalObject, and will contain three elements:
- events: an array of objects containing different types of events, triggered by different types of interactions. These events can be used to trigger individual calls to Adobe Analytics. In this setup however we will bundle the content of multiple events using the list variable, reducing the number of calls to Adobe Analytics to once per page to reach a good compromise between tracking accuracy and costs.
- listVar: a single string containing a pipe-concatenated distinct list of campaign-experiment-variations loaded in the page. With each new impression event above, the relevant information will be appended to the existing value. The Adobe list variable can be populated directly with this value.
- uniqueImp: an array that is used to create the ‘listvar’ field above.
The dyGlobalObject’s events array can be populated by different events, each carrying specific information we might want to record in Adobe:
- Variation impression: this event will execute the function every time a test or campaign variation is served for a visitor on your site.
- Recommendation impression: this event will execute the function every time a set of items were rendered on the page. It carries information about the algorithm and the items that were recommended.
To push information on variation impressions to data layer
- In Dynamic Yield, go to Settings › Integrations.
- Click Custom Analytics Platform and click Enable Integration.
- Select Variation Impression.
- Replace the example code with the following, and then save.
function afterVariationSelected(tagId, tagName, experienceName, experience, variations, isNoAction) {
window.dyGlobalObject = window.dyGlobalObject || {};
window.dyGlobalObject.events = window.dyGlobalObject.events || [];
window.dyGlobalObject.listVar = window.dyGlobalObject.listVar || [];
window.dyGlobalObject.uniqueImp = window.dyGlobalObject.uniqueImp || [];
var timestamp = Math.round((new Date()).getTime() / 1000);
var expName = decodeURI(experience.name);
var experienceId = experience.id;
if (isNoAction) {
addExperienceToGlobalObject(tagId, tagName, experienceId, expName, isNoAction, variations[0].id, 'Control', timestamp);
} else {
variations.forEach(function(variation) {
addExperienceToGlobalObject(tagId, tagName, experienceId, expName, isNoAction, variation.id, decodeURI(variation.name), timestamp);
});
}
if (DYO.userAgent.isSafari(navigator.userAgent)) {
DY.CS = DY.CS || {};
DY.CS.reportToAdobeReady = DY.CS.reportToAdobeReady || DYO.CoreUtils.waitForVariable('DY.CS.reportToAdobe');
DY.CS.reportToAdobeReady.then(function() {
DY.CS.reportToAdobe.report();
});
}
function addExperienceToGlobalObject(tagId, tagName, experienceId, expName, isNoAction, variationId, variationName, timestamp) {
window.dyGlobalObject.events.push({
'event': 'impression',
'cmpId': parseInt(tagId),
'cmpName': tagName,
'expId': experienceId,
'expName': expName,
'varId': variationId,
'varName': variationName,
'isCG': isNoAction,
'eventTs': timestamp
});
var listItem = [tagName, expName, variationName].join('.');
if (window.dyGlobalObject.uniqueImp.indexOf(listItem) === -1) {
window.dyGlobalObject.uniqueImp.push(listItem);
}
window.dyGlobalObject.listVar = window.dyGlobalObject.uniqueImp.join('|');
}
} - After a few minutes, open the browser console on your website, where at least one Dynamic Yield campaign is running, and type dyGlobalObject. You should see the events array being populated with one event of type impression for each of the running campaigns, and the listVar element is populated with the pipe-concatenated list [campaign_name].[experience_name].[variation_name], like the example below:
{
"events": [{
"cmpId":524122,
"cmpName":"Custom Action: Set Cookie 1",
"event":"impression",
"eventTs":1605468964,
"expId":994350,
"expName":"Experience 1",
"isCG":false,
"varId":"13487153",
"varName":"Variation 1"
}, {
"cmpId":525193,
"cmpName":"Recommendation",
"event":"impression",
"eventTs":1605468964,
"expId":997366,
"expName":"Experience 1",
"isCG":false,
"varId":"13629597",
"varName":"Variation 1"
}],
"listVar": "Custom Action: Set Cookie 1.Experience 1.Variation 1|Recommendation.Experience 1.Variation 1",
"uniqueImp": [
"Custom Action: Set Cookie 1.Experience 1.Variation 1",
"Recommendation.Experience 1.Variation 1"
]
}
Note that in our integration function above, in the following line:
var listItem = [tagName, expName, variationName].join('.');
We explicitly specify that each value of the list variable should be constructed as: [campaign_name].[experience_name].[variation_name]
You can change this definition, for example:
- Choosing a different separator (e.g. in case some of your entity names contain dots)
- Choosing different entity values (e.g. you might want to utilize IDs instead of names to save space in your list variable (remember each value of the list has a maximum length of 250 characters)
For example, if we wanted to record entity ids, separated by semicolons, we would edit the function to:
var listItem = [tagId, experience.id, variationId].join(';');
If you choose to use IDs instead of entity names, we recommend using Adobe’s SAINT classification to map them to the respective entity names. Note though that at the moment Dynamic Yield cannot provide convenient and systematic access to the metadata relating to these entity IDs for use with Adobe’s classification importer. IDs and respective metadata however can be found, for each variation, in the global object’s event array, and can be manually classified in Adobe. More on classification in paragraph Analyzing Dynamic Yield Campaigns in Adobe Analytics, below.
To push to data layer information on recommended products (Optional)
For recommendation campaigns, we can also surface information about the utilized algorithm and the recommended products.
- Go to the Custom Analytics Platform integration and check on Recommendation Impressions.
- Replace the example code with the following and save.
function afterRcomResponse(strategy, fallback, widgetId, slots) { window.dyGlobalObject = window.dyGlobalObject || {}; window.dyGlobalObject.events = window.dyGlobalObject.events || []; window.dyGlobalObject.events.push({ 'event': 'recommendation_impression', 'strId': strategy.widgetId, 'strType': strategy.strategy, 'slots': strategy.slots, 'isFallback': strategy.fallback, 'eventTs': Math.round((new Date()).getTime() / 1000), }); }
-
After a few minutes, open the browser console on your website, where at least one Recommendation campaign is running, and type dyGlobalObject. You should see the events array contains a new event type: recommendation_impression
{ "events": [ { "event": "recommendation_impression", "eventTs": 1605468966, "isFallback": true, "slots": [ { "fallback": true, "item": { "categories": [ "Cats", "Toys" ], "description": "A Scratch-tastic product.", "dy_display_price": "0", "group_id": "119", "image_url": "http://cdn.dynamicyield.com/petshop/images/Group 119.png", "in_stock": true, "keywords": [ ], "name": "Cat Scratch Tower (Midi)", "price": 0, "publish_time": "2020-11-15T16:15:50", "sku": "119", "url": "/product/119" } } ], "strId": 89828, "strType": "TOP_N_RANDOM" } ] }
Note: in the following step of this guide we will only focus on the integration of variation impressions.
Step 3: Send a Call to Adobe Analytics
Once we have exposed the information we want to send to Adobe to the data layer object, we will send a call to Adobe Analytics. There are two options to do that:
- Via Dynamic Yield, once per page
- Custom, via your tag manager solution
Option | Calls Once Per Impression | Calls Once Per Page | On Existing Call |
---|---|---|---|
Via Dynamic Yield | - | Call made on page unload or equivalent via Dynamic Yield Custom Code as an additional s.tl() call. | - |
Custom (via Tag Manager) | Call made via tag manager on event type = impression | Call made via tag manager as additional s.tl() call. | Call made via tag manager together with existing. |
Option 1: Sending a Call Via Dynamic Yield Once per Page
We will use a Dynamic Yield Custom Code campaign to populate the list variable from the data layer and then trigger an Adobe Analytics s.tl() call.
- Go to Site Personalization › New Campaign and click Custom Code.
- Select to trigger the campaign on page load. Do not worry, we are only going to set an event listener on page load, the contained function will execute before unload for static sites, and on spa_start for single page applications.
- Important: since this is an auxiliary campaign and we do not want to track it in Adobe, disable the Execute custom integration and Serve On every SPA event options, and click next.
- Click on the Variation tab (leaving the Targeting tab empty, targeting all users)
- Click New Variation and select the Custom Code template.
- Go to Design and paste the following code in the JS tab. Note that in this code snippet we are explicitly populating list variable number 3. Replace 3 with your list variable identifier as defined in Adobe Analytics, then click Save Variation.
var variableName = 'list1';
var isSafari = DYO.userAgent.isSafari(navigator.userAgent);
if (!isSafari) {
window.addEventListener('beforeunload', sendDataToAdobeAnalytics);
DY.API('sub', {
on: 'spa_start',
callback: sendDataToAdobeAnalytics
});
}
function sendDataToAdobeAnalytics() {
var data = window.dyGlobalObject && window.dyGlobalObject.listVar;
if (!data) {
return;
}
var reportingSettings = {
linkTrackVars: variableName
};
reportingSettings[variableName] = data;
s.useBeacon = true;
s.tl(true, "o", "DY Campaigns", reportingSettings);
delete window.dyGlobalObject;
}
DY.CS = DY.CS || {};
DY.CS.reportToAdobe = (function() {
var TIMEOUT = 400;
var timeoutId = null;
function sendData() {
sendDataToAdobeAnalytics();
timeoutId = null;
}
function report() {
if (timeoutId !== null) {
clearTimeout(timeoutId);
timeoutId = null;
}
timeoutId = setTimeout(sendData, TIMEOUT);
}
return {
report: report
};
})(); - Select any goal as your primary metric, keeping in mind, you are not setting up an actual test, but just an auxiliary campaign to make the API call, so any goal will do.
- Make sure the allocation is set to send 100% of the traffic to your variation.
- Click Save Experience and Save & Publish the Campaign.
Option 2: Sending a call via your tag manager solution
This option leaves you the most flexibility to utilize the data layer object the way it best suits your implementation.
You can utilize the content of the dyGlobalObject’s listVar element as is, or build something analog working with the contents of each object in the events array.
You can also decide with which frequency and which way the call should be made: whether as a separate s.tl(), or together with the existing s.t() pageview.
Some setup examples:
Option | Setup | Pros | Cons |
---|---|---|---|
To trigger a call on every campaign impression | Populate your list variable and bind the call on dyGlobalObject.event.event_type = impression | Best accuracy | Cost of calls |
To bundle calls together as an additional s.tl() call | Use the content of dyGlobalObject.event.listVar or build your own analog solution, and trigger an s.tl() call when the page unloads. | Good compromise | Cost of additional s.t() call |
To bundle calls together on an existing call | Use the content of dyGlobalObject.event.listVar or build your own analog solution | No additional calls and costs | Inaccuracy due to race conditions, if campaigns are served after the call is made. |
Validating The Integration
If you opted for integrating via Dynamic Yield, or via tag manager using the list variable, you can validate the integration is working as expected using the Adobe Experience Cloud Debugger, making sure the list variable is correctly populated. Below an example:
Analyzing Dynamic Yield Campaigns in Adobe Analytics
Once the setup is complete, you should see that your list variable is being populated in Adobe Analytics. We can approach analysis in two ways:
Using the list variable as-is
Let’s assume we have a Recommendation Campaign with two experiences and two variations per experience.
In Adobe Analytics, we can create a new freeform table and drag the “DY Integration” dimension into the view, alongside with Visits, Unique Visitors or any conversion metrics.
In this example, since we have two experiences containing two variations each, we should see four rows. If the number of combinations is high we might want to split each combination in their respective hierarchy of Campaign › Experience › Variation, for more convenient analysis.
Using Classification to Create Separate Dimensions for Campaigns, Experiences, and Variations.
Additionally to using the list variable as-is, you can use classification to further split each list value, separating on our chosen separator character.
For example, if each value of the list variable is set up as:
[campaign_name].[experience_name].[variation_name]
We will be able to create three dimensions, by splitting on “.”:
- DY Campaign
- DY Experience
- DY Variation
To do so:
- Navigate to Admin › Classification Rule Builder
- Add a new rule of type Regular Expression
- Select your list variable as input
- Select a matching condition based on the separator. For example, if using “.”, the match criteria can be set to: ^(.*)\.(.*)\.(.*)
- Since we are splitting into three dimensions, make sure to classify the results by their ordinal position: DY Campaign = $1, DY Experience = $2, DY Variation = $3
Once our new dimensions are ready are built we can return to a workspace and utilize them:
Turning Off the Integration for a Specific Campaign
By default, the custom analytics platform integration is enabled for all campaigns. The integration can be turned off per campaign. This is done in the Advanced Settings of each campaign.
- When editing or creating a campaign, go to Advanced Settings.
- Turn off (or on) Enable custom integration.
DMPG is an independently-owned digital experience enablement agency, certified in Google and Adobe Martech platforms, providing strategy and delivery services covering customer data platforms, marketing automation, cross-channel personalization, conversion rate optimization, digital analytics, and tag management.