10 ou pourcents ou K/M) $with_metric = 0; foreach ($posts_list as $p) { $txt = ($p["title"] ?? "") . " " . ($p["excerpt"] ?? ""); if (preg_match("/\d{2,}[KMk%]?|\d+\.\d+|\d+\/\d+/", $txt)) $with_metric++; } $pct_with_metric = $total_posts > 0 ? round($with_metric / $total_posts * 100, 1) : 0; // 2. Reach moyen 30j $cutoff = strtotime("-30 days"); $reach_30d = []; foreach ($posts_list as $p) { if (strtotime($p["post_date"] ?? "2020-01-01") >= $cutoff) { $reach_30d[] = intval($p["views"] ?? 0); } } $avg_reach = count($reach_30d) > 0 ? round(array_sum($reach_30d) / count($reach_30d)) : 0; // 3. Taux engagement moyen $eng_rates = []; foreach ($posts_list as $p) { $views = intval($p["views"] ?? 0); if ($views > 0) { $interactions = intval($p["likes"] ?? 0) + intval($p["comments"] ?? 0) + intval($p["reposts"] ?? 0); $eng_rates[] = $interactions / $views * 100; } } $avg_eng = count($eng_rates) > 0 ? round(array_sum($eng_rates) / count($eng_rates), 2) : 0; // 7. Claims à risque publics (regex détection: +500, 52 domaines, launch in days) $risky = 0; $risky_posts = []; foreach ($posts_list as $p) { $txt = ($p["title"] ?? "") . " " . ($p["excerpt"] ?? ""); if (preg_match("/\+500%|52 domaines|launch in days/i", $txt)) { $risky++; $risky_posts[] = $p["title"]; } } // 8. Parité corp vs LS $corp = 0; $ls = 0; foreach ($posts_list as $p) { if (($p["source"] ?? "") == "W") $corp++; elseif (($p["source"] ?? "") == "L") $ls++; } $parity = ($corp + $ls) > 0 ? round($corp / max(1, $ls), 2) : 0; // 9. Services UP publics $rt = @json_decode(@file_get_contents("http://localhost/api/realtime-status.php"), true); $up = $rt["summary"]["up"] ?? 0; $total_srv = $rt["summary"]["total"] ?? 1; $pct_up = round($up / $total_srv * 100, 1); $kpis = [ "posts_with_metric" => ["value" => $pct_with_metric, "target" => 90, "unit" => "%", "status" => $pct_with_metric >= 90 ? "OK" : "BELOW"], "avg_reach_30d" => ["value" => $avg_reach, "target" => 800, "unit" => "views", "status" => $avg_reach >= 800 ? "OK" : "BELOW"], "engagement_rate_30d" => ["value" => $avg_eng, "target" => 2.0, "unit" => "%", "status" => $avg_eng >= 2 ? "OK" : "BELOW"], "tagline_compliance" => ["value" => 0, "target" => 100, "unit" => "%", "status" => "PENDING", "note" => "Deploy V1 first"], "unique_proofs_cited" => ["value" => null, "target" => 15, "unit" => "/month", "status" => "TBD"], "linkedin_to_demo" => ["value" => null, "target" => 30, "unit" => "/month", "status" => "TBD", "note" => "Need /live-status tracking"], "risky_claims" => ["value" => $risky, "target" => 0, "unit" => "posts", "status" => $risky == 0 ? "OK" : "CRITICAL", "posts" => $risky_posts], "account_parity" => ["value" => $parity, "target_range" => [0.8, 1.2], "unit" => "ratio corp/LS", "status" => ($parity >= 0.8 && $parity <= 1.2) ? "OK" : "SKEWED"], "public_services_up" => ["value" => $pct_up, "target" => 80, "unit" => "%", "status" => $pct_up >= 80 ? "OK" : "BELOW"], "named_cases_month" => ["value" => 0, "target" => 2, "unit" => "/month", "status" => "BELOW", "note" => "No named client posts yet"] ]; if ($metric !== "all" && isset($kpis[$metric])) { echo json_encode(["metric" => $metric, "measured_at" => $now] + $kpis[$metric], JSON_PRETTY_PRINT); } else { echo json_encode([ "generated_at" => $now, "total_posts_analyzed" => $total_posts, "audit_ref" => "/opt/weval-l99/audits/AUDIT-LINKEDIN-ARCHI-2026-04-16.md", "audit_score" => 4.8, "kpis" => $kpis ], JSON_PRETTY_PRINT); }