This article is about Optimizely Classic. If you're using Optimizely X, check this article out instead.
relevant products:
  • Optimizely Classic

This article will help you:
  • Implement Optimizely if you have pre-existing Universal Analytics tags
  • Preserve referral sources during redirects

If you’re an existing Google Tag Manager user, you may already have pre-configured Universal Analytics tags that fire off pageview calls.

Here’s how they look in Google Tag Manager:

If this is the case, it’s not ideal to create the custom HTML tag just to add the Optimizely integration, especially when you are using multiple advanced settings in the tags. Having the custom HTML tag fire in conjunction with these existing template tags could skew results due to Universal Analytics making multiple pageview calls.

In this case, it makes more sense to update your existing tags so that you can still filter your results with Optimizely segments.

If you don't have an existing implementation of Google Tag Manager (GTM) and you want to use GTM to implement Optimizely, check this article instead.

Use Google Tag Manager's custom JavaScript macro

As with all asynchronously loaded experiments (for example, conditional activation, geo-targeting, and anytime the timing of when the experiment is defined on the page may be affected), this solution must be adjusted to account for the timing issues these sort of experiments present. 

If it’s a geo-targeted experiment, you can wait to fire the macro until // is present on the page.

If it’s list, DCP, or third-party audience, you can wait for[project_id].

You can continue to pass Optimizely experiment information to Google Analytics with a custom JavaScript macro within Google Tag Manager. This involves some set-up within all three applications: Google Analytics, Optimizely, and Google Tag Manager.

  1. In Google Analytics, create a Universal Analytics custom dimension that will receive Optimizely experiment information. This custom dimension and the index you give it will be used to create reports that leverage your Optimizely integration data for filtering. In this example, we’re using an index of 3 for the custom dimension.

  2. In the Optimizely Visual Editor, select Options > Integrations.

  3. Configure your Optimizely experiment to pass its information to the corresponding custom dimension you created in Google Analytics (in this example, 3). 

  4. In Google Tag Manager, under Container > Variables, create a new user-defined variable.

  5. Select the type Custom JavaScript Variable.

  6. Enter a variable name that corresponds to the custom dimension you created in Google Analytics. In this example, we’re using “Optimizely Variable Slot 3,” but in your own integrations, you can replace this according to whichever index you select in Google Analytics.

  7. Add the code listed below the screenshot in the Custom JavaScript field under Configure Variable and click Save Variable.

    function () {
          var o = window.optimizely,
              aE = o.activeExperiments,
              v =,
              gaKey = "",
              gaValue = "",
              rD =;
          for(var i = 0; i < aE.length; i++) {
             var e = aE[i],
             vId = o.variationIdsMap[e],
             vIndex = o.variationMap[e],
             isMvt = vId.length > 1,
             eName =[e].name;
             gaKey = (isMvt ? "MVT" : "AB") + " Test: " + eName + "";
             if (!isMvt) {
                 gaValue = (vIndex === 0 ? "Control" : "V") + vIndex + ": " + o.variationNamesMap[e];
             } else {
                 var s =,
                     sId =[e].section_ids;
                 for (i = 0; i < sId.length; i++) {
                    if(i == 0) {
                      gaValue = s[sId[i]].name.toString() + ': ' + v[vId[i]].name;
                    } else {
                      gaValue += ', ' + s[sId[i]].name.toString() + ': ' + v[vId[i]].name;
             if (gaKey.length !== 0 && gaValue.length !== 0 && o.allExperiments[e].universal_analytics && o.allExperiments[e].universal_analytics.slot == 3) {
               return gaKey+": "+gaValue;
         if (rD !== undefined) {
             var rDe = rD.experimentId,
                 rvId = o.variationIdsMap[rDe],
                 rVIndex = o.variationMap[rDe],
                 rIsMvt = rvId.length > 1,
                 rEName =[rDe].name,
                 rGaKey = "",
                 rGaValue = "";
             rGaKey = (rIsMvt ? "MVT Redirect" : "AB Redirect") + " Test: " + rEName + "";
             if (!rIsMvt) {
                 rGaValue = (rVIndex === 0 ? "Control" : "V") + rVIndex + " Redirect: " + o.variationNamesMap[rDe];
             } else {
                 var sR =,
                     sIdR =[rDe].section_ids;
                for(i = 0; i < sIdR.length; i++) {
                     rGaValueArray = sR[sIdR[i]].name.toString() + "Redirect: " + v[rvId[i]].name;
             if (rGaKey.length !== 0 && rGaValue.length !== 0 && o.allExperiments[rDe].universal_analytics && o.allExperiments[rDe].universal_analytics.slot == 3) {
               return rGaKey+": "+rGaValue;
  8. Modify the sample JavaScript code to match the custom dimension index you’re using. This code will return the experiment name and variation name key/value pair within Google Tag Manager.

  9. Within an existing pageview tag in Google Tag Manager, navigate to More Settings > Custom Dimensions.

  10. Specify the custom dimension index that you want to use for your Optimizely experiment (in our example, the index is 3).

  11. In the Dimension Value field, choose Optimizely Variable Slot 3.

    Google Tag Manager Custom Javascript Variable

  12. Under Configure Tag > More Settings > Advanced Configuration, check the Tracker name box and leave the Tracker Name field blank.

    Note: If you're specifying a tracker name, make sure the name in the field matches.
  13. In the custom report within Google Analytics for index 3, don’t filter by anything specific; use a wildcard RegEx (regular expression) match .*.


This article assumes that you already installed Optimizely natively in the <head> tag and it’s firing synchronously.

We chose index 3 for this example. If you want to use a different Universal Analytics index, you’ll need to change the naming and change the index number within the "if" logic of the code, as well as your custom dimension and report definitions.

Preserve referral sources during redirects

When a redirect takes place in Optimizely with the Universal Analytics integration enabled, we grab the document.referrer value and call the ga('set','referrer'); function to maintain the original referrer. This works well on landing pages, but if there is a redirect on any page deeper into your site, it strips the visitor's original session referrer and sets the referrer as the immediately preceding page. This inflates the referral traffic source in your Universal Analytics and AdWords reports.

To preserve the referral source, implement this code linked on Github so that it runs on every page load above the Optimizely snippet or in Project JavaScript. You may also implement this code in a tag manager or natively on your site, as long as it runs before the Optimizely snippet.

On the initial landing page, the code will grab the session's initial referrer and set it to a cookie. This cookie persists throughout the visitor’s navigation on your site. When the visitor is redirected on a non-landing page as part of an Optimizely experiment, the code will determine if the existing session's referrer should be preserved or updated to document.referrer. The code sends the appropriate referrer to Universal Analytics, and the original traffic source is persistent.

The scope variable controls how long you want Optimizely to preserve the session's original referrer, so it is important to set this code on every page. For example, if you want to set the scope to session but only run this code on the page where the redirect occurs, code on a later page could overwrite the referrer. The Optimizely code would need to be called again to correct it, because the logic ensures the same referrer from the beginning of the session is resent to GA every time the code runs. In the page-scoped scenario, this code will re-determine the referrer on every page, and will not remember it from the beginning of the session.

Make sure to follow the implementation instructions at the top of the code. The code must be run on each pre- and post-redirect page, and all other pages where you want Optimizely to set the referrer.