# A/B Testing - Documentation of Murph
None

Skip to content

# 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 }