Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
455968a
Update composer.json
kawtar1993 Mar 22, 2022
ebe93bc
Update composer.json
kawtar1993 Mar 22, 2022
6768eb7
Update composer.json
kawtar1993 Mar 22, 2022
bc7b1c7
Update config.php
kawtar1993 Mar 23, 2022
9d6cd6c
Update config.php
kawtar1993 Mar 23, 2022
5c9bd83
Update AbTesting.php
kawtar1993 Mar 23, 2022
16494d9
Update InvalidConfiguration.php
kawtar1993 Mar 23, 2022
79e70bc
Update AbTesting.php
kawtar1993 Mar 23, 2022
15dea40
Update InvalidConfiguration.php
kawtar1993 Mar 23, 2022
be63544
Update AbTesting.php
kawtar1993 Mar 23, 2022
e2c94fd
Update 2019_02_02_200315_create_experiments_table.php
kawtar1993 Mar 23, 2022
da1091b
Update Experiment.php
kawtar1993 Mar 23, 2022
709765f
Update AbTesting.php
kawtar1993 Mar 23, 2022
827719c
Update AbTesting.php
kawtar1993 Mar 24, 2022
55286e0
Update AbTesting.php
kawtar1993 Mar 24, 2022
1cbf273
Update AbTesting.php
kawtar1993 Mar 24, 2022
4d4b262
Update AbTesting.php
kawtar1993 Mar 25, 2022
7158b75
Update AbTesting.php
kawtar1993 Mar 25, 2022
525187e
Update InvalidConfiguration.php
kawtar1993 Mar 25, 2022
489ebab
Update AbTesting.php
kawtar1993 Mar 25, 2022
9990b70
Update AbTesting.php
kawtar1993 Mar 25, 2022
93e7e69
Update AbTesting.php
kawtar1993 Mar 25, 2022
91dea45
Update AbTesting.php
kawtar1993 Mar 25, 2022
ce12343
Update AbTesting.php
kawtar1993 Mar 25, 2022
bca9341
Update AbTesting.php
kawtar1993 Mar 25, 2022
e1129ec
Update InvalidConfiguration.php
kawtar1993 Mar 25, 2022
05f01e3
Update InvalidConfiguration.php
kawtar1993 Mar 25, 2022
84d6a0c
Update AbTesting.php
kawtar1993 Mar 25, 2022
37d9b54
Update AbTesting.php
kawtar1993 Mar 25, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@
}
],
"require": {
"php": "^7.2 | ^8.0",
"illuminate/support": "^6.0 | ^7.0",
"php": "^8.1.1",
"illuminate/support": "^9.2",
"jaybizzle/crawler-detect": "^1.2"
},
"require-dev": {
"orchestra/testbench": "3.9.*",
"phpunit/phpunit": "^8.0 | ^9.0",
"mockery/mockery": "^1.0"
"phpunit/phpunit": "^9.0",
"mockery/mockery": "^1.3.1"
},
"autoload": {
"psr-4": {
Expand Down
22 changes: 22 additions & 0 deletions config/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,28 @@
'goals' => [],
/*
|--------------------------------------------------------------------------
| Percentage
|--------------------------------------------------------------------------
|
| Percentage by experiment.
|
| Example: [50, 50]
|
*/
'percentages' => [],
/*
|--------------------------------------------------------------------------
| Interval
|--------------------------------------------------------------------------
|
| Date interval of AB testing.
|
| Example: ['2022-03-31 00:00:00', '2022-04-30 00:00:00']
|
*/
'interval' => [],
/*
|--------------------------------------------------------------------------
| Ignore Crawlers
|--------------------------------------------------------------------------
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public function up()
$table->increments('id');
$table->string('name')->unique();
$table->integer('visitors');
$table->double('percentage');
$table->timestamps();
});
}
Expand Down
66 changes: 62 additions & 4 deletions src/AbTesting.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Ben182\AbTesting\Models\Goal;
use Illuminate\Support\Collection;
use Jaybizzle\CrawlerDetect\CrawlerDetect;
use Carbon\Carbon;

class AbTesting
{
Expand All @@ -31,6 +32,18 @@ protected function start()
{
$configExperiments = config('ab-testing.experiments');
$configGoals = config('ab-testing.goals');
$configPercentages = config('ab-testing.percentages');
$configInterval = config('ab-testing.interval');

$configPercentagesNumeric = array_filter($configPercentages, function($percentage) {
return is_numeric($percentage);
});

if (count($configPercentagesNumeric) !== count($configPercentages)) {
throw InvalidConfiguration::numericPercentages();
}

$totalPercentage = array_sum($configPercentages);

if (! count($configExperiments)) {
throw InvalidConfiguration::noExperiment();
Expand All @@ -39,15 +52,25 @@ protected function start()
if (count($configExperiments) !== count(array_unique($configExperiments))) {
throw InvalidConfiguration::experiment();
}

if ($totalPercentage !== 100) {
throw InvalidConfiguration::totalPercentage();
}

if (count($configPercentages) !== count($configExperiments)) {
throw InvalidConfiguration::percentage();
}

if (count($configGoals) !== count(array_unique($configGoals))) {
throw InvalidConfiguration::goal();
}


foreach ($configExperiments as $configExperiment) {
foreach ($configExperiments as $index => $configExperiment) {
$this->experiments[] = $experiment = Experiment::with('goals')->firstOrCreate([
'name' => $configExperiment,
], [
'percentage' => $configPercentages[$index],
'visitors' => 0,
]);

Expand All @@ -72,13 +95,25 @@ protected function start()
*/
public function pageView()
{
$configInterval = config('ab-testing.interval');

if(count($configInterval) == 1 ||
(count($configInterval) == 2 && (!Carbon::createFromFormat('Y-m-d H:i:s', $configInterval[0]) || !Carbon::createFromFormat('Y-m-d H:i:s', $configInterval[1]))) ||
(count($configInterval) == 2 && Carbon::createFromFormat('Y-m-d H:i:s', $configInterval[0])->gt(Carbon::createFromFormat('Y-m-d H:i:s', $configInterval[1])))) {
throw InvalidConfiguration::interval();
}

if (config('ab-testing.ignore_crawlers') && (new CrawlerDetect)->isCrawler()) {
return;
}

if (session(self::SESSION_KEY_EXPERIMENT)) {
return;
}

if (!empty($configInterval) && !$this->inInterval($configInterval)) {
return;
}

$this->start();
$this->setNextExperiment();
Expand All @@ -87,6 +122,19 @@ public function pageView()

return $this->getExperiment();
}

/**
* Check if the current date is in the interval
*
* @return bool
*/
protected function inInterval($interval)
{
$currentDate = Carbon::now();
$startDate = Carbon::createFromFormat('Y-m-d H:i:s', $interval[0]);
$endDate = Carbon::createFromFormat('Y-m-d H:i:s', $interval[1]);
return $currentDate->between($startDate,$endDate);
}

/**
* Calculates a new experiment and sets it to the session.
Expand All @@ -110,9 +158,19 @@ protected function setNextExperiment()
*/
protected function getNextExperiment()
{
$sorted = $this->experiments->sortBy('visitors');

return $sorted->first();
$experiments = $this->experiments->sortByDesc('percentage');

$visitorsSum = $experiments->sum('visitors');

$nextExperiment = collect([]);

if($visitorsSum != 0)
{
$nextExperiment = $experiments->filter(function($experiment) use ($visitorsSum) {
return (($experiment->visitors / $visitorsSum) * 100) < $experiment->percentage;
});
}
return !$nextExperiment->isEmpty() ? $nextExperiment->first() : $experiments->first();
}

/**
Expand Down
20 changes: 20 additions & 0 deletions src/Exceptions/InvalidConfiguration.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,24 @@ public static function goal(): self
{
return new static('The goal names should be unique.');
}

public static function percentage(): self
{
return new static('There is no percentage for every experiment');
}

public static function totalPercentage(): self
{
return new static('Total percentage should be equal to 100');
}

public static function numericPercentages(): self
{
return new static('Percentages should be numeric');
}

public static function interval(): self
{
return new static('The elements of interval array must be dates of format Y-m-d H:i:s and the first element less than the second');
}
}
1 change: 1 addition & 0 deletions src/Models/Experiment.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class Experiment extends Model
protected $fillable = [
'name',
'visitors',
'percentage',
];

protected $casts = [
Expand Down