Once you are using LiftIgniter, A|B testing design and layout changes is the best way to further optimize performance.
You can use LiftIgniter's tracking to measure the impact of these changes by identifying a unique "source" value for each variant, similar to the A|B test you probably ran when trying out LiftIgniter against your existing recommendation strategy.
"Source" Names
Typically, you would use our two standard source names, "base" or "LI". "Base" is always indicated by an orange line, while "LI" is always blue. In a design test, where LiftIgniter recommendations are being used in all slices, you can use custom "source" names as well. These will be identified by purple line in the Analytics graphs. In the example below, the customer chose to test two different layouts for their right-rail widget. Each layout is identified by a different custom source, resulting in two purple lines on the graph.
In general, we would recommend calling the control slice "base" and use a custom name for the variant so that you can more easily see the performance difference between the two, as one line would be orange and the other purple.
Full Code Sample
// The template for displaying the recommended items. <script type="application/mustache" id="recommended-item-template"> <div class='recommended_item'> <a class='headline' href='{{url}}'>{{title}}</a> </div> </script> // Renders the recommendations and overwrites innerHTML of area marked with 'li-widget-item' according to the template above. var rendering_callback = function(resp) { var els = document.querySelectorAll('#li-recommendation-unit > div.li-widget-item'); var template = document.querySelector('#recommended-item-template').innerHTML; for (var i = 0; i < els.length && i < resp.items.length; ++i) { // Basically Mustache.render(template, resp.items[i]); els[i].innerHTML = $p('render', template, resp.items[i]); } } // Tracks each 'li-widget-item' by adding event listener and query string tags to each URL. var trackAlgo = function(algorithm) { $p('track', { // marked for replacement during A/B test. elements: document.querySelectorAll('#li-recommendation-unit > div.li-widget-item'), name: 'my-widget-name', source: algorithm, _debug: true }); } var abTestHandler = function(slice) { // Slice is modulo 100 of the hash. // So you can set slice to 0 and 100 to check LI and base slice respectively if (slice < 50) { // Register call to overwrite widget being tested with LI recommendations, // and track metrics appropriately. $p('register', { max: 4, widget: 'my-widget-name', callback: function(resp) { // You might wish to wrap the code in this callback inside jQuery, to handle load order issues //render the recommendations rendering_callback(resp); // track the recommendation area as the control or 'base' slice. trackAlgo('base'); } }); } else { // You might wish to wrap the code in this callback inside jQuery, to handle load order issues // track marked areas as the variant name. $p('register', { max: 4, widget: 'my-widget-name', callback: function(resp) { // You might wish to wrap the code in this callback inside jQuery, to handle load order issues //render the recommendations rendering_callback(resp); // track the recommendation area as the variant slice with a custom source name. trackAlgo('new-design-1'); } // Executes all registered calls. $p('fetch'); } // Decide which slice the current user is on. // $p('userHash') hashes user cookie id to a random 32-bit integer. // $p('abTestSlice') returns the absolute value of this number mod 100 $p('abTestSlice', { callback: abTestHandler } );