94 lines
4.1 KiB
PHP
94 lines
4.1 KiB
PHP
<?php
|
||
// /api/linkedin-alignment-kpi.php — KPI pilotage alignment LinkedIn × Archi
|
||
// Invoqué par cron ou dashboard wiki
|
||
header("Content-Type: application/json");
|
||
|
||
$metric = $_GET["metric"] ?? "all";
|
||
$now = date("c");
|
||
|
||
// Valeurs baseline calculées à partir de lhistorique posts LinkedIn (via linkedin-posts.php)
|
||
// et de larchi live (wevia-public-status.php)
|
||
|
||
$posts = @json_decode(@file_get_contents("http://localhost/api/linkedin-posts.php"), true);
|
||
$posts_list = $posts["posts"] ?? [];
|
||
$total_posts = count($posts_list);
|
||
|
||
// 1. Posts avec chiffre-choc (détection regex : nombres > 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);
|
||
}
|