Implementation

<!DOCTYPE html>
<html>
<head>
  <title>Bunchbox implementation sample</title>
  <script src="//cdn.bunchbox.co/4aa7bb5c5616ee6459a19734.min.js"></script>
</head>

<body>
The content of the document......
</body>
</html>

Bunchbox uses a JavaScript file on your site to provide various functions. This file contains all the logic and important information that you set up via the app in your account.


The script is made available via a CDN (Content-Delivery-Network) and thus guarantees a close position to the website visitor and thus an improvement in connectivity.


The script tag for your account can be found in your account settings.

Interface

Global variables

<!DOCTYPE html>
<html>
<head>
  <title>Bunchbox implementation sample</title>
  <script>
    window._bb = window._bb || [];
    window._bb.push([command, value]);
  </script>
  <script src="//cdn.bunchbox.co/4aa7bb5c5616ee6459a19734.min.js"></script>
</head>

<body>
The content of the document......

<script>
  window._bb = window._bb || [];
  window._bb.push([another_command, value]);
</script>
</body>
</html>

Bunchbox avoids defining unnecessary variables on the global namespace. Only the variables _bb_helpers and _bb are defined globally. The latter serves as an interface.


You can use this interface - depending on the command - before, during or after running Bunchbox.


The _bb object defines the push method.


_bb.push(array_with_commands...);


The method expects at least one array describing the command.

User-defined attributes

Visitor attributes

window._bb = window._bb || [];
window._bb.push(
    ['attribute', 'source', 'social'],
    ['attribute', 'hasNewsletter', true]
);

window._bb.push(['attribute', type, [value]])


If you have visitor attributes available, you can pass these Bunchbox before execution. You can use the attributes you provide, for example, for targeting conditions.


E-commerce attributes

window._bb = window._bb || [];
window._bb.push(
    ['ecommerce', 'orderSize', 99.99],
    ['ecommerce', 'productIds', ['id1', 'id2']],
    ['ecommerce', 'orderId', '48b7db13-a8c9-44c1-be18-5ea46e35c01f']
);

window._bb.push(['ecommerce', [type], [value]])


In order to view success metrics such as Revenue-Per-Visitor in the report, you have to give Bunchbox certain values on pages on which you can achieve defined goals. Each conversion can be assigned a purchase value orderSize, the ID of the order orderId and IDs of purchased products productIds.


Manual activation of experiments

window._bb = window._bb || [];
window._bb.push(['activate experiment', '4aa7f5d0a7a7bad33b439b9a']);

window._bb.push(['activate experiment', experimentId, [stepIndex]])


If you have created an experiment that has no targeting conditions, you can activate it manually.


Tracking of event goals

window._bb = window._bb || [];
window._bb.push(['track event goal', '4aa7f5d0a7a7bad33b439b9a', 'goalId']);

window._bb.push(['track event goal', [experimentId], goalId])


If your experiment has an event goal, you can track it with this command. The ID of the experiment is optional. If you omit these, all active experiments are taken into account. If several experiments have an event goal with the corresponding goalId, a conversion is tracked for all applicable targets.


window._bb = window._bb || [];
var link = window._bb.push(['cross domain link']);

// auf einer weiteren Domain

window._bb.push(['cross domain link', link]);

window._bb.push(['cross domain link', [linkObject]])


Bunchbox offers the possibility to serialize existing test participations of a visitor as a link object. You can then manually transfer this link to another domain in order to link both domains unidirectionally. A link has a lifetime of 30 seconds. After receiving a link object on the second domain, you can pass Bunchbox the link.


Safe Mode

window._bb = window._bb || [];
window._bb.push(['safe mode', true]);

window._bb.push(['safe mode', isSafeModeEnabled])


If you want to prevent the execution of variants on certain pages - regardless of targeting - you can ensure this with the command safe mode. This command causes no experiments to be evaluated or executed. There can therefore be no DOM manipulations on the part of the experiments. Experiment targets, on the other hand, will continue to be evaluated.


State request

window._bb = window._bb || [];
window._bb.push([
    'get state',
    function(state) {
        // read from state ...
    }
]);

window._bb.push(['get state', callback])


The get state command can be used to query the state of the current evaluation. This command can be executed at any time. The transferred callback function is executed as soon as the evaluation is completed. The evaluation includes the evaluation of user and tracking filters as well as the experimental targeting conditions, variants and goals. As soon as execution is complete, the specified callback function is executed. The first parameter is a JavaScript object. This object contains the results of the tracking filters and user filters, an overview of all previously defined user attributes and a list of any executed experiments.


{
    accountId: '4b447121b2d3c8851f61a62a',
    userId: '4b447134b2d3c8851f61a62c',
    isUserExcludedByUserFilter: false,
    isUserExcludedByTrackingFilter: false,
    customAttributes: {
        page_type: 'pdp',
        hasNewsletter: false
    },
    activeExperiments: [
        {
            experimentId: '4b44660d0206844801d8f76a',
            experimentName: 'LP Button Test',
            variantId: '4b44660d0206844801d8f783',
            variantName: 'Button Position Left',
            event: 'bb_experiment_lp_button_test_button_position_left'
        }
    ]
}

Variants

The following help functions are available within the context of a code variant.

Redirect

bb.redirect('//www.example.com/');
// oder
bb.redirect('/experiment/variante.html');

bb.redirect(url);


This function delegates the given URL or path to window.location to ensure that no further experiments are performed.


Tracking of event goals

bb.track('event goal', 'engagement');

bb.track(goalType, goalId);


With this function, the event goals defined in the experiment can be tracked. The second parameter goalId corresponds to the ID of the goal defined by you in the experiment.


Waiting for events

bb.waitUntil(
    function() {
        return !!window.$;
    },
    function() {
        $('body').css({ background: 'red' });
    },
    { forever: true }
);

bb.waitUntil(testFn, callback, [options])


Since Bunchbox is executed immediately after loading the page, it is possible that required global objects are not yet available at the time of execution. With bb.waitUntil the following execution can be delayed until the given condition is fulfilled.


Waiting for DOM elements

waitForElements

var task = bb.waitForElements(
    'ul > li',
    function(li) {
        li.textContent = li.textContent + ' New!';
    },
    {
        timeout: 5 * 1000,
        onTimeout: function() {
            alert('Timeout!');
        }
    }
);

if (maybeTrue) task.cancel();

At the time of execution of Bunchbox it is in most cases necessary to wait for required DOM elements to be able to change them. With bb.waitForElements you can wait for one or more elements to change the element as fast as possible without visual side effects for the website visitors.


bb.waitForElements(selector, callback, [options])


exists

bb.exists('h2', function(els) {
    els[0].innerHTML = 'Buy now';
});

bb.exists(
    'ul > li',
    function(els) {
        els.forEach(function(li, i) {
            li.innerHTML = i + 1 + '. Item';
        });
    },
    { forever: true, elements: 3 }
);

bb.exists(selector, callback, [options])


DOM manipulation

append

bb.waitForElements('section', function(section) {
    bb.append(section, '<h1>New category</h1>');
});

bb.append(element, htmlString)


This function allows you to add your own HTML to existing DOM elements.



prepend

bb.waitForElements('section', function(section) {
    bb.prepend(section, '<h1>New category</h1>');
});

bb.prepend(element, htmlString)


This function allows you to add your own HTML code to existing DOM elements. Unlike bb.append, the HTML is placed before the specified element.


replaceWith

bb.waitForElements('section', function(section) {
    bb.replaceWith(section, '<section>New section</section>');
});

bb.replaceWith(element, htmlString)


This function replaces an existing DOM element with new HTML.


css

bb.css('.container h2 { display: none; }');
// oder
bb.css(document.body, '.container h2 { display: none; }');

bb.css([element], styleString)


Adds a stylesheet to the page to design the DOM.


DOM Events

on

bb.on('click', function(event) {
    event.target.innerHTML += '<button>Submit</button>';
});

bb.on('mouseout', 'h2', function(event) {
    event.target.innerHTML = 'Category';
});

bb.waitForElements('h2', function(h2) {
    bb.on('mouseover', h2, function(event) {
        event.target.style.color = 'red';
    });
});

bb.waitForElements('body', function(body) {
    bb.on('click', body, 'h2', function(event) {
        event.target.style.color = 'blue';
    });
});

bb.on(event, [elements, selector], callback)


bb.on offers the appropriate functionality to listen to DOM events. The function can be used to listen to events directly at an element. The event delegation function can also be used.


off

var ids = bb.on('click', 'header', function(event) {
    bb.off(ids);
    event.target.style.backgroundColor = 'red';
});

bb.off(ids)


This function removes one or more event listeners previously registered with bb.on.


Mouse tracking

bb.mousetracking.pause();

// ...

bb.mousetracking.resume();

bb.mousetracking.pause() and bb.mousetracking.resume()


Provided that mouse tracking has been activated for the experiment, tracking for the current variant can be paused or continued using these functions.

Further Information

{
    experimentId: '4aa7e3a5a5ecf992cd77bdf9';
    experimentName: 'AB Checkout Experiment';
    stepId: '4aa7e3a5a5ecf992cd77bdfa';
    variantEvent: 'ab_checkout_experiment_original';
    variantId: '4aa7e3a5a5ecf992cd77bdfb';
    variantName: 'Original';
}

Various information can be retrieved via bb.info. This information can be used, for example, to provide data to third-party tools.


Single-page applications

Single page applications play a special role in AB testing. Unlike traditional pages, there is only an initial page load. All subsequent pages are generated dynamically without additional page load.


The implementation of Bunchbox therefore requires special attention. Bunchbox offers an interface which can be used successfully independent of the framework (e.g. ReactJS, Vue, AngularJS).

Implementation

<!DOCTYPE html>
<html>
<head>
  <title>Bunchbox SPA implementation sample</title>
  <script>
    window._bb = window._bb || [];
    window._bb.push(['auto evaluation', false]);
  </script>
  <script src="//cdn.bunchbox.co/4aa7bb5c5616ee6459a19734.min.js"></script>
</head>
<body>
The content of the document......
</body>
</html>

First, the automatic evaluation must be deactivated, since this is controlled manually in the following.

Controlling the evaluation

var routes = [
    { path: '/a-page', component: Page },
    { path: '/another-page', component: AnotherPage }
];

var router = new VueRouter({
    mode: 'history',
    routes: routes,
    base: '/'
});

_bb = window._bb || [];
router.afterEach(function(current, referrer) {
    _bb.push([
        'evaluate experiments',
        {
            attributes: {
                foo: 'bar'
            }
        }
    ]);
});

This procedure allows Bunchbox to accept the validity of certain attributes and settings. Triggering an evaluation always resets all previously defined data and settings. The newly transferred data determines the new status.

Payload

_bb = window._bb || [];
_bb.push([
    'evaluate experiments',
    {
        attributes: {
            foo: 'bar',
            bar: ['foo']
        },
        ecommerce: {
            orderSize: 99.99,
            orderId: '1e90384530c2',
            productIds: ['0d0cd94dfd74', 'bd79fc089b79']
        },
        safeMode: false
    }
]);

URL fragment based apps

_bb = window._bb || [];
_bb.push(['disable history navigation']);

If the single-page application uses URL fragments (#) to define URLs, this must be communicated to Bunchbox.

The command disable history navigation is used for this purpose.