This article will help you:
  • Get set up within Google Tag Manager to integrate Optimizely X and Google Universal Analytics
  • Confirm that your integration is working properly

If you’re an existing Google Tag Manager user, you may already have pre-configured Universal Analytics tags that fire off pageview calls and do not want to use a regular custom HTML tag. You can integrate Google UA with Optimizely X with this one-time setup process.

In this article, we walk you through setting up the integration and confirming your setup.

Download a checklist to help you manage this procedure.

When to use this procedure

The most common reasons you might need to follow these steps are:

  • If you are working with redirect experiments, or

  • If you are using a dynamic tracker.

Looking for a different Google Analytics integration? See our Standard Google Analytics integration article or set up a Custom Analytics integration.

Before you start

You will need to create a Google UA custom dimension and a custom report.

One-time setup to integrate via Google Tag Manager

Here's how to use GTM to integrate Optimizely X and Google UA:

  1. In Google Tag Manager, navigate to Workspace > Variables.

  2. Create a new User-Defined Variable calledoptimizely-dimension-number.

    In the Type field, choose Data Layer Variable type optimizely-dimension-number.

    Then, in the Data Layer Version field, choose Version 2. 

  3. Create a new User-Defined Variable named optimizely-dimension-value

    • In the Type field, choose Data Layer Variable.

    • In the Data Layer Variable Name field, type optimizely-dimension-value

    • In the Data Layer Version field, choose Version 2.

  4. Create a new User-Defined Variable named optimizely-referrer .

    • In the Type field, choose Data Layer Variable.

    • In the Data Layer Variable Name field, type optimizely-referrer.

    • In the Data Layer Version field, choose Version 2.

  5. Navigate to Workplace > Triggers.

  6. Create a new Custom Event named "Optimizely campaign decided."

    • In the Event name field, type “campaign-decided.”

  7. Create a new Custom Event named "Optimizely referrer override."

    • In the Event name field, type “optimizely-referrer-override.”

  8. Navigate to Workplace > Tags.

  9. Create a new Custom HTML Tag named "Optimizely Integration Code."

  10. Create a new Google Universal Analytics Tag named "Optimizely Campaign decided" to track event in UA.

    • In the Tag Type field, choose Universal Analytics.

    • In the Track Type field, enter Event.

    • In the Category field, enter Optimizely.

    • In the Action field, enter Assigned to Campaign.

    • Leave the Label and Value fields blank. These are not required fields according to Google Analytic's event tracking documentation .

    • Set Non-Interaction Hit to True.

    • Under Google Analytics Settings, select the Google Analytics variable that you want to integrate Optimizely with.

    • Check the Enable overriding settings in this tag Option.

    • Click on More Settings.

    • Click on Custom Dimensions.

    • Under Custom Dimensions:

      Set Index to {{optimizely-dimension-number}}
       
      Set Value to {{optimizely-dimension-value}}
    • In the Triggering field, choose the "Optimizely campaign decided" custom event.

    • Here how the tag should appear. Please note, the name under Google Analytics Setting will be different than the one on the screenshot because the name is user defined.gtm-campaign decided.jpg

  11. Create a new Google Universal Analytics Tag named "Optimizely Referrer override" to track event in UA. Please note that this field is only for redirects.

    • In the Tag Type field, choose Universal Analytics.

    • In the Track Type field, choose Event.

    • In the Category field, enter Optimizely.

    • In the Action field, enter Redirect Referrer Override.

    • Leave the Label and Value fields blank because they are not required.

    • Under Google Analytics Settings, select the Google Analytics variable that you want to integrate Optimizely with.

    • Check the Enable overriding settings in this tag Option.

    • Set Non-Interaction Hit to True.

    • Under Fields to Set:

      Set Field Name to referrer
       
      Set Value to {{optimizely-referrer}}
    • In the Triggering field, choose the "Optimizely Referrer Override" custom event.

    • Here is how your tag should appear:
      gtm-referrer override.jpg

Tag configuration

Copy this code exactly as-is into the custom HTML section described here. (The easiest way to copy the sample is to click View source on the top right-hand corner of the code box below.)

In order for the following code to work, Optimizely object needs to be available by the time it runs - make sure to load the Optimizely snippet before the tag with the below code.

<script>
var DATALAYER_OBJECT_NAME = 'dataLayer';

/**
* Some analytics platforms have the ability to fix referrer values by overriding the page referrer value.
* this function is called when a redirect has occured on the previous page.
*
* @param {string} referrer - The effective referrer value
*/
var referrerOverride = function(referrer) {
    var dataLayerObject = window[DATALAYER_OBJECT_NAME] || [];
    dataLayerObject.push({
      'event': 'optimizely-referrer-override',
      'optimizely-referrer': referrer
    });
};

/**
* Used for experiments created in 'new Optimizely'. This function is executed for all
* experiments that are running on the page. Use the arguments to send data to your platform.
*
* @param {string} campaignName - The name of a campaign that is running on the page
* @param {string} campaignId - The ID of a campaign that is running on the page
* @param {string} audienceNames - The names of all the audience the visitor is considered part of related to this campaign
* @param {string} audienceIds - The names of all the ids the visitor is considered part of related to this campaign
* @param {string} variationName - The name of the experiment the user is seeing. Frequently, a name is only available for the campaign
* @param {string} variationId - The ID if the experiment the user is seeing
* @param {string} variationName - The name of the variation the user is seeing
* @param {string} variationId - The ID if the variation the user is seeing
* @param {boolean} inHoldback - If true, the visitor has not been exposed to this variation, but is kept in a holdback
*   which is a sample of the visitor that isn't exposed so that Optimizely can calculate the impact of a campaign.
*/
var sendCampaignData = function(
  campaignName,
  campaignId,
  audienceNames,
  audienceIds,
  experimentName,
  experimentId,
  variationName,
  variationId,
  inHoldback
) {
  var dimension = optimizely.get('data') && optimizely.get('data').campaigns[campaignId] && optimizely.get('data').campaigns[campaignId].integrationSettings && optimizely.get('data').campaigns[campaignId].integrationSettings.google_universal_analytics && optimizely.get('data').campaigns[campaignId].integrationSettings.google_universal_analytics.universal_analytics_slot;
  
  
  if (dimension) {
    var campaign = campaignName ? campaignName + '(' + campaignId + ')' : campaignId;
    var audience = audienceNames.join(',');
    var experiment = experimentName ? experimentName + '(' + experimentId + ')' : audience + '(' + experimentId + ')' ;
    var variation = variationName ? variationName + '(' + variationId + ')' : variationId;
    var holdback = inHoldback ? 'holdback' : 'treatment';
    var customVariableValue = [campaign, experiment, variation, holdback].join(':');
    var dataLayerObject = window[DATALAYER_OBJECT_NAME] || [];
    dataLayerObject.push({
      'event': 'campaign-decided',
      'optimizely-dimension-value': customVariableValue,
      'optimizely-dimension-number': dimension
    });
  }
};

/**
* This function fetches all the campaign data from the new Optimizely client
* and calls the functions provided in the arguments with the data that needs to
* be used for sending information. It is recommended to leave this function as is
* and to create your own implementation of the functions referrerOverride and
* sendCampaignData.
*
* @param {Function} referrerOverride - This function is called if the effective referrer value differs from
*   the current document.referrer value. The only argument provided is the effective referrer value.
* @param {Function} sendCampaignData - This function is called for every running campaign on the page.
*   The function is called with all the relevant ids and names.
*/
var initNewOptimizelyIntegration = function(referrerOverride, sendCampaignData) {
  // There can only be one effective referrer on a page. This boolean makes sure the
  // redirect overwrite only happens once. Multiple referrerOverwrites might result in undesired behavior.
  var referrerOverwritten = false;
  var newActiveCampaign = function(id) {
    var state = window['optimizely'].get && window['optimizely'].get('state');
    var referrer = state.getRedirectInfo() && state.getRedirectInfo().referrer;
    if (!referrerOverwritten && referrer) {
      referrerOverride(referrer);
      referrerOverwritten = true;
    }
    var activeCampaigns = state.getCampaignStates({
      isActive: true
    });
    var campaignState = activeCampaigns[id];
    var campaignName = campaignState.campaignName;
    var campaignId = id;
    var audienceNames, audienceIds;
    if (campaignState.audiences.length > 0) {
      audienceNames = campaignState.audiences.map(function(audience) {
        return audience.name
      });
      audienceIds = campaignState.audiences.map(function(audience) {
        return audience.id
      });
    } else {
      audienceNames = ['everyone_else'];
      audienceIds = [0];
    }
    var experimentName = campaignState.experiment.name;
    var experimentId = campaignState.experiment.id;
    var variationName = campaignState.variation.name;
    var variationId = campaignState.variation.id;
    sendCampaignData(
      campaignName,
      campaignId,
      audienceNames,
      audienceIds,
      experimentName,
      experimentId,
      variationName,
      variationId,
      campaignState.isInCampaignHoldback
    );
  };
  
  /**
   * At any moment, a new campaign can be activated (manual or conditional activation).
   * This function registers a listener that listens to newly activated campaigns and
   * handles them.
   */
  var registerFutureActiveCampaigns = function() {
    window.optimizely = window.optimizely || [];
    window.optimizely.push({
      type: 'addListener',
      filter: {
        type: 'lifecycle',
        name: 'campaignDecided'
      },
      handler: function(event) {
        var id = event.data.campaign.id;
        newActiveCampaign(id);
      }
    });
  };
  
  /**
   * If this code is running after Optimizely on the page, there might already be
   * some campaigns active. This function makes sure all those campaigns are
   * handled.
   */
  var registerCurrentlyActiveCampaigns = function(){
    var state = window['optimizely'].get && window['optimizely'].get('state');
    if (state) {
      var activeCampaigns = state.getCampaignStates({
        isActive: true
      });
      for (var id in activeCampaigns) {
        newActiveCampaign(id);
      }
    }
  };
  
  registerCurrentlyActiveCampaigns();
  registerFutureActiveCampaigns();
};

/**
* A wrapper around the logic for both the classic and new Optimizely integration.
* @param {Function} referrerOverride - This function is called if the effective referrer value differs from
*   the current document.referrer value. The only argument provided is the effective referrer value.
* @param {Function} sendExperimentData - This function is called for every running experiment on the page.
*   The function is called with all the relevant ids and names. Used for classic Optimizely.
* @param {Function} sendCampaignData - This function is called for every running campaign on the page.
*   The function is called with all the relevant ids and names. Used for new Optimizely.
*/
var initOptimizelyIntegration = function(referrerOverride, sendCampaignData) {
  initNewOptimizelyIntegration(referrerOverride, sendCampaignData);
}

initOptimizelyIntegration(referrerOverride, sendCampaignData);

</script>

Confirm your integration setup

After completing your integration, here’s how to check that it works properly:

  1. Create a new campaign/experiment to integrate with Google UA.

  2. Turn on UA integration for the campaign/experiment.

  3. Set the custom dimension where Optimizely should send data.

  4. Run the campaign/experiment.

  5. Open the Network panel in your browser.

  6. Navigate to the page where the campaign/experiment is running.

  7. Filter for “collect” to only show UA requests.

  8. Look in the Headers section of each request for the cd{X} value.

If the integration works properly, you’ll see this output in the Headers section for each request with the cd{X} value ({X} is the dimension number you set in step 3):

campaign_name:experience_name:variation_name:holdback

Each section is delimited by a colon: