Creating an Evaluator

This article includes instructions and code examples for writing evaluators. For information on using the evaluators in campaigns, see the User Documentation article.

An evaluator is custom JavaScript code that runs on the web page and returns a value based on data that exists on the page. You can create evaluators to use for custom targeting conditions, variable values in templates, or real-time values for custom filtering rules.

📌

Example:

An evaluator can return the difference between the current cart value and the free-shipping threshold, and request products with a higher price than the evaluator value.

The code is run only when an experience using the evaluator is loaded onto a page. Usually, this happens during the pageload, unless an action delay is applied using triggers. Evaluators have a timeout of 4 seconds, and return as false if the timeout is reached before a result is returned.

Create the evaluator

  1. Go to Assets › Evaluators and click Add New.
  2. Enter a name for the evaluator, and (optionally) notes.
  3. Define the value type and expected values. These will affect how conditions built on the evaluator will behave:
    • Value type: Specify String or Number. If you select Number, the targeting conditions will enable you to specify greater than or less than values. If you select String, you can only target based on values that contain the string.
    • Expected values (optional): This limits the available values when using the evaluator as a targeting condition. The specified values are added in a dropdown menu. For example, if your evaluator checks whether the user is logged in or not, you can set expected values to True or False.
  4. Use the preview to review how the targeting condition will look and behave.
  5. Click Next, and write your JavaScript code in the editor. See the_ Writing evaluator code _section for more information.
  6. Click Save. Creating, editing, and deleting evaluators can take up to 5 minutes to take effect.

🚧

Evaluators can contain up to 5,000 characters.

Writing evaluator code

An evaluator is JavaScript code that returns a value. It can be simple code that fetches a text from an element on the page, or it can be code that takes any element on the page, manipulates it, and returns a result.

There are two types of evaluators:

  • Regular evaluator: Runs on the page immediately; used when there is nothing asynchronous in the process of getting a result.
  • Async evaluator: Depends on another process that has to run on the page to provide a result, such as a DOM element that appears after the page loads.

To avoid cases where an evaluator fails to return a value, or returns null because something does not yet exist on the page, we recommend using a JavaScript promise. This ensures that the targeting conditions evaluation waits until the evaluator returns a proper value. Dynamic Yield enables you to do this with our own version of the q library in the DYO object (DYO.Q).

🚧

Notes:

  • If native JavaScript promises are supported, DYO.Q uses them and extends their functionality to ensure that the performance matches the native implementation. This means that if you've already implemented DYO.Q, there's no need to change it. However, if you are still making a decision regarding your implementation, we recommend using native JavaScript promises.
  • Even if you decide not to use the q library, your code must include a reference to the library for the evaluator to run asynchronously. The reference can be commented out in the code, for example: //DYO.Q
  • Do not give different variables similar names, because this can cause interference in the running session.

Evaluator code examples

Number of items in cart
DYO.Q(DYO.waitForElementAsync("", 1, 10, 100)).then(function(elements) {
  return parseInt(elements[0].textContent);
});
Is the cart selector on the page?
DYO.Q(DYO.waitForElementAsync("",1, 10, 100))
  .then(function() {
    return "True";  
  }
);
Total cart value (without a currency symbol)
DYO.Q(DYO.waitForElementAsync("",1, 10, 100))
  .then(function(elements) {
    return parseFloat(elements[0].textContent.replace(/[^0-9\.]+/g,""));
  }, function() {
    return 0;
  });
Total cart value from the data layer

Return the total cart value as taken from the dataLayer attribute, for sites that are integrated with Google Analytics. This assumes the dataLayer is at position 0. You can also add a loop to discover the position of the dataLayer if the position is not 0.

//max retries & interval duration can be changed, make sure you are accessing the right position in dataLayer - in this example its the first index in the array
var MAX_RETRIES = 5;
var FALLBACK_VALUE = 0;
var INETRVAL_IN_MS = 100;

DYO.Q.Promise(function(resolve) {
  var retryCounter = 0;
  var interval = setInterval(function() {
    if (typeof dataLayer === 'object' && typeof dataLayer[0] === 'object') {
      clearInterval(interval);
      resolve(parseFloat(dataLayer[0].cartValue) || FALLBACK_VALUE);
    } else {
      retryCounter++;
    }

    if (retryCounter > MAX_RETRIES) {
      resolve(FALLBACK_VALUE);
      clearInterval(interval);
    }
  }, INETRVAL_IN_MS);
});
Number of available recommended items
try {
   (function() {
       var STRATEGY_ID_TO_CHECK = ;
       var MAX_PRODUCTS_TO_CHECK = ;
       if (!DYO.Q || !DYO.recommendationWidgetData) {
           return;
       }
       var deferred = DYO.Q.defer();
       DY.API('callback', function() {
           DYO.recommendationWidgetData(STRATEGY_ID_TO_CHECK, {maxProducts: MAX_PRODUCTS_TO_CHECK}, function(err, data) {
               if (data && data.slots && data.slots.length) {
                   deferred.resolve(data.slots.length);
                 } else {
                     deferred.resolve(-1);
                 }
           });
       });
       return deferred.promise;
   })();
} catch (e) {}
Difference between the cart value and the free-shipping threshold
const THRESHOLD = 50; // Cart threshold 
const CART_TOTAL_SELECTOR = '.js-cart-totals__total' // Cart selector per site

DYO.waitForElementAsync(CART_TOTAL_SELECTOR).then((elements) => {
  const cartValue = parseFloat(elements[0].textContent.replace(/[^\d.-]/g, ''));

  return Math.max(THRESHOLD - cartValue, 0);
});
Text element on the page

For example, use this evaluator to return the brand of the page.

const DEFAULT_VALUE = '';
const CSS_SELECTOR = '';

DYO.Q(DYO.waitForElementAsync(CSS_SELECTOR, 1, 100, 10))
  .then(function(elements) {
    var el = elements[0];

    return el.textContent;
  }, function() {
    return DEFAULT_VALUE;
  });
User gender
var DEFAULT_VALUE = 'Unisex';

var CSS_SELECTOR = '.customer-gender';

DYO.Q(DYO.waitForElementAsync(CSS_SELECTOR, 1, 100, 5))
  .then(function(elements) {
    var el = elements[0];

    return el.textContent;
  }, function() {
    return DEFAULT_VALUE;
  });

Writing evaluators for template variables

To display the evaluator value inside a variation (as opposed to using it for a targeting condition), the evaluator can't be asynchronous, nor can you use the q library and a promise. Its value must return immediately upon variation rendering. For example, an evaluator that returns the page language:

try{
   (function(){
       if (DY.recommendationContext && DY.recommendationContext.lng){
           return DY.recommendationContext.lng;
       }else{return 'NA';}
    })();
} catch(e) {}

Debugging evaluators

Run the following API in the browser's console to check the value that an evaluator returns. Replace "EVALUATOR_ID" with the evaluator's ID you are debugging (go to Assets › Evaluators to see the IDs of all of your evaluators).

DYO.Q(DYO.CoreUtils.safeEval(DYO.oevals[EVALUATOR_ID].code))
  .then(function(result) {
    console.log("Returned value from evaluator:", result);
  });