Predict web recommender templates use the popular doT.js template language.

When recommended items are returned from the recommender servers in the SC object, the template controls the structure and the content of document elements inserted into your recommendation widget. Basically, a template is a piece of HTML code containing JavaScript snippets that refer to the recommended items.

We serve a default template controlled by CSS, but you are welcome to implement your own template. We advise you to familiarize yourself with the concepts by reading this section; then you can start the actual implementation by copying and modifying the default template.

Contents

Using a non-default recommender template

If you want to use your own template, follow the instructions below. Please note that you can create multiple templates and that any widget can reference any template. Just be careful to ensure that they have unique names.

Defining a recommender template

Add your template to a script block with the scripts type attribute set to text/html. Inside the block, start with the preamble <![CDATA[ and finish with ]]>. You may define multiple templates using different ids. The example below shows how to add a dummy template that displays nothing but the text “This is my first website recommender template“.

<script type="text/html" id="my-recommender-template">
<![CDATA[
<i>This is my first recommender template</i>.
]]>
</script>

Applying the template to a recommender box

The template can be passed to the recommend API command by setting templateId. For example, the above-defined my-recommender-template can be applied to the RELATED widget as below.

<div id="my-recommendation-container"></div>
<script>
      ScarabQueue.push(["recommend", {
       logic: "RELATED",
       containerId: "my-recommendation-container",
       templateId: "my-recommender-template"
     }]);
</script>

The template language

Templates are substituted with the JavaScript object SC holding the recommended products in the array SC.page.products. Each product has attributes corresponding to the columns of the uploaded catalog. For example, SC.page.products[0].title refers to the content of the catalog field title of the first recommended item, etc.

The size of this array never exceeds the limit passed to the recommend command as an argument.The template is essentially an HTML string, but you can insert the value of a JavaScript variable into the HTML by {{= variable }}. For example:

<i>We recommend {{=SC.page.products.length}} number of products for You</i>!

In addition, the template may contain JavaScript code blocks between {{ and }}. For example:

{{ if(SC.page.products.length > 0) { }}
<i>We primarily recommend {{=SC.page.products[0].title}} for You</i>!
{{ } else { }}
<i>Sorry! No recommendations found!</i>
{{ } }}

Marking the outer HTML elements of recommended items

Our system needs to track each click on recommended items. To support this, you must add the attribute data-scarabitem to one of the HTML elements containing the recommended item, and set the value to the ID of the recommended product. See the example of a link to a recommended item contained in a span element:

<span data-scarabitem="{{= SC.page.products[i].id }}">
    <a href="{{= SC.page.products[i].link }}">
        <img src="{{= SC.page.products[i].image }}">
            {{= SC.page.products[i].title }}
   </a>
</span>

Names of the recommender navigation buttons

Users may request more recommendations, or go back to the previously recommended items. The corresponding HTML elements must therefore have class attributes set to scarab-next and scarab-prev, respectively. Our system will set the click event handlers on those elements. For example:

<div class="scarab-prev">Click here for previously shown recommendations</div>
...
recommended items
...
<div class="scarab-next">Click here for more recommendations</div>

If the corresponding operation is disabled (the first set is displayed, or there are no more recommendations to show), the scarab-disabled-button class name is added to the HTML element’s class attribute. CSS rules can be applied to this class to hide or disable the corresponding buttons.

Copy and modify the default template

If you are familiar with the previous section, you start the actual implementation by using and modifying the default template quoted below.

<script type="text/html" id="my-recommender-template">
<![CDATA[
{{ if (SC.page.products.length) { }}
<div class="scarab-itemlist">
    <div class="scarab-prev">◀</div>
    {{ for (var i=0; i < SC.page.products.length; i++) { }}
      {{ var p = SC.page.products[i]; }}
      <span data-scarabitem="{{= p.id }}" class="scarab-item">
          <a href="{{= p.link }}">
              <img src="{{= p.image }}">
              {{= p.title }}
          </a>
      </span>
    {{ } }}
    <div class="scarab-next">▶</div>
</div>
{{ } }}
]]>
</script>

Remember that you have to apply the template to each recommender widget as in the example below:

<div id="my-recommendation-container"></div>
<script>
ScarabQueue.push(["recommend", {
    logic: "RELATED",
    containerId: "my-recommendation-container",
    templateId: "my-recommender-template"
}]);
</script>

Working with the recommended items directly in Javascript

If you want to access the recommended items directly, you can pass a Javascript function to the recommend command, called the success handler. It is called after the recommendation service returns the recommendations but before the widget is rendered. The success handler takes two parameters, the SC object, and a render function which has to be called to start the widget rendering. Here are some things that you can do with this function.

Display discounts

Let’s say you want to display the discount on the product compared to the recommended retail price. You could calculate the value from the price and msrp fields in the template code between double brackets {{ }}, but that would make the template harder to read. The success function lets you separate display from logic.

var mySuccessHandler = function(SC, render) {
  for (var i = 0, l = SC.page.products.length; i < l; i++) {
    var product = SC.page.products[i];
    product.discount = ((1 - product.price / product.msrp) * 100).toFixed(0) + '%';
  }
  render(SC);
};

ScarabQueue.push(["recommend", {
  logic: "RELATED",
  containerId: "my-recommendations",
  success: mySuccessHandler
}]);

The example above allows you to use the field discount in the recommender template similarly to catalog fields like title or link.

Do something after the recommendations are rendered

You might want to attach a custom click handler, or start an animation after the widget is rendered.

var mySuccessHandler = function(SC, render) {
  render(SC);
  attachMyClickHandler();
};
ScarabQueue.push(["recommend", {
  logic: "RELATED",
  containerId: "my-recommendations",
  success: mySuccessHandler
}]);

Don’t use Scarab rendering, render with your own code

If you just want to get the IDs of the recommended products, and take care of the rest yourself, you can do this with a success handler that doesn’t call render.

var mySuccessHandler = function(SC, render) {
  var recommendedItems = [];
  for (var i = 0, l = SC.page.products.length; i < l; i++) {
    recommendedItems.push(SC.page.products[i].id);
  }
  doMyOwnThing(recommendedItems);
};
ScarabQueue.push(["recommend", {
  logic: "RELATED",
  containerId: "my-recommendations",
  success: mySuccessHandler
}]);

You will still have to render the widget in the given container, and mark the recommended items with data-scarabitem attributes, otherwise click tracking won’t work.

Get live data from your servers

In some scenarios, you need to collect additional information about the recommended items by talking to other servers with asynchronous requests. For example, you sell movie tickets, and you want to display the exact number of tickets available, checking availability in your own booking database.

var mySuccessHandler = function(SC, render) {
  $.ajax({
    url: 'ajax/num_available_tickets?items=...',
    success: function(data) {
      for (var i = 0, l = SC.page.products.length; i < l; i++) {
        SC.page.products[i].num_available_tickets = ...
      }
      render(SC);
    }
  });
};
ScarabQueue.push(["recommend", {
  logic: "RELATED",
  containerId: "my-recommendations",
  success: mySuccessHandler
}]);

The num_available_tickets field can now be used in the template code. Please note that this delays the widget’s appearance, since the browser will have to wait for an extra request.

See also