The availability of features may depend on your plan type. Contact your Customer Success Manager if you have any questions.

Dev GuideAPI Reference
Dev GuideAPI ReferenceUser GuideLegal TermsGitHubDev CommunityOptimizely AcademySubmit a ticketLog In
Dev Guide

Create custom integration for GA4 using GTM

Create a custom integration with Google Analytics 4 (GA4) to capture and analyze traffic data across your websites and applications.

📘

Note

See Optimizely's Third-Party Add-Ons & Platform Integration Terms.

🚧

Important

Starting July 1, 2023, GA4 will replace standard Google Universal Analytics (UA), which will no longer process data. For more information, see Introducing Google Analytics 4 (GA4).

📘

Note

Optimizely recommends using the built-in integration to integrate with GTM. See Integrate Google Analytics (GA4) for more details.

If you use Google Analytics to monitor your project’s traffic, you can view the results of your Optimizely Web Experimentation experiments alongside the rest of the data that Google Analytics collects.

You can set up the custom integration between Optimizely Web Experimentation or Optimizely Performance Edge and Google Analytics 4 (GA4) with Google Tag Manager (GTM).

To set up the custom GA4 integration without using GTM for Optimizely Web Experimentation, see this article. Optimizely does not support a custom GA4 integration for Optimziely Performance Edge without GTM.

Configure GA4 in Optimizely Web Experimentation

Step 1. Add script in GTM

In GTM, add the following script as a custom HTML tag using the steps below. This script should run on every page:

  1. Go to Workspace > Tags > New.
  1. Enter Optimizely integration code in the Untitled Variable field.
  1. Click Tag Configuration and select Custom HTML.
  1. Copy the appropriate Web or Performance Edge code below and paste it into the HTML field.

    📘

    Note

    If you want to send campaignData as well, you can add it to the sendCampaignData function in the script. This is also where you can adjust the dataLayer.push to any naming convention you prefer.

Optimizely Web Experimentation

<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 occurred 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 Optimizely Web Experimentation. This function is executed for all
  * experiments that are running on the page. Use the arguments to send data to your platform.
  *
  * @param {string} campaignId - The ID of a campaign that is running on the page
  * @param {string} integrationString - Integration string for a particular campaign
  * which is a sample of the visitor that is not exposed so that Optimizely Web Experimentation can calculate the impact of a campaign.
  */

  var sendCampaignData = function(campaignId, integrationString) {
    var dataLayerObject = window[DATALAYER_OBJECT_NAME] || [];
    dataLayerObject.push({
      'event': 'optimizely_decision_web',
      'optimizely_experiment': integrationString.experiment,
      'optimizely_variant': integrationString.variation
    });
  };

  /**
  * This function fetches the campaign integration string from the Optimizely Web Experimentation 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*
  * @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 campaignId = id;
      var integrationString = state.getDecisionObject({'campaignId':campaignId});
      sendCampaignData(campaignId, integrationString);
  };

  /**
  * 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 || [];
    try{
      window.optimizely.push({
        type: 'addListener',
        filter: {
          type: 'lifecycle',
          name: 'campaignDecided'
        },
        handler: function(event) {
          var id = event.data.campaign.id;
          newActiveCampaign(id);
        }
    });
    }catch(error){
      console.log('Something went wrong, this error can occur if there is a client side SDK. Which overwrites the optimizely object.');
    }
  };

  /**
  * If this code is running after Optimizely Web Experimentation 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'] && 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 the new Optimizely Web Experimentation 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} sendCampaignData - This function is called for every running campaign on the page.
  * The function is called with all the relevant ids and names.
  */
  var initOptimizelyIntegration = function(referrerOverride, sendCampaignData) {
    initNewOptimizelyIntegration(referrerOverride, sendCampaignData);
 };

  initOptimizelyIntegration(referrerOverride, sendCampaignData);
</script>

Optimizely Performance Edge

<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 occurred 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 Optimizely Performance Edge. This function is executed for all
  * experiments that are running on the page. Use the arguments to send data to your platform.
  *
  * @param {string} campaignId - The ID of a campaign that is running on the page
  * @param {string} integrationString - Integration string for a particular campaign
  * which is a sample of the visitor that isn't exposed so that Optimizely Performance Edge can calculate the impact of a campaign.
  */
  var sendCampaignData = function(campaignId, integrationString) {
    var dataLayerObject = window[DATALAYER_OBJECT_NAME] || [];
    dataLayerObject.push({
      'event': 'optimizely_decision_web',
       'optimizely_experiment': integrationString.name,
       'optimizely_variant': integrationString.variation.name
    });
  };

  /**
  * This function fetches the campaign integration string from the Optimizely Performance Edge 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['optimizelyEdge'].get && window['optimizelyEdge'].get('state');
      var referrer = state.getRedirectInfo() && state.getRedirectInfo().referrer;
      if (!referrerOverwritten && referrer) {
        referrerOverride(referrer);
        referrerOverwritten = true;
      }
      var activateCampaigns = state.getActiveExperiments();
      var integrationString = activateCampaigns[id];
      sendCampaignData(activateCampaigns, integrationString);
   };

/**
* 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.optimizelyEdge = window.optimizelyEdge || [];
try{
window.optimizelyEdge.push({
type: 'addListener',
filter: {
type: 'lifecycle',
name: 'campaignDecided'
},
handler: function(event) {
var id = event.data.campaign.id;
newActiveCampaign(id);
}
});
}catch(error){
console.log('Something went wrong, this error can occur if there is a client side SDK. Which overwrites the optimizely object.');
}
};

/**
* If this code is running after Optimizely Performance Edge 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['optimizelyEdge'] && window['optimizelyEdge'].get && window['optimizelyEdge'].get('state');
if (state) {
var activeCampaigns = state.getActiveExperiments();
for (var id in activeCampaigns) {
newActiveCampaign(id);
}
}
};
registerCurrentlyActiveCampaigns();
registerFutureActiveCampaigns();
};
  /**
  * A wrapper around the logic for the new Optimizely Performance Edge 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} sendCampaignData - This function is called for every running campaign on the page.
  * The function is called with all the relevant ids and names.
  */
  var initOptimizelyIntegration = function(referrerOverride, sendCampaignData) {
    initNewOptimizelyIntegration(referrerOverride, sendCampaignData);
  };
  initOptimizelyIntegration(referrerOverride, sendCampaignData);
</script>
  1. Click Triggering and select All Pages.

📘

Note

If your site activates Optimizely Web Experimentation before consent, you need to:

  • Set a trigger in GTM for this tag when cookie acceptance is complete
  • Run this tag after the Google Analytics: GA4 Configuration and Optimizely X - GA4 event tags (step 3 and step 4 below)
  1. Click Save.

Step 2. Add User-Defined Variables in GTM

📘

Note

If you are using GA4 Event Tracking or Report Generation, the process below is the same, but you need to add different variables. See Integrate Google Analytics 4 for the variables.

Complete the following steps to add the optimizely_experiment and optimizely_variant variables:

  1. Go to Workspace > Variables > New.
  1. Enter optimizely_experiment in the Untitled Variable field.
  1. Click Variable Configuration and select Data Layer Variable.
  1. In the Data Layer Variable Name field, enter optimizely_experiment.
  1. Click Save.
  2. Repeat step 1 through step 6 for the optimizely_variant variable.

Step 3. Set up the configuration tag in GTM

Complete the following steps to set up a Google Analytics GA4 Configuration tag:

  1. Go to Workspace > Tags > New.
  1. Enter Google Analytics GA4 Configuration in the Untitled Tag field.
  1. Click Tag Configuration and select Google Analytics: GA4 Configuration.
  1. Enter your Measurement ID.
  1. Click Triggering and select Initialization - All Pages.
  1. Click Save.

Step 4. Set up the event tag in GTM

In GTM, complete the following steps to set up an Optimizely X - GA4 event tag:

  1. Go to Workspace > Tags > New.
  1. Enter Optimizely X - GA4 event in the Untitled Tag field.
  1. Click Tag Configuration and select Google Analytics: GA4 Event.
  1. Expand the Configuration Tag drop-down list and select Google Analytics GA4 Configuration.
  1. In the Event Name field, enter optimizely_decision_web.
  1. Expand Event Parameters and then click Add Row.
  2. In the Parameter Name field, enter optimizely_experiment.
  1. In the Value field, click the value select icon and then select optimizely_experiment.
  2. Click Add Row again.
  3. In the Parameter Name field, enter optimizely_variant.
  1. In the Value field, click the value select icon and then select optimizely_variant.
  2. Click Triggering and then click the New Trigger icon to create the following trigger:
    1. Enter Optimizely X - GA4 event trigger in the Untitled Trigger field.

ii. Click Trigger Configuration and select Custom Event.

iii. In the Event name field, enter optimizely_decision_web.

iv. Click Save and then click Save again on the overall tag setup page.

  1. Now submit and publish your workspace changes by going to Workspace >  Submit > Publish (adding any details you would like to the Submission Configuration).

Now your Optimizely Web Experimentation or Optimizely Performance Edge data immediately starts syncing to GA4 (no further steps required).