trypost/app/Services/Social/FacebookAnalytics.php
Paulo Castellano a8bb44f0e5 fix: self-host billing bypass, Facebook API metrics migration, X token refresh, and duplicate social accounts
- Block all billing/usage/subscribe routes in self-hosted mode (redirect to calendar)
- Hide billing_email field in account settings when self-hosted
- Migrate deprecated Facebook Page Insights metrics to new Media Views API (v25.0)
- Fix X analytics token refresh to use Basic Auth (matching XPublisher/ConnectionVerifier)
- Prevent duplicate social accounts by using updateOrCreate across all OAuth controllers
2026-04-15 09:46:18 -03:00

88 lines
2.8 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Services\Social;
use App\Models\SocialAccount;
use App\Services\Social\Concerns\HasSocialHttpClient;
use Carbon\CarbonInterface;
use Illuminate\Http\Client\PendingRequest;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
class FacebookAnalytics
{
use HasSocialHttpClient;
private string $baseUrl = 'https://graph.facebook.com/v25.0';
private string $accessToken;
public function getMetrics(SocialAccount $account, ?CarbonInterface $since = null, ?CarbonInterface $until = null): array
{
$since ??= now()->subDays(7);
$until ??= now();
$cacheKey = "analytics:facebook:{$account->id}:{$since->format('Y-m-d')}:{$until->format('Y-m-d')}";
$cacheTtl = app()->isProduction() ? 3600 : 1;
return Cache::remember($cacheKey, $cacheTtl, function () use ($account, $since, $until) {
return $this->fetchMetricsFromApi($account, $since, $until);
});
}
private function fetchMetricsFromApi(SocialAccount $account, CarbonInterface $since, CarbonInterface $until): array
{
$this->accessToken = $account->access_token;
$response = $this->getHttpClient()
->get("{$this->baseUrl}/{$account->platform_user_id}/insights", [
'metric' => 'page_total_media_view_unique,post_total_media_view_unique,page_post_engagements,page_daily_follows,page_media_view',
'period' => 'day',
'since' => $since->startOfDay()->unix(),
'until' => $until->endOfDay()->unix(),
'access_token' => $this->accessToken,
]);
if ($response->failed()) {
Log::warning('Facebook page insights fetch failed', [
'body' => $this->redactResponseBody($response->body()),
]);
return [];
}
$data = data_get($response->json(), 'data', []);
$metrics = [];
foreach ($data as $metric) {
$name = data_get($metric, 'name');
$values = data_get($metric, 'values', []);
if (empty($values)) {
continue;
}
$total = collect($values)->sum('value');
$label = match ($name) {
'page_total_media_view_unique' => 'Page Reach',
'post_total_media_view_unique' => 'Posts Reach',
'page_post_engagements' => 'Posts Engagement',
'page_daily_follows' => 'Page Followers',
'page_media_view' => 'Page Views',
default => ucfirst(str_replace('_', ' ', $name)),
};
$metrics[] = ['label' => $label, 'value' => $total];
}
return $metrics;
}
private function getHttpClient(): PendingRequest
{
return $this->socialHttp();
}
}