The integration options in this article have been created and validated in collaboration with DMPG, an Adobe Analytics and Adobe Target specialized partner. The integration works only with Dynamic Yield script implementations.
Our custom analytics integration enables 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 third-party Analytics platform is to record information about which Dynamic Yield Experiences visitors were exposed to (including campaigns, variations, and product recommendations).
There are three moving parts to the integration:
- A live Dynamic Yield campaign, with the Execute Custom Integrations toggle turned on. This enables the campaign to expose its metadata (say, campaign, experience, and variation names) whenever it's 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'll 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 the Dynamic Yield 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 through Dynamic Yield or your tag manager solution.
Step 1: Configure a list variable in Adobe Analytics
Adobe Analytics list variables enable you to use a single delimiter-separated string to store multiple values, which can then be split and analyzed independently. Each value represents a different campaign, experience, and variation combination.
To set up a list variable, navigate to its configuration page following this Adobe documentation, and configure one of your variables as follows:
- Name: Dynamic Yield
-
Expiration: This is the equivalent of the Dynamic Yield Attribution Window. If Attribution IQ is part of your Adobe package, you can edit expiration on demand when analyzing your results. If you don’t, you'll 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: To replicate this in Adobe Analytics, you'll need to 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 to | (pipe). Changing it to a different delimiter requires adjustments to the script in step 2 of the integration.
- Allocation: Set to Full to mimic Dynamic Yield attribution logic, so that each individual test receives full conversion credit.
- Max Values: 250
Step 2: Set up a global data layer object
When Adobe Analytics is ready to receive data from Dynamic Yield, we'll create a data layer object, using the Dynamic Yield Custom Analytics integration.
The data layer object is called dyGlobalObject, and contains 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'll 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 on the page. With each new impression event, the relevant information is appended to the existing value. The Adobe list variable can be populated directly with this value.
- uniqueImp: An array used to create the listVar field.
The dyGlobalObject’s events array can be populated by different events, each carrying specific information you might want to record in Adobe:
- Variation impression: This event will execute the function every time a test or campaign variation is served to a visitor on your site.
- Recommendation impression: This event will execute the function every time a set of items is rendered on the page. It carries information about the algorithm and the recommended items.
To push information on variation impressions to the data layer:
If you already have the Analytics Platform Integration extension installed, go to Web Personalization › Extensions and start at step 3.
- Go to Experience OS App Store › Analytics Platform Integration and click Install.
- Click Configure extension.
- Activate the extension, and then click Edit.
- Select Variation Impressions, replace the sample 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 || []; const timestamp = Math.round((new Date()).getTime() / 1000); let expName = decodeURI(experience.name); const 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 }); const 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 running campaign, and the listVar element is populated with the pipe-concatenated list [campaign_name].[experience_name].[variation_name], like the following example:
{
"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 this line in the previous integration function code:
const listItem = [tagName, expName, variationName].join('.');
It is explicit 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 (say, if some of your entity names contain dots)
- Choosing different entity values (say, if you want to use 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 you want to record entity IDs, separated by semicolons, edit the function to:
const listItem = [tagName, expName, variationName].join(';');
If you decide to use IDs instead of entity names, we recommend using the Adobe SAINT classification to map them to their respective entity names. Note that at the moment, Dynamic Yield cannot provide convenient and systematic access to the metadata relating to these entity IDs for use with the Adobe classification importer. However, IDs and respective metadata can be found, for each variation, in the global object’s event array, and can be manually classified in Adobe. Learn more about classification in this article section Analyzing Dynamic Yield Campaigns in Adobe Analytics.
To push to data layer information on recommended products (optional):
For recommendation campaigns, you 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(response) {
window.dyGlobalObject = window.dyGlobalObject || {};
window.dyGlobalObject.events = window.dyGlobalObject.events || [];
window.dyGlobalObject.events.push({
'event': 'recommendation_impression',
'strId': response.widgetId,
'strType': response.strategy,
'slots': response.slots,
'isFallback': response.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: The next step of this guide focused only on the integration of variation impressions.
Step 3: Send a call to Adobe Analytics
After you expose the information, send a call to Adobe Analytics in one of the following ways:
Option | Calls once per impression | Calls once per page | On existing call |
---|---|---|---|
Call via Dynamic Yield | - | Upon page unload or equivalent via Dynamic Yield Custom Code as an additional s.tl() call | - |
Custom call, via tag manager | Upon event type = impression | Via tag manager as additional s.tl() call | Via tag manager together with existing |
Option 1: Send a call via Dynamic Yield, once per page
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 Web Personalization › New Campaign and click Custom Code.
- Select to trigger the campaign upon page load. This just sets an event listener on page load; the contained function executes before unload for static sites, and upon spa_start for single-page applications.
-
Important: Because this is an auxiliary campaign, and you don't want to track it in Adobe, disable the Track campaign performance in your analytics platform and Serve On every SPA event options, and then click next.
- Click the Variations 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 you're explicitly populating list variable number 3. Replace 3 with your list variable identifier as defined in Adobe Analytics, then click Save Variation.
const variableName = 'list3'; const INTERVAL = 5000; const dyAdobeTimeCookie = DYO.StorageUtils.get('dy-adobe', ['sessionStorage']); let newPosition = 0; let dyAdobeInterval; // For disabling interval logic, put a zero (0) DY.CS = DY.CS || {}; const adobeSender = () => { const currentTime = new Date().getTime(); const newTime = new Date(currentTime + INTERVAL).getTime(); window.addEventListener('beforeunload', sendDataToAdobeAnalytics); document.addEventListener('mouseout', (evt) => { if (evt.toElement === null && evt.relatedTarget === null) { sendDataToAdobeAnalytics(); } }); document.addEventListener("scroll", scrollSpeed); if (dyAdobeInterval !== 0) { dyAdobeInterval = setInterval(() => { if (dyAdobeTimeCookie === null) { DYO.StorageUtils.set('dy-adobe', newTime, ['sessionStorage']); sendDataToAdobeAnalytics(); } else { if (currentTime > dyAdobeTimeCookie) { sendDataToAdobeAnalytics(); DYO.StorageUtils.set('dy-adobe', newTime, ['sessionStorage']); } } }, INTERVAL); } } function scrollSpeed() { let lastPosition = window.scrollY; setTimeout(() => { newPosition = window.scrollY; }, 100); currentSpeed = newPosition - lastPosition; if (currentSpeed > 220) { sendDataToAdobeAnalytics(); } } function sendDataToAdobeAnalytics() { const data = window.dyGlobalObject && window.dyGlobalObject.listVar; if (!data) { return; } const reportingSettings = { linkTrackVars: variableName }; reportingSettings[variableName] = data; s.useBeacon = true; s.tl(true, "o", "Dynamic Yield", reportingSettings); delete window.dyGlobalObject; } DY.CS.reportToAdobe = (function() { const TIMEOUT = 400; let timeoutId = null; function sendData() { sendDataToAdobeAnalytics(); timeoutId = null; } function report() { if (timeoutId !== null) { clearTimeout(timeoutId); timeoutId = null; } timeoutId = setTimeout(sendData, TIMEOUT); } return { report: report }; })(); adobeSender();
- Select any goal as your primary metric, keeping in mind that you're 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 to integrate via Dynamic Yield, or via tag manager using the list variable, you can validate that the integration is working as expected using the Adobe Experience Cloud Debugger, making sure the list variable is correctly populated. For example:
Analyzing Dynamic Yield campaigns in Adobe Analytics
Once the setup is complete, you should see that your list variable is populated in Adobe Analytics. You can approach analysis using the list variable as-is, or using classification to further split each list value.
Using the list variable as-is
Say that you have a Recommendations campaign with two experiences and two variations per experience.
In Adobe Analytics, you can create a new freeform table and drag the DY Integration dimension into the view, alongside visits, unique visitors or any other conversion metric.
In this example, because the two experiences include two variations each, you should see four rows. If the number of combinations is high, you might want to split each combination into its respective hierarchy of campaign › experience › variation for more convenient analysis.
Using classification to create separate dimensions for campaigns, experiences, and variations
In addition to using the list variable as-is, you can use classification to further split each list value, separating on your chosen separator character.
For example, if each value of the list variable is set up as:
[campaign_name].[experience_name].[variation_name]
You can create three dimensions, by splitting at the period (.), like this:
- 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 a period (.), the match criteria can be set to: ^(.*)\.(.*)\.(.*)
- Because you're splitting into three dimensions, make sure to classify the results by their ordinal position: DY Campaign = $1, DY Experience = $2, DY Variation = $3
When the new dimensions are ready, return to a workspace and use them:
Turning off the integration for a specific campaign
By default, the custom analytics platform integration is enabled for all campaigns. However, 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) Execute custom integrations.
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.