Skip to content

Instantly share code, notes, and snippets.

@nielspeen
Created August 13, 2023 10:23
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nielspeen/e7911933a87d3b459a3b62c8218c6a6e to your computer and use it in GitHub Desktop.
Save nielspeen/e7911933a87d3b459a3b62c8218c6a6e to your computer and use it in GitHub Desktop.
Measure conversions using Laravel Pennant
<?php
namespace App\Services;
/*
* A thin layer on top of Laravel Pennant to track conversions.
*/
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
class ConversionService
{
/*
* Call ConversionService::migrateDatabase() once to add the converted column to the features table.
*/
public static function migrateDatabase(): void
{
Schema::table('features', function ($table) {
$table->boolean('converted')->default(false);
});
}
/*
* Call ConversionService::convert() to mark a feature as converted.
*
* Example:
* ConversionService::convert('new-frontpage', session()->getId());
*/
public static function convert(string $featureName, string $scope): void
{
DB::table('features')
->where('name', $featureName)
->where('scope', $scope)
->update([
'converted' => true,
'updated_at' => now()->toDateTimeString(),
]);
}
public static function isConverted(string $featureName, string $scope): bool
{
return DB::table('features')
->where('name', $featureName)
->where('scope', $scope)
->where(
'converted',
true
)->exists();
}
public static function getStats(string $featureName): array
{
$totalEnabled = DB::table('features')
->where('name', $featureName)
->where('value', 'true')
->count();
$totalDisabled = DB::table('features')
->where('name', $featureName)
->where('value', 'false')
->count();
$convertedWhenEnabled = DB::table('features')
->where('name', $featureName)
->where('value', 'true')
->where('converted', true)
->count();
$convertedWhenDisabled = DB::table('features')
->where('name', $featureName)
->where('value', 'false')
->where('converted', true)
->count();
$unconvertedWhenEnabled = $totalEnabled - $convertedWhenEnabled;
$unconvertedWhenDisabled = $totalDisabled - $convertedWhenDisabled;
return [
'total' => $totalEnabled + $totalDisabled,
'total_enabled' => $totalEnabled,
'total_disabled' => $totalDisabled,
'converted_when_enabled' => $convertedWhenEnabled,
'converted_when_disabled' => $convertedWhenDisabled,
'unconverted_when_enabled' => $unconvertedWhenEnabled,
'unconverted_when_disabled' => $unconvertedWhenDisabled,
'conversion_rate_when_enabled' => $totalEnabled > 0 ? $convertedWhenEnabled / $totalEnabled : null,
'conversion_rate_when_disabled' => $totalDisabled > 0 ? $convertedWhenDisabled / $totalDisabled : null,
'non_conversion_rate_when_enabled' => $totalEnabled > 0 ? $unconvertedWhenEnabled / $totalEnabled : 0,
'non_conversion_rate_when_disabled' => $totalDisabled > 0 ? $unconvertedWhenDisabled / $totalDisabled : 0,
];
}
public static function averageTimeToConversion(string $featureName): array
{
$states = ['true', 'false'];
$results = [];
foreach ($states as $state) {
$convertedRecords = DB::table('features')
->where('name', $featureName)
->where('value', $state)
->where('converted', true)
->get(['created_at', 'updated_at']);
$totalTime = 0;
foreach ($convertedRecords as $record) {
$createdTime = strtotime($record->created_at);
$updatedTime = strtotime($record->updated_at);
$totalTime += ($updatedTime - $createdTime);
}
$averageSeconds = count($convertedRecords) > 0 ? $totalTime / count($convertedRecords) : 0;
$averageTime = gmdate("H:i:s", $averageSeconds);
$results[$state === 'true' ? 'enabled' : 'disabled'] = $averageTime;
}
return $results;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment