JavaScript SDK

Vidora’s JavaScript SDK allows developers to send, set and retrieve user information from the client-side. The JavaScript API is also fully compatible with tag managers such as Google Tag Manager and Tealium.

The following sections describe how to initialize the JavaScript API and call its various functions to set unique ids for your users, and send behavioral events to Vidora.

Initializing Vidora’s API

Load Vidora’s JavaScript API

Load Vidora’s JavaScript API with the following script tag:

<script src="https://assets.vidora.com/js/vidora-client.1.3.2.min.js" type="text/javascript"></script>

To avoid manually updating your JavaScript embed when a new version is released, Vidora also provides an option to embed the latest version:

<script src="https://assets.vidora.com/js/vidora-client.1.x.x.min.js" type="text/javascript"></script>

Add Loader Snippet

Paste the following loader snippet with your API Key in the head section of your html document: Place this snippet between synchronously loaded script tags and before any calls made to the Vidora Global Object.

<script>(function(a,b,c,d,e){var f={_q:[]};f.ready=f.push=function(a){f._q.push(a)},c in a||(a[c]=f),a[c].ready(function(a,b){b._i(d,e)})})(window,document,"vidora",YOUR_API_KEY);</script>

Vidora’s Global and API Objects

After including either the loader snippet or vidora-client.js, any call to the Vidora Global Object (window.vidora) is valid. All calls to Vidora’s API must route through window.vidora and will queue until the Vidora API has finished loading.

The window.vidora.ready call will allow the Vidora API to complete loading and produce a Vidora API object that you can safely access. For example:

window.vidora.ready(function(api) {
   console.log("Vidora API finished initializing!");
   api.getUUID();
});

Calling API Functions

Function calls to Vidora’s JavaScript API can be made with array arguments or with closures.

Calls with Array Arguments

Push an array to the Vidora API Object, with the first element specifying the function name and subsequent values specifying the arguments to be sent to the function call. Note, you cannot get values calling an API function with a push format.

Request

window.vidora.push([functionName, arguments]);

Parameters

Parameter Type Description
functionName string The name of the API function.
arguments string A string of a single argument or an array of argument strings.

Calls with Closures

While the push format will not allow you to get values, accessing the API with a closure lets you call any function within the Vidora API Object.

Request

window.vidora.ready(function(api) {   
  api.functionName(arguments);
});

Parameters

Parameter Type Description
closure function A function that takes a single argument, which is the Vidora API Object.

 

Identifying Your Users

Vidora uses unique user ids in order to collect behavioral event data and generate predictions for each of your users. The JavaScript API provides various ways to set, generate, and retrieve these unique user ids.

Function Description
api.setUserId Specify an id to associate with event data sent to Vidora’s servers.
api.getUserId Retrieve the user id that has been set with api.setUserId. If an id has not yet been set and api.getUserId is run, Vidora will generate a unique user id (UUID) and store this value in a vidoraUserId cookie
api.getUUID Generate a unique user id (UUID) and store this value in a vidoraUserId cookie

 

If you have unique ids for your users, Vidora recommends specifying this id (userId) using api.setUserId. Setting the id allows you to tie predictions from your machine learning models back to a known list of users, so that you can consider model outputs in conjunction with other user information that you may have. If you do not have a unique id (e.g. for anonymous users), Vidora can handle user tracking for you by generating a unique user id (UUID) and storing the value in a vidoraUserId cookie. A cookie will be created when any of three things occur:

  1. getUUID is run
  2. getUserId is run when an id has not been set using api.setUserId
  3. A user’s id has not been set and an event is submitted for that user

If you wish to avoid creating a cookie, ensure that (1) no calls to api.getUUID are run, (2) calls to api.getUserId are not made prior to setting the user id, and/or (3) a user id is set with api.setUserId prior to sending an event for the user.

Setting the UserId

Using the api.setUserId function, you can specify a userId to associate with event data sent to Vidora’s servers. When a userId is set, subsequent events that occur on the page will be assigned to that user. Note that api.setUserId should be called on every page load to ensure that data is sent from across your entire site.

If api.getUUID is run after a userId is set, evcents will still be sent with the userId that you specified, but Vidora will also generate a unique user id (UUID) and store this value in a vidoraUserId cookie.

Request

api.setUserId(userId)

Parameters

Parameter Type Description
userId string The user id value to send to Vidora’s servers. It is important that each user, both logged in and anonymous, is assigned a unique id.

 

Example 1: Array Arguments

The setUserId function is executed on the Vidora API Object once the API has loaded, setting the userId to “7baffc459cd6047b7a059f697681c04e”:

window.vidora.push(["setUserId", "7baffc459cd6047b7a059f697681c04e"]);

Example 2: Closures

Similar to the prior example, the closure will execute api.setUserId once the API has loaded, setting the userId to “7baffc459cd6047b7a059f697681c04e”:

window.vidora.ready(function(api) {   
    api.setUserId("7baffc459cd6047b7a059f697681c04e");
 });

Getting the UserId

Once the userId has been set with the api.setUserId function, the api.getUserId function retrieves the userId and prints this value to the developer’s console.

If api.getUserId is run but you have not set an id for the user, Vidora will generate a unique user id (UUID) and store this value in a vidoraUserId cookie.

Request

api.getUserId()

Since the api.getUserId function retrieves a value, it must be run with closures rather than array arguments.

Example: Closures

Once the API has loaded, the api.getUserId function gets the userId and prints this value to the developer’s console.

window.vidora.ready(function(api) {
   console.log("UserId: " + api.getUserId());
});

Getting The Unique User Id (UUID)

When the function call api.getUUID is run, Vidora will generate a unique identifier for the user and store this value in a vidoraUserId cookie. For example, if an anonymous user is interacting with your site, a UUID will be generated for this user if the user’s events are submitted to the API. The value of the vidoraUserId cookie can also be accessed by calling api.getUUID. The default expiration date of the vidoraUserId cookie is 2 years since the time it was created.

Request

api.getUUID()

Since the api.getUUID function retrieves a value, it must be run with closures rather than array arguments.

Example: Closures

Once the API has loaded, the api.getUUID function gets the vidoraUserId cookie value and prints this value to the developer’s console.

window.vidora.ready(function(api) {
   console.log("Vidora UUID: " + api.getUUID());
});

Sending An Event

Events sent to Vidora’s Analytics Servers are used to improve recommendations and predictions for each of your users. Behind the scenes, Vidora aggregates these event messages into batches that are sent together to minimize the number of packets that must be sent, so a call to send an event may not immediately put a packet on the wire.

Request

api.send(eventType, itemIds)

Parameters

Parameter Type Description
eventType string The type of event that has occurred.
itemIds string A string of a single item’s id, or an array of string item ids associated with the event.

 

Example 1: Array Arguments

Sending a play event for the item id “dQw4w9WgXcQ” to Vidora’s servers using push syntax looks like:

window.vidora.push(["send", "play", "dQw4w9WgXcQ"]);

Example 2: Closures

Sending a play event for the item id “dQw4w9WgXcQ” to Vidora’s servers using closure syntax looks like:

window.vidora.ready(function(api) {
   api.send("play", "dQw4w9WgXcQ");
});

Example 3: Array Arguments with Multiple Item Ids

Sending shown events for two items having the ids “dQw4w9WgXcQ” and “WgXcQdQw4w9” to Vidora’s servers using push syntax looks like:

window.vidora.push(["send", "shown", ["dQw4w9WgXcQ","WgXcQdQw4w9"]]);

Vidora recommends that a shown event should only be sent for an item if it is at least 50% visible on the page for at least 1 second. A shown event should only be sent once per item per page load. The sample code below is designed to send shown events in the suggested manner for items within a module.

// Get the slots and create a handler that listens for visibility changes.
function getHtmlElements() {
  // Create a function to grab HTML elements that contain the module slots.
}

var itemElements = getHtmlElements();
var handler = createVisibilityChangeHandler(itemElements, vidoraAPI);

window.addEventListener('DOMContentLoaded', handler);
window.addEventListener('load', handler);
window.addEventListener('scroll', handler);
window.addEventListener('resize', handler);

// Call the handler manually.
handler();

// Set the amount of time that an item must be visible in order for a shown event to occur to 1000 milliseconds.
var SHOWN_DWELL_DURATION = 1000;

// Set the percent of pixels that must be visible on the page to count as an impression to 50%.
var SHOWN_PIXEL_PERCENT  = 0.5 - 0.0000001;

// When the visibility changes (scrolls, resizes, content loaded), check to see whether slots are visible and if so, fire off a shown event.
function createVisibilityChangeHandler(itemElements, vidoraAPI) {
  return function() {
    for (var i = 0; i < itemElements.length; i++) {
      var slot = itemElements[i];
      // Only send a shown event for the slot if it is visible and an event hasn't already been sent.
      if (!slot.shownSent && slotIsVisible(slot)) {
        // Send the shown event only after enough time has passed during which the slot is still visible. Clear the timeout if it is no longer visible, and wait if the slot already has a timeout on it.
        if (slot.timeout) {
          // Create a handler to send the shown event, and set a timeout of 1 second.
          var shownHandler = createSendShownEventHandler(slot, vidoraAPI);
          slot.timeout = window.setTimeout(shownHandler, SHOWN_DWELL_DURATION);
        }
      }
      else if (slot.timeout) {
        // If the slot has a timeout, but it is no longer visible, clear the timeout.
        window.clearTimeout(slot.timeout);
        delete slot.timeout;
      }
    }
  }
}

// Create a handler for sending a shown event so we don't run into the for loop closure problem where the variables aren't scoped properly.
function createSendShownEventHandler(slot, vidoraAPI) {
  return function() {
    // Retrieve the content id from the item element. The getAttribute() method is the recommended method of retrieving the content id, but you may retrieve it any way you wish, including an asynchronous approach.
    var contentID = slot.getAttribute("data-id");
    var position = slot.getAttribute("data-position");
    vidoraAPI.send("shown", contentID, {
      params {
        group_id: "GROUP_ID" // Set the group_id to a unique identifier for each module
        position: position,
        cookie_id: vidoraAPI.getUUID()
      }
    });
    // Mark the slot as shown.
    slot.shownSent = true;
  };
}

// Returns whether the slot is visible on the page by checking first whether the document is hidden and then checking whether the element is in the viewport.
function slotIsVisible(slot) {
  return (!document.hidden && isElementInViewport(slot));
}

// Determine if an element is within the viewport by calculating the area of overlap between the rectangle defined by the window viewport and element's bounding rectangle relative to the viewport. The element is considered visible if at least a percent of the area is visible within the viewport, or if larger than the viewport, at least a percent of the viewport contains the item.
function isElementInViewport(htmlElement) {
  var rect = htmlElement.getBoundingClientRect();
  var elementArea = rect.width * rect.height;
  var viewportWidth = window.innerWidth;
  var viewportHeight = window.innerHeight;
  var viewportArea = viewportWidth * viewportHeight;
  var overlapX = calculateOverlap(0, viewportWidth, rect.left, rect.right);
  var overlapY = calculateOverlap(0, viewportHeight, rect.top, rect.bottom);
  var overlapArea = overlapX * overlapY;
  return overlapArea > SHOWN_PIXEL_PERCENT * Math.min(elementArea, viewportArea);
}

// Helper function to calculate the overlap between two intervals. Returns 0 if no overlap.
function calculateOverlap(min0, max0, min1, max1) {
  return Math.max(0, Math.min(max0, max1) - Math.max(min0, min1));
}

Integrating with Google Tag Manager

The JavaScript API can be implemented using tag management systems such as Google Tag Manager (GTM). GTM allows you to collect behavioral data from the client and send it to Cortex without having to insert Vidora snippets directly into your front-end code.

The key elements of GTM are described below:

  • The Data Layer is a JavaScript object that acts as a virtual layer of your website where information is stored and sent to GTM, so that it may later be transferred to Cortex. Variables are used to capture information from your webpages. As behavioral events occur, information about these events are stored in variables and sent to the data layer.
  • Tags are code snippets used to report behavioral events from the data layer to Cortex using JavaScript API functions.
  • Triggers are used to observe behavioral events sent to the data layer and decide which tags, if any, should be run in response.

Google Tag Manager uses these to automatically check whether actions being taken by users on your webpage match the events specified in your triggers. If a match occurs and a trigger is fired, GTM will execute tags associated with that trigger to send behavioral data to Cortex.

The steps outlined below (1-4) provide instructions for integrating the JavaScript API with GTM.

Step 1: Define data layer variables.

Define the variables to be stored in your GTM data later. These variables contain information that you would like to collect from your webpage and pass to GTM.

Built-In Variables

GTM comes equipped with several built-in variables that you may configure to include in your data layer. To send behavioral events to Cortex, the built-in ‘Event’ variable is required. Depending on your use cases, other built-in variables you may want to configure include:

User-Defined Variables

GTM also allows you to defined custom variables in order to send additional information to the data layer. Please see the Event Parameters section for a list of required and optional parameters available to define as variables and send alongside each event. Note that the required type parameter should be configured as the built-in ‘Event’ variable (see above), not a user-defined variable.

Step 2: Send events through the data layer.

First, set up your data layer by including the following snippet at the head of your webpage.

<script>
   dataLayer=[];
</script>

The data layer snippet must be placed above any GTM container code, since GTM must fetch variables from the data layer before evaluating any triggers or executing any tags.

Once the data layer is configured, send event data from your front-end to your data layer, where it may be collected by GTM and routed to the JavaScript API.

Example Click Event

<script>
  dataLayer.push({
    "event": "click",
    "item_id": "abc"
  });
</script>

The above example snippet should be executed when the user clicks on item “abc”. The built-in ‘Event’ variable and user-defined ‘item_id’ variable must be declared prior to sending this event to the data layer.

When sending shown events for a list of items, data should be consolidated in an array so as to minimize the number of pushes required.

Example shown events

<script>
  dataLayer.push({
    "event": "shown",
    "item_id": ["123", "456", "789"]
  });
</script>

The above example snippet should be executed when the user is shown three items with item_ids “123”, “456”, and “789”. The built-in ‘Event’ variable and user-defined ‘item_id’ variable must be declared prior to sending these events to the data layer.

Step 3: Create event triggers.

Once you’ve configured your front end to push variables onto the data layer when events occur, you may now set up triggers to listen for certain events. When a variable with the value specified by your trigger is passed to the data layer, the trigger evaluates to true and prompts certain tags to run.

Example Click Event Trigger

The above example trigger specifies that the built-in ‘Event’ variable must be sent to the data layer with value “click” in order for tags associated with this trigger to execute. In the next step, we will create a ‘Vidora Click Event’ tag which will run when this ‘Click Event’ trigger is fired.

A trigger should be defined for each event type that you plan to send to Cortex. Available event types include:

Name Filter Description
click Event = click User clicked to view the item.
shown Event = shown User was shown the item.
group_shown Event = group_shown User was shown the group of items (note that this event should be accompanied by the group_id variable).
play Event = play User began playing media content.
playhead_update Event = playhead_update User played x seconds of media content.
share Event = share User shared the item.
like Event = like User liked/un-liked or disliked/un-liked the item.
purchase Event = purchase User purchased the item.
sent Event = sent User was sent an email or app notification.

 

Step 4: Create tags.

Now that you’ve set up your triggers, create tags which will execute when a trigger’s firing criteria are met. Your tags will use Vidora’s JavaScript API functions to send information from GTM to Cortex when the associated trigger is fired.

Load Vidora Snippet

First create a tag to load the Vidora JavaScript SDK, set the userId, and send pageview events on every webpage. This tag should be associated with the ‘All Pages’ firing trigger to ensure that it is run across your entire site. The script that must be loaded is:

<script src="https://assets.vidora.com/js/vidora-client.1.2.9.min.js" type="text/javascript"></script>

<script>(function(a,b,c,d,e){var f={_q:[]};f.ready=f.push=function(a){f._q.push(a)},c in a||(a[c]=f),a[c].ready(function(a,b){b._i(d,e)})})(window,document,"vidora",YOUR_API_KEY);</script>

<script>
  window.vidora.push(["setUserId", "GLOBAL_USER_ID"]);
  window.vidora.push(["send", "pageview", null, { params: { page_hostname: {{page_hostname}}, page_path: {{page_path}}, page_url: {{page_url}}, referrer: {{referrer}} }}]);
</script>

The variables included in the ‘params’ hash depend on which built-in and user-defined variables you would like to attach as metadata to the pageview event. Note that if an id value is not passed to the setUserId function, Vidora will create a cookie with a unique user id (UUID) for the user.

Sending Events

Next create tags associated with each event trigger in order to send event data to Cortex.
Example Click Event Tag

<script>   
  window.vidora.push(["send", "click", {{content_id}}, { params: { group_id: {{group_id}}, page_url: {{page_url}}, referrer: {{referrer}} }}]);
</script>

The above example tag reports a click event for the user along with the content_id, group_id, page_url, and referrer variables associated with the event. This snippet should be loaded into a tag associated with a trigger that fires when the value of the ‘Event’ variable equals “click”.

Handling Ad Blockers

When a user has enabled certain ad blockers, Cortex-powered modules may be prevented in the browser. Vidora’s JavaScript API allows you to configure a content delivery network (CDN) to bypass these ad blockers using the below four steps:

  1. Set up a CDN in front of origin domain alloy.vidora.com, so that requests are routed through the CDN rather than made directly to a Vidora domain.
  2. Do not cache Vidora’s responses in the CDN, so that every request is redirected to Vidora’s servers.
  3. Import your SSL certificate to the CDN so that HTTPS allows the client to connect with the CDN.
  4. Ensure that all requests to Vidora’s APIs and links to Vidora assets use the CDN domain.

Security

Event data is always sent with HTTPS using TLS to Vidora’s servers. We do not allow SSL 3.0 due to potential for the POODLE Attack.

Each Vidora API Key is securely generated and revocable on Vidora’s servers.

If signed authentication is necessary, please see documentation on calling our Personalization API with server side integration. Please note that one cannot mix signature authentication and token-only authentication for the same service calls, as the signature would no longer be useful for authentication.

Tested Browsers

The JavaScript API goes through automated and manual tests to ensure cross-browser functionality. We currently test on Internet Explorer 9-11, Firefox, Chrome, Safari, Opera, and mobile browsers on iOS and Android.

Unsupported browsers, such as IE6, fail gracefully; a user viewing a site with IE6 will see the site as it would appear without Vidora’s script-loading, and user events will not be collected.

Please contact support@vidora.com if you find any issues with a particular browser or have additional requirements!

Related Links

Still have questions? Reach out to support@vidora.com for more info!

Table of Contents