Implement academy analytics, billing, and web stories updates
This commit is contained in:
60
app/Services/Academy/AcademyPopularityService.php
Normal file
60
app/Services/Academy/AcademyPopularityService.php
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Services\Academy;
|
||||
|
||||
use App\Models\AcademyContentMetricDaily;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
final class AcademyPopularityService
|
||||
{
|
||||
/**
|
||||
* @param array<string, int|float|null> $metrics
|
||||
*/
|
||||
public function calculatePopularityScore(array $metrics): float
|
||||
{
|
||||
return round(
|
||||
((float) ($metrics['unique_visitors'] ?? 0) * 1)
|
||||
+ ((float) ($metrics['engaged_views'] ?? 0) * 3)
|
||||
+ ((float) ($metrics['likes'] ?? 0) * 5)
|
||||
+ ((float) ($metrics['saves'] ?? 0) * 7)
|
||||
+ ((float) ($metrics['prompt_copies'] ?? 0) * 8)
|
||||
+ ((float) ($metrics['negative_prompt_copies'] ?? 0) * 4)
|
||||
+ ((float) ($metrics['starts'] ?? 0) * 4)
|
||||
+ ((float) ($metrics['completions'] ?? 0) * 10)
|
||||
+ ((float) ($metrics['upgrade_clicks'] ?? 0) * 15)
|
||||
+ ((float) ($metrics['premium_preview_views'] ?? 0) * 3)
|
||||
- ((float) ($metrics['bounce_count'] ?? 0) * 2),
|
||||
2,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, int|float|null> $metrics
|
||||
*/
|
||||
public function calculateConversionScore(array $metrics): float
|
||||
{
|
||||
$uniqueVisitors = max(1, (int) ($metrics['unique_visitors'] ?? 0));
|
||||
|
||||
return round((((float) ($metrics['upgrade_clicks'] ?? 0) * 100) / $uniqueVisitors), 2);
|
||||
}
|
||||
|
||||
public function queryBetween(Carbon $from, Carbon $to): Builder
|
||||
{
|
||||
return AcademyContentMetricDaily::query()
|
||||
->whereBetween('date', [$from->toDateString(), $to->toDateString()]);
|
||||
}
|
||||
|
||||
public function topContent(Carbon $from, Carbon $to, int $limit = 10): Collection
|
||||
{
|
||||
return $this->queryBetween($from, $to)
|
||||
->selectRaw('content_type, content_id, sum(views) as views, sum(unique_visitors) as unique_visitors, sum(engaged_views) as engaged_views, sum(likes) as likes, sum(saves) as saves, sum(prompt_copies) as prompt_copies, sum(completions) as completions, sum(upgrade_clicks) as upgrade_clicks, sum(popularity_score) as popularity_score')
|
||||
->groupBy('content_type', 'content_id')
|
||||
->orderByDesc('popularity_score')
|
||||
->limit($limit)
|
||||
->get();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user