A/B Testing

Overview

Murph contains a basic tools to create A/B Tests.

The logic of the implement follows this logic:

  • A node can be configured to enable A/B Test. You also define a code to set the name of the test
  • When Murph receives a request, an event is dispatched and contains an App\Core\Ab\AbTestInterface object
  • You must create an event subscriber and set variations defined by
    • a name (a string)
    • a value (whatever you want)
    • a percentage chance (optional)
  • Then a variation is picked and saved in user cookies
  • Finally, you can retrieve the picked variation PHP side and template side

Configure the node

Go the navigation and edit the tested node:

  • Enable A/B testing
  • Define a code (eg: example_test)

The Event Subscriber

The event subscriber helps you to define each variation and the TTL.

// src/EventSubscriber/MyAbTestEventSubscriber.php

namespace App\EventSubscriber;

use App\Core\EventSubscriber\AbEventSubscriber as EventSubscriber;
use App\Core\Event\Ab\AbTestEvent;

class MyAbTestEventSubscriber extends EventSubscriber
{
    public function onInit(AbTestEvent $event)
    {
        if ($event->getTest()->getName() !== 'example_test') {
            return;
        }

        $event->getTest()
            ->addVariation('test_1', 'Value #1', 20) // 20% of chance
            ->addVariation('test_2', 'Value #2', 30) // 30% of chance
            ->addVariation('test_3', 'Value #3', 50) // 50% of chance
            ->setDuration(3600 * 24) // duration of the cookie in seconds
        ;
    }

    public function onRun(AbTestEvent $event)
    {
        // executed if a variation is newly picked
    }
}

The result

you can retrieve the test and the variation picked in PHP side and in template side.

use App\Core\Ab\AbContainerInterface;

public function foo(AbContainerInterface $testContainer)
{
    if ($testContainer->has('example_test')) {
        $test = $testContainer->get('example_test');

        $result = $test->getResult(); // eg: "test_2"
        $value = $test->getResultValue(); // eg: "Value #2"

        // ...
    }

    // ...
}
{% if ab_test_exists('example_test') %}
    {% set test = ab_test('example_test') %}
    {% set result = ab_test_result('example_test') %}
    {% set value = ab_test_value('example_test') %}

    {# ... #}
{% endif %}

Global A/B Test

If you need to perform an A/B test everywhere, you need to create a specific listener:

// src/EventListener/CustomAbListener.php

namespace App\EventListener;

use App\Core\EventListener\AbListener as EventListener;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\RequestEvent;

class CustomAbListener extends EventListener
{
    /**
     * {@inheritdoc}
     */
    protected function supports(Request $request): bool
    {
        return true;
    }

    /**
     * {@inheritdoc}
     */
    protected function getAbTestCode(): string
    {
        return 'my_global_ab_test_code';
    }
}

CustomAbListener must be registred:

# config/services.yml

services:
    # ...

    App\EventListener\CustomAbListener;
        tags:
            - { name: kernel.event_listener, event: kernel.request }
            - { name: kernel.event_listener, event: kernel.response }