Running non-blocking A/B tests, feature flags with Laravel, PHP
Tags: abtest, featureflags, laravel, php
Published: 2022-06-24 12:46:54

![Illustration of nothing](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/43xfr7drq07jyj0hkpux.png)
 

 Hey guys. My name is Alex. I'm a software engineer in unicorn by day and the founder of a couple of SaaS projects by night (and evening sometimes). From Ukraine, now living in Porto.


![Author photo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xljzxn4ghmnlfpmfg5zd.jpg)

## Introduction

This story is about the ABRouter - new open-source platform for running A/B tests, feature flags, and collecting statistics on the back-end side with the high level of support of Laravel, PHP, and Symfony. 

Additionally, that tool supports Parallel Running - built-in mode that allows using the features in non-blocking mode. All that you need to do - is configure the queues and Redis on your project. Unfortunately, this mode is not supported for Symfony now, but you can help us implement it (because the tool is open-source).

As I said, the tool is fully open-source, and I have almost nothing to sell, except for the cloud version, hah :) 


## Our first task with A/B test

So, I propose to start implementing first A/B test with a simple example - testing the most convertible color of the checkout button. For example, your current color of the sign-up button is blue, but you want to check, what if the green button will be more convertible?

Goal: To test the most convertible color of the form button
Branches distribution: red - 33%, green - 33%, blue - 33%.
Technical task: assign the color of the button: which the user got into.

### Creating the first A/B test on the ABR side


#### Step 1
Sign-up by the [link](https://abrouter.com/en/signup)

> Please, note you can deploy ABRouter locally or on your remote server.
[learn more about deploying](https://github.com/abrouter/abrouter)

#### Step 2
Create your experiment

Pay attention to the Experiment ID. You will use it as the identifier of the experiment to run it.


![Create experiment](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9w1u3zetdqiiwo5cvytk.png) 



#### Step 3
Grab the data
After creating the A/B test you can get the important data to run it.
Experiment id:
![Grab Experiment id:](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/im5xh04j5211kkp2394j.png)
 

Token:
![Grab token](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bt27nagyzwct0o9x96hv.png)
 

## Configure application side

### If you're using Laravel: 

Install the library to your codebase on PHP:https://github.com/abrouter/laravel-abtest

This library is based on the main ABRouter client:https://github.com/abrouter/abrouter-php-client

`composer requires abrouter/laravel-abtest
`
This package provides auto-discovery for the service provider. If Laravel package auto-discovery is disabled, add service providers manually in your /app/app.php of your repository.
There are service providers you must add:
\Abrouter\LaravelClient\Providers\AbrouterServiceProvider::class

Publish client configuration:
`php artisan vendor:publish --tag=abrouter
`
Configure the client:

```
<?php
declare(strict_types = 1);

return [
    'token' => '0ea94e3527644b8e6259b790d866223490f3c91634bbfd0eb978b4a57a4d835d57ab5195f892b15d',
    'host' => 'https://abrouter.com',
];

```


### If you're using vanilla PHP: 

`composer require abrouter/abrouter-php-client`

[abrouter/abrouter-php-client repository on Github](https://github.com/abrouter/abrouter-php-client) 

Please, visit the repository for configuration instructions. The package wouldn't work without DI. So, if you're not using DI yet, try [PHP-DI](https://php-di.org/).


### If you're using Symfony:

#### Install the library to your codebase on PHP:
https://github.com/abrouter/symfony-abtest

`composer require abrouter/symfony-abtest`

#### Register the bundle:
```
// config/bundles.php
return [
// [...]
Abrouter\SymfonyClient\AbrouterClientBundle::class => ['all' => true],
];
```


#### Put your ABRouter token in /config/packages/abrouter_client.yaml

```
abrouter_client:
  token:                ''
  host:                 'https://abrouter.com'
```

### Common recommendations
Feel free to learn additional details in the repositories of framework you're using. If you want to configure Parallel(non-blocking) running please read package instructions.


## Start coding A/B test

### If you're using Laravel: 

```
<?php

use Abrouter\Client\Builders\StatEventBuilder;
use Abrouter\Client\Client;

class ExampleController
{
    public function __invoke(Client $client, StatEventBuilder $statEventBuilder)
    {
        $userId = auth()->user()->id;
        $buttonColor = $client->experiments()->run($userId, 'button_color_test');

        //send the statistics
        $client->statistics()->sendEvent(
            $eventBuilder
                ->incremental()
                ->event('button_test_visit')
                ->setUserId($userId)
                ->build()
        );
        

        return view('button', [
            'color' => $buttonColor->getBranchId(),
        ]);
    }
}
```

Additionally, check out the example for Laravel [https://github.com/abrouter/laravel-example](https://github.com/abrouter/laravel-example)


### If you're using vanilla PHP: 

```
<?php

use Abrouter\Client\Config\Config;
use DI\ContainerBuilder;
use Abrouter\Client\Client;

require '/app/vendor/autoload.php';

$containerBuilder = new ContainerBuilder();
$di = $containerBuilder->build();

$token = '04890788ba2c89c4ff21668c60838a00a87b1cf42c9c6b45d6aa8e11174f0d5762b16b6c09b6b822'; //you can find your token in ABRouter dashboard

$di->set(Config::class, new Config($token, 'https://abrouter.com'));
/**
 * @var Client $client
 */
$client = $di->make(Abrouter\Client\Client::class);

$statBuilder = $di->make(Abrouter\Client\Builders\StatEventBuilder);

$userSignature = $_SESSION['user_id'] ?? uniqid();
$experimentId = 'button_color_test';//experiment id is also there


$runExperimentResult = $client->experiments()->run($userSignature, $experimentId);

//sending button_test_page_visit event as button_test_page_visit+1
$client->statistics()->sendEvent(
     $eventBuilder
        ->incremental()
        ->event('button_test_visit')
        ->setUserId($userId)
        ->build()
);


$experimentId = $runExperimentResult->getExperimentId(); //form-color
$branchId = $runExperimentResult->getBranchId(); //red
echo '<button style="color: '. $branchId .'">Hello</button>';
```

### If you're using Symfony: 

```
<?php

namespace App\Controller;

use Abrouter\Client\Client;
use Abrouter\Client\Manager\ExperimentManager;
use Symfony\Component\HttpFoundation\Response;
use Abrouter\Client\Builders\StatEventBuilder;

class IndexController
{
    public function index(Client $client, StatEventBuilder $statBuilder)
    {
        $userId = $this->getUser()->getUsername();

        //sending button_test_page_visit event as button_test_page_visit+1
        $client->statistics()->sendEvent(
             $eventBuilder
                ->incremental()
                ->event('button_test_visit')
                ->setUserId($userId)
                ->build()
         );


        /**
         * The button color will be changed 50% green/50% red
         */
        $buttonColorExperimentId = 'button_color_test';
        return new Response(json_encode([
            'button_color' => $client
                ->experiments()
                ->run($userId, $buttonColorExperimentId)->getBranchId(),
        ]));
    }
}
```

Additionally, check out the example for symfony [https://github.com/abrouter/symfony-abtest-example](https://github.com/abrouter/symfony-abtest-example)


## Results variations of A/B test

Color of the button will be automatically changed on each request for every page reload. Because we have used uniqid(). ABRouter system will memorize the relation between user identifier and branch he got, so if we will repeat the request with the same user identifier we will get the same branch as on previous run.

![Results of A/B testing](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uwhm6fe1jbp8zmnc8brj.png)
 
## Tracking

Feel free to send the statistics to the ABRouter server. The product support showing statistics by experiment and over all. Learn more about the statistics in the [docs](https://docs.abrouter.com).

## Running feature flag example

Running feature flag is a kind common for all platforms. Let's see how to do it with Laravel: 

```
<?php
declare(strict_types = 1);

namespace App\Http\Controllers;

use Abrouter\Client\Client;

class ExampleFeatureFlagsController
{
    public function __invoke(Client $client)
    {
        $enabledButtonFeatureFlag = $client->featureFlags()
            ->run('enabled_button_feature_flag');
        $disabledButtonFeatureFlag = $client->featureFlags()
            ->run('disabled_button_feature_flag');

        return view(
          'featureFlags',
          [
            'enabledButtonFeatureFlag' => $enabledButtonFeatureFlag,
            'disabledButtonFeatureFlag' => $disabledButtonFeatureFlag,
          ]
        );
    }
}
```


##Useful links 

[Deploy ABRouter locally or on the remote server](https://github.com/abrouter/abrouter)
[Running feature flags](https://abrouter.com/en/laravel-feature-flags)
[Laravel client GitHub](https://github.com/abrouter/laravel-abtest) - includes full instructions for running on Laravel
[PHP client GitHub](https://github.com/abrouter/abrouter-php-client) - includes full instructions for running on PHP
[Symfony client GitHub](https://abrouter.com/en/symfony-ab-tests) - includes full instructions for running on PHP
[ABRouter website](https://abrouter.com/)

## Summary

I have shown you how to implement an A/B test, feature flags and send the statistics with Laravel, Symfony and PHP via ABRouter. Looks like it's quite simple.
Please, remember, that every change that you are making to the app should be through an A/B test. It's a key to build a successful product.

If you have any questions, feel free to ask me at abrouter@proxiedmail.com

Thank you for reading.