Skip to main content


Optimizely Knowledge Base

Audience activation and troubleshooting

  • Troubleshoot audience conditions
  • Access the visitor object
  • How audiences activate differently
  • Understand how an audience assignment can change through a visitor's session or experience

There are several different ways to build an audience condition in Optimizely, as well as different approaches necessary for evaluating and troubleshooting each one.  

Some visitor attributes may change over time. For many of these—like cookies, custom attributes, and custom JavaScript—Optimizely uses the freshest possible information to decide if a visitor qualifies for an experiment. However, when an attribute relies on network calls (for example, geo-targeting or third-party integration), that information may take longer to arrive. This article walks through the different types of audience conditions, explains when they are available, and details how to troubleshoot them. 

Static audience conditions 

Audience conditions that are not expected to change are evaluated at the beginning of the visitor's session. Once this happens, Optimizely does not request the value again for the entire session; instead, it's held in local storage and referenced as needed. This section describes several examples of these "sticky" audience conditions. 

Device Type

The device type condition uses last-touch attribution for a visitor session, meaning Optimizely will look at the visitor's user agent to determine the user's device type and store that value in local storage. 

Most visitors won't change the device they're using during a session. However, when working to QA your experiments, checking different device types is common. 

In this scenario, if a user is emulating a mobile device in their browser and gets bucketed into an experiment, and then switches out of that emulated view back to the desktop, Optimizely will still identify that users as being on a mobile device.  To check, look at the visitor object optimizely.get('visitor').device: the value returned is the device Optimizely associates with the visitor. 

To change the device, either clear cookies and local storage, or use a new incognito window. 


Optimizely evaluates the referrer value as soon as the visitor first touches the snippet, potentially before an experiment even begins. This value is sticky and will not be revaluated until the visitor starts a new session. A visitor can have a different referring values for different sessions. 

  • This value is not the same as document.referrer.   Optimizely's referrer is the last URL a visitor saw on a domain that did not have the current snippet on it.  

  •  To use document.referrer as an audience condition, use the custom JavaScript audience condition to set your own logic.

Traffic source

Like referrertraffic source is evaluated as soon as the visitor begins their session. This value is sticky and will not be revaluated until the visitor starts a new session. A visitor can have a different traffic source values for different sessions.


This is a special query parameter that is stored in the visitor object optimizely.get('visitor').campaign . Optimizely will reference the stored value as the visitor navigates around the site, and will persist the audience condition even if the query parameter is gone.  The campaign query parameter will only last for the session in which it was set. 

Custom attributes

Custom attributes are values stored on the visitor's browser using custom code. They will not change unless custom code is written to overwrite the value. A custom attribute will remain on the visitor's browser until the visitor clears local storage.

Custom attributes are generally not available on the first page load of the page where Optimizely assigns the value to the visitor.

Dynamic audience conditions

Dynamic audience conditions are expected to change as the visitor navigates around the site. Optimizely evaluates them each time an experiment activates. This means a visitor can pass and fail the same audience condition in the same session. 

Query parameters

The query parameter is evaluated immediately on pageload. Unlike campaign parameters (which are stored in the visitor object), query parameters only persist through pageloads that include the query within in the URL. 

If an experiment requires modification of the query parameters to match an audience condition, this change must occur before Optimizely executes, or the page must be refreshed.

  • If the customer assigns to, some browsers do a full page reload using the just-assigned query parameters. Since the client reactive on this reload, query parameters are guaranteed fresh. 

  • Another way of changing query parameters is using the browser’s window.history.pushState/replaceState API to change the URL, but this will not trigger a page reload.  A manual reactivation of the client is required to apply to audience targeting conditions.

Custom JavaScript audience conditions

Custom JavaScript evaluates to true or false, and will be evaluated every time the experiment activates. When using it, make sure that any values the custom JavaScript relies on are defined before Optimizely begins evaluating. Audience conditions are evaluated very early in the snippet; if the values are not available in time, the visitor will not be bucketed for the experiment as intended. 

  • If a required value isn't available until after the snippet executes, you could use conditional activation to delay experiment activation until the variable is available. However, this approach can cause flashing.

  • To minimize flashing, consider also using a cookie audience to persist the audience condition.

If a visitor changes an audience condition, that change only applies to events triggered for experiments that activate after the change is made.  

Network-sourced attributes

Attributes like Dynamic Customer Profiles (DCP), List Attributes, IP Address, and Location all involve sending network requests. This involves a tradeoff: 

  • Optimizely can use potentially stale data to make an immediate decision about which experience the visitor will have, or

  • Optimizely can defer that decision to ensure it's made with fresh data, but risk prolonged flashing in the process.

In either case, the snippet still sends a request to refresh the data, so subsequent snippet activations are likely to have valid cached data to work with.

With these targeting conditions, Optimizely sends requests to fetch the latest data from these services whenever the snippet activates. The responses to those requests may not arrive by the time the snippet decides on a visitor's experience. But even if that does happen, it isn't always a problem: previous snippet activations may have left values for list attributes, IP address, and location cached in localStorage. The persisted values are refreshed when Optimizely receives the responses to the snippet's original requests. If your experiment's activation mode is anything other than immediate, Optimizely will almost certainly use the fresh values anyway.


Optimizely's geo-targeting is based on IP address information from Akamai EdgeScape. Optimizely makes an API call to define the visitor's location when the snippet evaluates. This will only happen if an audience using geo-targeting is being evaluated for an experiment activated on that page. The IP address is then used in an API call that checks the address against the EdgeScape database and returns information about the visitor's location. Next, Optimizely uses that information to evaluate the audience condition and stores it in the visitor object, where it can be referenced for the duration of the session.

To troubleshoot geo-targeting, type the following URL in an adjacent tab of your website:

You'll see the information Optimizely will use to build the audience condition at the beginning of the session.

Screen Shot 2018-10-30 at 11.08.42 AM.png

Since Optimizely evaluates this information at the start of the visitor's session, mobile device users can move around during the session. If they do, the information Optimizely needs for geo-targeting will be stale. To check the freshness of Optimizely's location data, use the visitor object optimizely.get('visitor').locationto get the values Optimizely is actively using.   

Screen Shot 2018-10-30 at 2.55.50 PM.png

List Attribute and DCP

List Attributes and DCP are audiences that are based off uploaded content provided by the Optimizely user.  They are different in that list attributes are made up of a single column of data, like a set of zip-codes, while DCP is more than one column of data, like plan type and country that can be accessed by a predefined customer ID.   Each works a little differently:

  • For list attributes, when the snippet activates, it looks for cached list attributes. If they exist but are based on a set of list attribute values which differ from the visitor’s current values, the snippet ignores them.

  • For DCP, when the snippet activates, it looks for cached data. If that cached data exists but is for a set of aliases which differ from the visitor’s current aliases, the snippet ignores the data because it's out of date.

In either of these cases or when there is no cached data at all, the snippet will briefly delay making a decision to allow fresh data to arrive; currently, this delay is two seconds. If that happens, the fresh data will be incorporated into the visitor’s profile and used for evaluating audience membership. Otherwise, the decision proceeds without the new data. In that case, Optimizely assumes the visitor does not satisfy any conditions relating to that data.

Even in these situations, a visitor may still qualify for an audience. As an example, consider an audience like DCP “or” Cookie, where DCP information is not absolutely necessary to be included in the audience. For this audience, determining experiment eligibility would be delayed only if the cookie condition failed and there was no cached and valid DCP data.

To refresh the data that comes from these sources long after the page has loaded (e.g., in a single-page app), reactivate the snippet via the activate API call.

Troubleshoot list attributes

For list attributes, troubleshoot using the visitor object API call (optimizely.get('visitor').lists) to determine if you meet the conditions of an audience constructed with an uploaded list; Optimizely will return a value of either true or false. Below is an example of an uploaded list of California zip codes used as an audience condition:

Screen Shot 2018-10-30 at 2.30.02 PM.png

To identify the value Optimizely used to evaluate uploaded audience conditions, use the following URL in an adjacent tab to get the object from Optimizely's audience evaluating service, Tapi.<project id>

This object will include more details than the geo-targeting URL above.

2.25.19 PM.png

Optimizely will use the visitor's IP to find the zip code. The value is then passed to the list attributes targeting service, where it is matched against the lists that have uploaded through Optimizely. The service returns a value of true or false, which is what Optimizely uses to determine audience eligibility. This evaluation usually takes longer than a pageload, so the zip code audience will not be specifically defined until the second pageload.

Tapi services uses Maxmind for geolocation evaluation.  Unlike the Geo-targeting audience above where Optimizely makes a direct request to the endpoint and receives an object back, in List attributes Optimizely makes a request to the Tapi service.  The Tapi service, in turn, makes the request to Maxmind, which returns a location based on IP address that includes additional information like zip-codes.  This object is then used by Tapi to compare the returned information against the uploaded list on file and returns true or false evaluation for the audience condition in the response in addition to the location object. 

Troubleshoot DCP

For Dynamic Customer Profiles, troubleshoot using the visitor object API call (optimizely.get('visitor').dcpData) to determine if you meet the conditions of an audience constructed with an uploaded list.  If no object returns, confirm that an experiment using a DCP audience is active on the page.  Optimizely will return an object that returns information based on the uploaded list ID and the customer ID that Optimizely identified for the visitor.  Below is an example of the returned object:Screen Shot 2019-07-24 at 5.00.17 PM.png

In the above, the aliases object contains a set of keys and values, where the key represents the ID for the uploaded DCP table and the value is the value of the customer ID.  The ID of the uploaded table can be found under the title for the uploaded table under the Attributes section of Optimizely. 

Screen Shot 2019-07-24 at 4.48.03 PM.png


Like List Attributes Dynamic Customer Profiles rely on the Optimizely Tapi service to make decisions about if a visitor passes an audience condition or not.  When the snippet executes, and an experiment with a DCP audience activates, Optimizely looks for the customer ID.  If the customer ID is found, the value is sent to Tapi.  The audience condition is specific to a DCP table, so when Tapi 'checks' for the customerId value, it will only look at the DCP table associated with the audience condition it is evaluating for. 

When Tapi completes its check of the visitor's customerId value it will send a response that can be found in the network by filtering for the word 'tapi'.  The Optimizely userId is used as the name, click on the preview tab for an easy to read response.  This is the same information that gets stored in the visitor object.

Screen Shot 2019-07-24 at 5.32.12 PM.png

This evaluation usually takes longer than a pageload, so the DCP audience will not be defined until the second pageload.

Audience integration

The “waiting” policy for audience integration is the same for DCP and list attributes. The main difference is that, instead of the snippet initiating and waiting on HTTP requests, some other condition (e.g., a property on the global object being defined) is awaited.

Each audience integration has its own implementation requirements. For a specific integration, you can find its implementation instructions via our Integrate Other Platforms Knowledge Base article.