Introduction

LiftIgniter is a personalization service for content recommendations. We take in data about 1) user behavior and 2) content metadata and use machine learning algorithms to rank which items are most likely to be clicked on for each individual user, on every pageview. Our service can be integrated via our Javascript SDK, API, or using a mix of both.


In a pure Javascript integration, there are four key snippets of code you will need:

  1. The Tracking Beacon - this loads our full SDK asynchronously on page load, and tracks three basic behavior events (pageviews, staying on the page for 10s, and staying on page for 3 minutes). It also collects metadata from every page where it is active to populate our Inventory of recommendable items. If there are some pages you do not want to include in recommendations, please see our documentation on Inventory Management!
  2. A Mustache.JS Template - this HTML template identifies which metadata fields should be shown where, and which CSS classes should be applied to them
  3. The Recommendation Area <div> - most often, there is already an area on the page that contains recommendations that you will be A|B testing LiftIgniter against. This <div> is identified as the overwrite target in the Widget Request JS
  4. The Widget Request JS - this registers the name of the widget, how many items need to be recommended, and which div should be overwritten and tracked.




A diagram of the order of operations for the Javascript functions involved in requesting and rendering recommendations


Example Code Snippets


The Tracking Beacon

<script type="text/javascript">
  if (typeof $igniter_var === 'undefined') {
    !function n(t,c,r,o,a,i,s,e,f,l,u){l=null!=t[r]&&"function"==typeof t[r].now?t[r].now():null,t.$igniter_var=i,t[i]=t[i]||function(){(t[i].q=t[i].q||[]).push(arguments)},e=c.getElementsByTagName(o)[0],(f=c.createElement(o)).async=1,"//cdn"==a?(t[i].s=l,f.onerror=function(e){t[i].e=e,n(t,c,r,o,a+"-fallback",i,s)}):t[i].r=l,(u=!t.Promise||!t.MutationObserver||!Object.assign)||(t[i].v="nbc"+(0<=a.indexOf("-fallback")?"f":"")),f.src=a+".petametrics.com/"+s+(u?"":"-nbc")+".js?ts="+(+new Date/36e5|0),e.parentNode.insertBefore(f,e)}(window,document,"performance","script","//cdn","$p","{JAVASCRIPT_KEY");

    $p('init', "{JAVASCRIPT_KEY");
    $p('send', "pageview");
  }
</script>


A Mustache.JS Template

<script type="application/mustache"
        id="li-recommendation-template">
  {{#items}}
  <div class='recommended_item'>
    <a href="{{url}}">
      <img src="{{thumbnail}}" width="150" height="150" />
      <span class="title">{{title}}</span>
    </a>
  </div>
 {{/items}}
</script>


You can use any field name in your inventory metadata in your template, and apply any CSS you want to it. This allows our recommendations to be added invisibly to your site - you have complete control over what your widgets look like.


The Recommendation Area

<div id="li-recommendation-unit"></div>


If you don't have any recommendations being shown in an area, your div may be as simple as the example above. If you want to replace or A|B test against an existing recommendation area, make sure that you select the appropriate parent div.


The Widget Request JS

$p('register', {
    max: 5, // Number of items you want to show
    widget: 'default-widget',
    callback: function(resp) {
      // Query selector should match div name from Recommendation Area
      var el = document.querySelector('#li-recommendation-unit');
      // Template should match mustache template name from Step 2
      var template = document.querySelector('#li-recommendation-template').innerHTML;
      // Basically Mustache.render(template, resp);
      el.innerHTML = $p('render', template, resp);
      
      $p('track', {
         // Div name from the Recommendation Area and recommendation item div name from Template
         elements: document.querySelectorAll('#li-recommendation-unit > div.recommended_item'),
         name: 'default-widget',
         // Match widget name
         source: 'LI',
         // Source "LI" indicates recommendations are provided by LiftIgniter
      });
    }
   });

// Executes the registered call.
$p('fetch');


You will notice 4 key functions within the widget request.

$p("register"): The register function prepares recommendation query to LiftIgniter's model server. You can set multiple registers before running $p("fetch"). Every time the register function is invoked, then our SDK will queue that request, and execute it once $p("fetch") is invoked. The register function can also be modified by any number of optswhich apply certain rules and filters to the recommendations allowed.


$p("render"): Render takes in the template and the items to render, and writes them to the specified area. This is used in the callback of $p("register") so that it runs only once recommendation items are returned to the client.


$p("track"): One of the most important functions in our entire JS SDK, $p("track") looks for all anchor links in the widget after our recommendations have been rendered. It then attaches event listeners and tags to each of those anchor links. This allows us to track the "widget_shown" (the recommendations were loaded on the page), "widget_visible" (the recommendations were scrolled into the user's viewport) and "widget_click" (the user clicked on a particular item) events. These three events are the primary signals for training our algorithm models. This is used in the callback of $p("register") so that it runs only once recommendation items are returned to the client.


$p("fetch"): This function executes all of the requests for recommendations queued up via $p("register"). In other words, you can register multiple widgets on a single page, then use fetch to get all of them at once.


More Information

We strongly recommend downloading the attached PDF, which goes through our JS integration in more detail, and provides extensive links to the rest of our documentation. It answers many of our FAQs, and provides troubleshooting tips as well. Please reach out to Support if you have any additional questions!