Implementierung

<!DOCTYPE html>
<html>
<head>
  <title>Bunchbox implementation sample</title>
  <script src="//cdn.bunchbox.co/4aa7bb5c5616ee6459a19734.min.js" referrerpolicy="no-referrer-when-downgrade"></script>
</head>

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

Bunchbox nutzt eine JavaScript-Datei auf Ihrer Seite, um diverse Funktionen bereitzustellen. Diese Datei umfasst die gesamte Logik und zudem wichtige Informationen, die Sie über die App in Ihrem Account einrichten.


Das Skript wird über ein CDN (Content-Delivery-Network) zur Verfügung gestellt und garantiert damit eine nahe Position zum Webseitenbesucher und somit eine Verbesserung der Konnektivität.


Das Skript-Tag zu Ihrem Account finden Sie in den Einstellungen Ihres Accounts.

Schnittstelle

Globale Variablen

<!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" referrerpolicy="no-referrer-when-downgrade"></script>
</head>

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

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

Bunchbox vermeidet unnötige Variablen am globalen Namespace zu definieren. Es werden ausschließlich die Variablen _bb_helpers und _bb global definiert. Letzteres dient Ihnen als Schnittstelle.


Sie können diese Schnittstelle - abhängig vom Befehl - vor, während oder nach der Ausführung von Bunchbox verwenden.


Das _bb Objekt definiert die push Methode.


_bb.push(array_with_commands...);


Die Methode erwartet mindestens ein Array, welches den Befehl beschreibt.

Benutzerdefinierte Attribute

Besucher-Attribute

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

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


Stehen Ihnen Besucher-Attribute zur Verfügung, können Sie diese Bunchbox vor der Ausführung übergeben. Die von Ihnen zur Verfügung gestellten Attribute können Sie z.B. für Targeting-Bedingungen nutzen.


Ecommerce-Attribute

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]])


Um Erfolgsmetriken wie z.B. Revenue-Per-Visitor im Report einsehen zu können, müssen Sie uns auf Seiten, auf denen von Ihnen definierte Ziele erreicht werden können, bestimmte Werte übergeben. Jeder Conversion kann ein Kaufwert orderSize, die ID der Bestellung orderId und IDs gekaufter Produkte productIds zugeordnet werden.


Manuelle Experiment-Aktivierung

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

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


Haben Sie ein Experiment erstellt, welches keine Targeting-Bedingungen besitzt, können Sie dieses manuell aktivieren.


Tracking von Ereignis-Zielen

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

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


Besitzt Ihr Experiment ein Ereignis-Ziel, können Sie dies mit diesem Befehl tracken. Die ID des Experiments ist hierbei optional. Lassen Sie diese weg, werden alle aktiven Experimente in Betracht gezogen. Besitzen mehrere Experimente ein Ereignis-Ziel mit der entsprechenden goalId, werden für alle zutreffenden Ziele eine Conversion getracked.


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 bietet die Möglichkeit, bestehenden Test-Teilnahmen eines Besuchers als Link-Objekt zu serialisieren. Diesen Link können Sie anschließend auf eine weitere Domain manuell übertragen, um so beide Domains unidirektional zu verlinken. Ein Link hat eine Lebensdauer von 30 Sekunden.


Nach Empfang eines Link-Objektes auf der zweiten Domain, können Sie den Link Bunchbox übergeben.


Abgesicherter Modus

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

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


Möchte man auf bestimmten Seiten die Ausführung von Varianten - unabhängig vom Targeting - verhindern, kann dies über den Befehl safe mode sichergestellt werden. Dieser Befehl führt dazu, dass keine Experimente evaluiert bzw. ausgeführt werden. Es kann somit zu keinen DOM-Manipulationen seitens der Experimente kommen. Experiment-Ziele werden hingegen weiterhin ausgewertet.



window._bb = window._bb || [];
window._bb.push(['consent', false]);

window._bb.push(['consent', hasUserGivenNecessaryConsent])


Bunchbox bietet die Möglichkeit, Cookie-Consent-konform zu arbeiten und dennoch ein optimales Testing-Ergebnis zu erzielen. Über den Befehl consent kann Bunchbox mitgeteilt werden, ob zum aktuellen Zeitpunkt eine Zustimmung des Besuchers vorliegt. Auch ohne Consent werden weiterhin Experimente gestartet und Conversion erkannt. Sie werden aber erst an Bunchbox zurück übermittelt, sobald der Besucher den Consent gegeben hat und Bunchbox darüber informiert wurde.

Wenn beim erstmaligen Öffnen der Seite der Besucher noch keinen Consent gegeben hat, wird empfohlen, vor dem Laden von Bunchbox false als Consent-Status zu übergeben. Sobald der Besucher der Nutzung von Bunchbox zugestimt hat, wird der consent-Befehl erneut mit true aufgerufen. Erst dann wird mögliches Tracking von Bunchbox abgeschickt.

Ohne den Consent-Befehl nimmt Bunchbox, wie bisher auch, an, dass kein Consent erforderlich ist.



Status-Abfrage

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

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


Um den Status der aktuellen Evaluierung abfragen zu können, kann der Befehl get state verwendet werden. Dieser Befehl kann zu jedem Zeitpunkt ausgeführt werden. Die übergebene Callback-Funktion wird ausgeführt, sobald die Evaluierung abgeschlossen ist. Die Evaluierung umfasst neben der Auswertung von User- und Tracking-Filtern, auch die der Experiment-Targeting-Bedingungen, Varianten und Zielen. Sobald die Ausführung abgeschlossen ist, wird die angegebene Callback-Funktion ausgeführt. Als ersten Parameter erhält diese ein JavaScript-Objekt. Dieses Objekt enthält neben den Ergebnissen der Tracking- und User-Filter, auch eine Übersicht über alle zuvor definierten Benutzer-Attribute und eine Liste von eventuell ausgeführten Experimenten.


{
    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'
        }
    ]
}

Flackern verhindern

window._bb = window._bb || [];
window._bb.push(['prevent flickering']);

window._bb.push(['prevent flickering', options])


Es gibt einige Situationen, in denen das Bunchbox JavaScript asynchron ausgeführt wird. In diesen Fällen kann eine Originalvariante sichtbar sein, bevor visuelle Änderungen durch die tatsächlich asynchron ausgeführte Variante vorgenommen werden. Dieser Befehl veranlasst das JavaScript, dem Dokumentelement eine CSS-Klasse hinzuzufügen. Die CSS-Klasse wird verwendet, um die Deckkraft der gesamten Seite auf Null zu setzen. Nach Ausführung des JavaScripts, wird die Klasse wieder entfernt, so dass der Besucher durch springende Elemente nicht beeinträchtigt wird.

Sofern nicht anders konfiguriert, ist bb-async-hide der erwartete Klassenname. Sie sollten sicherstellen, dass diese Klasse definiert ist, bevor das Bunchbox-JavaScript ausgeführt wird.

Wenn Sie bereits eine Klasse haben, die es dir erlaubt, die Deckkraft auf Null zu setzen, können Sie uns dies mit { className: 'my-custom-hide-class' } als zweiten Parameter mitteilen.

<!DOCTYPE html>
<html>
  <head>
    <title>Bunchbox implementation sample</title>
    <style>
      .prevent-flickering {
        opacity: 0 !important;
      }
    </style>
    <script>
      window._bb = window._bb || [];
      window._bb.push([
        'prevent flickering',
        { className: 'prevent-flickering' }
      ]);
    </script>
    <script src="//cdn.bunchbox.co/4aa7bb5c5616ee6459a19734.min.js" referrerpolicy="no-referrer-when-downgrade"></script>
  </head>

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

Flackern verhindern bei asynchroner Implementierung

<!DOCTYPE html>
<html>
  <head>
    <title>Bunchbox implementation sample</title>
    <style>
      .bb-async-hide {
        opacity: 0 !important;
      }
    </style>
    <script>
      /**
       * @param {Window} b The global object.
       * @param {HTMLDocument} e The document.
       * @param {HTMLHtmlElement} c The html element.
       * @param {string} d The name of property of the global Bunchbox object.
       * @param {string} h The account id used to load the Bunchbox script.
       * @param {string} g The class name used to hide the page
       * @param {number} a The maximium timeout in ms used as fallback
       */
      (function(b, e, c, d, h, g, a) {
        b[d] = b[d] || [];
        var f = b[d].show = function() {
          c.className = c.className.replace(RegExp(" ?" + g), "");
          f = b[d].show = function() {};
        };
        b.setTimeout(function() {
          f();
        }, a);
        c.className += " " + g;
        a = e.createElement("script");
        a.async = !0;
        a.src = "//cdn.bunchbox.co/" + h + ".min.js";
        a.onerror = function() {
          f();
        };
        (e.head || e.getElementsByTagName("head")[0]).appendChild(a);
      })(window, document, document.documentElement, "_bb", "539dd741b822cc631f000003", "bb-async-hide", 2000);
    </script>
  </head>
  <body>
    The content of the document......
  </body>
</html>

Wenn Sie Bunchbox asynchron laden wollen, können Sie dies mit diesem Skript tun. Das Skript lädt nicht nur Bunchbox, sondern verhindert auch potenzielles Flackern. Flackern kann auftreten, wenn der Standardseiteninhalt gerendert wird, bevor Bunchbox die visuellen Änderungen einer oder mehrere Varianten auf die aktuelle Webseite anwendet. Um dies zu verhindern, blendet dieses Snippet die Seite mit einer vordefinierten CSS-Klasse aus. Die Klasse wird dem Dokumentelement hinzugefügt und nach erfolgreichem Laden entfernt. Wenn Bunchbox-Ressourcen durch den aktuellen Browser blockiert werden, wird die Seite sofort wieder angezeigt. Darüber hinaus stellt das Snippet sicher, dass die Seite nie länger als das angegebene maximale Timeout verborgen bleibt.

Sofern nicht anders konfiguriert, ist bb-async-hide der erwartete Klassenname. Sie sollten sicherstellen, dass diese Klasse definiert ist, bevor das Bunchbox-JavaScript ausgeführt wird. Beachten sie außerdem dass 539dd741b822cc631f000003 eine Beispiel-Account-Id darstellt, welche Sie mit der ID ihres Accounts ersetzen müssen.

Wenn Sie bereits eine Klasse haben, die es dir erlaubt, die Deckkraft auf Null zu setzen, können Sie uns dies mitteilen indem statt 'bb-async-hide' eine andere Klasse angegeben wird. Ähnlich wie die CSS-Klasse kann auch der maximale Timeout konifguiert werden.

Varianten

Folgende Hilfsfunktionen stehen Ihnen innerhalb des Kontextes einer Code-Variante zur Verfügung.

Weiterleitung

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

bb.redirect(url);


Diese Funktion delegiert die übergebene URL oder den Pfad an window.location und stellt so sicher, dass keine weiteren Experimente ausgeführt werden.


Tracken von Ereignis-Zielen

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

bb.track(goalType, goalId);


Mit dieser Funktion können die im Experiment definierten Ereignis-Ziele getracked werden. Der zweite Parameter goalId entspricht dabei der von Ihnen im Experiment definierten ID des Ziels.


Auf Ereignisse warten

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

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


Da Bunchbox unmittelbar nach dem Laden der Seite ausgeführt wird, ist es möglich, dass benötigte globale Objekte zum Ausführungszeitpunkt noch nicht verfügbar sind. Mit bb.waitUntil kann die nachfolgende Ausführung verzögert werden, bis die gegebene Bedingung erfüllt ist.


Auf DOM Elemente warten

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();

Zum Zeitpunkt der Ausführung von Bunchbox ist es in den meisten Fällen nötig auf benötigte DOM-Elemente zu warten, um sie verändern zu können. Mit bb.waitForElements kann auf ein oder mehrere Elemente gewartet werden, um so schnellstmöglich das Element ohne visuelle Nebeneffekte für den Webseitenbesuchern zu verändern.


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)


Diese Funktion erlaubt das Hinzufügen von eigenem HTML an bestehende DOM-Elemente.


prepend

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

bb.prepend(element, htmlString)


Diese Funktion erlaubt das Hinzufügen von eigenem HTML Code an bestehende DOM-Elemente. Das HTML wird dabei anders als bei bb.append vor dem angegebenen Element platziert.


replaceWith

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

bb.replaceWith(element, htmlString)


Diese Funktion ersetzt ein bestehendes DOM-Elemente mit neuem HTML.


css

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

bb.css([element], styleString)


Fügt ein Stylesheet zur Seite hinzu um das DOM zu gestalten.


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)


Um auf DOM-Events lauschen zu können, bietet bb.on die geeignete Funktionalität. Die Funktion kann benutzt werden um auf Events direkt an einem Element zu lauschen. Darüber hinaus kann die Funktion zur Event-Delegation genutzt werden.


off

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

bb.off(ids)


Diese Funktion entfernt einen oder mehrere zuvor mittels bb.on angemeldete Event-Listener.


Mousetracking

bb.mousetracking.pause();

// ...

bb.mousetracking.resume();

bb.mousetracking.pause() und bb.mousetracking.resume()


Vorausgesetzt, für das Experiment wurde Mousetracking aktiviert, können über diese Funktionen das Tracking für die aktuelle Variante pausiert als auch fortgesetzt werden.

Weitere Information

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

Über bb.info können diverse Informationen abgerufen werden. Diese können beispielsweise genutzt werden, um Daten Drittanbieter-Tools zur Verfügung zu stellen.


Single-Page-Applications

Single-Page-Applications nehmen im Bereich des AB-Testings eine besondere Rolle ein. Anders als bei traditionellen Seiten, gibt es nur einen initialen Page-Load. Alle Folgeseiten werden dynamisch ohne zusätzlichen Page-Load erzeugt.


Die Implementierung von Bunchbox benötigt deshalb besonders Aufmerksamkeit. Bunchbox bietet hierzu eine Schnittstelle, welche unabhängig vom Framework (z.B. ReactJS, Vue, AngularJS) erfolgreich genutzt werden kann.

Implementierung

<!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" referrerpolicy="no-referrer-when-downgrade"></script>
</head>
<body>
The content of the document......
</body>
</html>

Zunächst muss die automatische Evaluierung deaktiviert werden, da dies im Folgenden manuell gesteuert wird.

Steuern der 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'
            }
        }
    ]);
});

Durch dieses Vorgehen kann Bunchbox die Gültigkeit bestimmter Attribute und Einstellungen annehmen. Das Anstoßen einer Evaluation führt immer dazu, dass alle zuvor definierten Daten und Einstellungen zurückgesetzt werden. Die neu übergebenen Daten bestimmen den neuen Stand.

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 basierte Apps

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

Nutzt die Single-Page-Application URL-Fragmente (#) zur Definition von URLs, muss dies Bunchbox mitgeteilt werden. Hierfür dient der Befehl disable history navigation.

Varianten

Varianten für Single-Page-Applications verlangen oft mehr Aufmerksamkeit als ihr Pendant auf herkömmlichen Webseiten. Bunchbox führt Varianten lediglich aus, kann Code-Ausführungen aber nicht rückgängig machen. Damit eine Variante mehrmals hintereinander ausgeführt werden kann und immer das gleiche Ergebnis zur Folge hat, kann auf ein bestimmtes Ereignis gelauscht werden. Hierzu stellt Bunchbox einen Event-Emitter bereit, welcher innerhalb des Varianten-Codes genutzt werden kann. Der Event-Emitter kann zudem genutzt werden um mit anderen Varianten zu kommunizieren.

const ee = bb.getEventEmitter();

const handler = () => console.log('React to custom event');

ee.on('custom:event', handler);

ee.emit('custom:event', 'I am the payload');
ee.off('custom:event', handler);

ee.once('custom:event:2', () => console.log('React to another custom event'));

Um innerhalb des Varianten-Codes herauszufinden, wann Bunchbox erneut evaluiert wird, können Sie auf das Ereignis reset lauschen. Dieses Ereignis wird immer vor einer nachfolgenden Bunchbox-Evaluierung ausgelöst. Das Ereignis kann somit dazu verwendet werden, Änderungen einer Variante rückgängig zu machen, bevor sie erneut ausgeführt wird.


Ereignisse können zudem von der "Außenwelt" ausgelöst werden. Hierzu kann folgender Befehl verwendet werden.

window._bb = window._bb || [];
window._bb.push(['emit', 'custom:event', 'I am the payload', 'Me too!']);

bb.getEventEmitter();


Diese Funktion gibt einen EventEmitter zurück. Dieser EventEmitter stellt wiederum die Funktionen on, once, off und emit zur Verfügung.


ee.on(event, handler);



ee.once(event, handler);



ee.off(event, handler);



ee.emit(event, handler);