How Can We Help?

Decision SDK Module

Cortex’s JavaScript SDK provides a robust set of functionality for developers to interface with Cortex directly from the client-side. This document provides an overview of the SDK module related specifically to optimizing dynamic decisions. The Decision module contains all functionality needed to enable your team with high-performing decisions, made in real-time using both historical and in-session data. Dynamic decisioning includes use cases like next-best-action and next-best-offer.

Module Description
Identification Set, generate, and retrieve a unique ID for each of your users.
Behavioral Send behavioral events to Cortex as users browse your site. These events serve as the basis for predictions made by your ML Pipelines.
Decision Deploy your ML Pipelines through a decisioning framework which dynamically determines the right onsite experience to provide each user. These decisions are based on predictions from your ML Pipelines, and can be configured to optimize for conversions, revenue, or more.

Overview of Decision Projects

Decision Projects allow our partners to deploy their ML Pipelines for automated decision-making. By predicting each user’s preferences and future behavior, and wrapping those predictions in an automated decision framework, organizations can automatically select which experience to provide each user in order to optimize a business goal (e.g. maximize likelihood of conversion, maximize net revenue, etc.). These sorts of initiatives are often referred to as next-best-action, next-best-offer, or dynamic decisioning.

These decisions are based on underlying predictions generated by 1 or more Future Events, Uplift, or Recommendations pipeline. For example, a pipeline predicting the likelihood subscribing within 10 minutes of seeing a paywall can be used to optimize the decision around whether to show the paywall to a given user at a given time. Or, a set of pipelines predicting the likelihood of interacting with a particular modal can be used to determine which modal should be shown to each user.

The Decision module of the JavaScript SDK allows these types of decisions to be made directly from the client. The following sections describe various functions contained within the Decision module, as well as the objects through which these functions can be accessed.

Configuring the Module

In order to translate predictions into decisions, the JavaScript SDK relies on two pieces of decision logic specified in a configuration: (1) a Decision Rule, and (2) an Explore/Exploit setting.

To override the default configuration and add custom business logic to a given pipeline, talk to your account manager or contact

Decision Rule

Specifies the rule for translating predictions from 1 or more ML pipelines into decisions. This rule — configured when you create your Decision Project in Cortex — can be based on a a single pipeline (e.g. “target users in the 90-100th percentile”), or a comparison across multiple pipelines (e.g. “target users with the promotion that they are most likely to click on”). 

If you are using a single Future Events or Uplift pipeline to make decisions, your rule will evaluate whether the prediction for each user falls within a particular range of values (e.g. “is the user’s conversion probability between 0-10%?”). By default, decisions from an Uplift pipeline use the zero uplift score to divide users into two cohorts: those predicted to respond positively to treatment, and those predicted to respond negatively. If you are using a single Recommendations pipeline, decisions will be based on each user’s top recommendations.

If you are comparing across multiple pipelines, your rule will evaluate which pipeline scored each user the highest or lowest for some prediction metric (e.g. “for which pipeline does the user have the greatest conversion probability?”). Note that you can only compare across pipelines of the same type.

When defining a Decision Rule, you should also specify an output string for each action which is available to be taken on behalf of each user (e.g. “show_paywall”, “dont_show_paywall”). When making a decision, the SDK will choose from these actions and return the corresponding string(s).

The Decision Rule for your project can be modified over time based on a performance analysis using explore/exploit results (see below).

Explore/Exploit/Delegate Settings

In order to gather unbiased data from which to learn, Cortex uses an explore/exploit framework in which decisions are randomized for a small percentage of users (the “explore” cohort). By randomizing decisions for a small set of users the system collects data to train the decisioning framework and ensure that optimal decisions are made moving forward. Additionally, you may allocate some users to a third “Delegate” cohort for which Cortex will not make decisions. Instead, these users are reserved for you to use your status quo decision-making process against which performance of Cortex’s decisions can be compared. There are three default settings that may be overridden.

Setting Description
Explore Type Should randomization occur at the user level or the session level? Default is user-level randomization.
Explore Percentage What percent of users / sessions (depending on the value of “explore type”)  should be placed in the “explore” cohort? Default is 10%.
Delegate Percentage What percent of users / sessions (depending on the value of “explore type”)  should be placed in the “delegate” cohort? Default is 0%.

Loading a Project

Get Project

Load a Decision Project into the client, so that it may be used to generate real-time decisions as a user browses your site. This function is accessed through the Cortex API object, and returns a Project object.




Parameter Type Description
projectId string Unique ID for the Decision Project. This can be accessed from Cortex, or via consultation with your account manager.

The Project Object

The SDK’s Project object provides functions for making decisions based on ML Pipelines built in Cortex. The following functions can be accessed through the Project object:

Function Type Description
getDecision ((callback: (decision: Decision) => any) => void) | (options: Options, callback: (decision: Decision) => any) => void |  Get the object representing the optimal decision to be made for a given user (see below).

Getting a Decision

For a given user, return a Decision object containing information about which action to take on behalf of the user.

If your Decision Rule is based on 1 or more Real-Time pipelines, the JavaScript SDK will automatically combine information from the user’s current session with historical features in order to generate an up-to-date decision in real-time. 


project.getDecision(options, function(decision){   // user-defined logic to act on the decision });


Parameter Type Description
callback function JavaScript function containing logic for executing the optimal decision (e.g. showing a paywall).
options Partial<{ additionalFeatures: {[key: string]: any}, onError: (err: string) => any }> Optionally, include key-value pairs corresponding to additional features which should be passed to the Project when generating a real-time prediction (which will be used for decision optimization). Example: current_article_section: ‘news’You may also pass an “onError” key to the Options parameter, allowing you to specify a function for gracefully handling errors. Example: onError: () => { handleError(); }

The below example shows how you might define the Options parameter, including both additional features and error handling:

const options = {
  additionalFeatures: {
    foo: "bar"
  onError: () => handleError(),

The Decision Object

The SDK’s Decision object represents a dynamic decision generated by your Decision Project. The following functions can be accessed through the Decision object:

Function Type Description
actions {id: string}[] The optimal action(s) to be taken for the user. Each action is represented by a hash containing an ‘id’ key, whose value is the string that you defined for each action when the Decision Project was created. If using Future Events or Uplift pipelines, a single action will be returned. If using a Recommendations pipeline, multiple actions will be returned, in descending order of relevance to the user.
tieEventToDecision (params?: {[key: string]: int | string}) => {[key: string]: int | string} When sending an event for the decision that was executed (e.g. shown_paywall), include this function alongside event parameters so that the event can be tied to the decision that was returned by the SDK. This is required for proper functioning of Cortex’s SDK.

Getting Best Action

Get the optimal action(s) to be taken for a user. Each action is represented by a hash containing an ‘id’ key, whose value is the string that you defined for each action when the Decision Project was created. If using Future Events or Uplift pipelines, a single action will be returned. If using a Recommendations pipeline, multiple actions will be returned, in descending order of relevance to the user.



Example Response

  {id: "show_paywall"}

Recording Treatment Events

Decision optimization requires that a treatment event be sent to Cortex. This event indicates that a decision returned by the SDK was in fact acted upon (e.g. showing a paywall). This treatment event must also be tied to the Pipeline from which the decision was generated. The tieEventToDecision function automatically handles this connection. The function must be included as an argument to your existing event tracking, be it through the SDK’s Behavioral Module or another provider such as Google Tag Manager.

See below for an example of tying a “shown_paywall” event to a dynamic decision when recording events through the Cortex SDK:




api.send('shown_paywall', null, {params: decision.tieEventToDecision()});

Example Usage

The following example shows how the SDK might be used to dynamically determine whether a user should be shown a paywall. The SDK executes the following logic –

  • Load a Decision Project into the client
  • Load a paywall and a registration wall into the client
  • Generate a dynamic decision to determine which wall, if any, should be shown
  • Record a treatment event indicating which wall, if any, was shown


  var project = api.getProject('your-project-id');
  var paywall = document.getElementById('subscription_paywall');
  var regwall = document.getElementById('registration_wall');

  project.getDecision((decision) => {
    actions = decision.actions;
    if (actions.find(({id}) => id == "show_paywall") {
      paywall.className = 'shown';
      regwall.className = 'hidden';
      api.send('shown_paywall', null, {params: decision.tieEventToDecision()});
    } else if (actions.find(({id}) => id == "show_registration_wall") {
      paywall.className = 'hidden';
      regwall.className = 'shown';
      api.send('show_registration_wall', null, {params: decision.tieEventToDecision()});
    } else {
      paywall.className = 'hidden';
      regwall.className = 'hidden';

Related Links

Still have questions? Reach out to for more info!

Table of Contents