| @@ -16,9 +16,8 @@ | ||
| 16 | 16 | |
| 17 | 17 | namespace ThinkRank\SEO; |
| 18 | 18 | |
| 19 | 19 | use ThinkRank\Core\Settings_Manager; |
| 20 | -use ThinkRank\Core\Plan_Config; | |
| 21 | 20 | use ThinkRank\Integrations\Google_Analytics_Client; |
| 22 | 21 | use ThinkRank\Integrations\Google_Search_Console_Client; |
| 23 | 22 | use ThinkRank\Integrations\Google_PageSpeed_Client; |
| 24 | 23 | use ThinkRank\Integrations\Google_Search_Analytics_Client; |
| @@ -711,10 +710,8 @@ | ||
| 711 | 710 | // 401s are re-thrown so the token-refresh retry below runs. |
| 712 | 711 | if ($this->analytics_client) { |
| 713 | 712 | try { |
| 714 | 713 | $dashboard_data['traffic'] = $this->analytics_client->get_traffic_data($date_range); |
| 715 | - $dashboard_data['organic_traffic'] = $this->analytics_client->get_organic_traffic($date_range); | |
| 716 | - $dashboard_data['top_pages'] = $this->analytics_client->get_top_pages(10, $date_range); | |
| 717 | 714 | } catch (\Exception $ga_error) { |
| 718 | 715 | if ($ga_error->getCode() === 401) { |
| 719 | 716 | throw $ga_error; |
| 720 | 717 | } |
| @@ -772,10 +769,8 @@ | ||
| 772 | 769 | $dashboard_data['search_performance'] = array_merge($search_performance, [ |
| 773 | 770 | 'totals' => $totals, |
| 774 | 771 | 'position_distribution' => $position_distribution |
| 775 | 772 | ]); |
| 776 | - | |
| 777 | - $dashboard_data['page_performance'] = $this->search_console_client->get_page_performance($site_url, $date_range, 10); | |
| 778 | 773 | } // Closing Search Console block |
| 779 | 774 | |
| 780 | 775 | // If successful, break loop |
| 781 | 776 | break; |
| @@ -973,44 +968,8 @@ | ||
| 973 | 968 | } |
| 974 | 969 | } |
| 975 | 970 | |
| 976 | 971 | /** |
| 977 | - * Get site indexing status | |
| 978 | - * | |
| 979 | - * @return array Indexing status data | |
| 980 | - */ | |
| 981 | - public function get_indexing_status(): array { | |
| 982 | - $cache_key = 'indexing_status'; | |
| 983 | - $cached_data = get_transient($cache_key); | |
| 984 | - | |
| 985 | - if ($cached_data !== false) { | |
| 986 | - return $cached_data; | |
| 987 | - } | |
| 988 | - | |
| 989 | - $indexing_data = [ | |
| 990 | - 'status' => 'unknown', | |
| 991 | - 'last_updated' => current_time('mysql') | |
| 992 | - ]; | |
| 993 | - | |
| 994 | - try { | |
| 995 | - if ($this->search_console_client) { | |
| 996 | - $site_url = $this->get_setting('search_console_property', get_site_url()); | |
| 997 | - $indexing_data = $this->search_console_client->get_indexing_status($site_url); | |
| 998 | - } | |
| 999 | - } catch (\Exception $e) { | |
| 1000 | - $indexing_data['error'] = $e->getMessage(); | |
| 1001 | - } | |
| 1002 | - | |
| 1003 | - // Cache successful results for 1 hour. Errors are never cached, so a | |
| 1004 | - // transient Google failure isn't served as "no data" for a full hour. | |
| 1005 | - if (empty($indexing_data['error'])) { | |
| 1006 | - set_transient($cache_key, $indexing_data, 3600); | |
| 1007 | - } | |
| 1008 | - | |
| 1009 | - return $indexing_data; | |
| 1010 | - } | |
| 1011 | - | |
| 1012 | - /** | |
| 1013 | 972 | * Force refresh of all cached data |
| 1014 | 973 | * |
| 1015 | 974 | * @return array Refresh results |
| 1016 | 975 | */ |
| @@ -1027,11 +986,8 @@ | ||
| 1027 | 986 | 'analytics_dashboard_v5_180d', |
| 1028 | 987 | 'seo_opportunities_7d', |
| 1029 | 988 | 'seo_opportunities_30d', |
| 1030 | 989 | 'seo_opportunities_90d', |
| 1031 | - 'seo_insights_7d', | |
| 1032 | - 'seo_insights_30d', | |
| 1033 | - 'seo_insights_90d', | |
| 1034 | 990 | 'indexing_status', |
| 1035 | 991 | 'thinkrank_dashboard_cwv' |
| 1036 | 992 | ]; |
| 1037 | 993 | |
| @@ -1099,411 +1055,6 @@ | ||
| 1099 | 1055 | */ |
| 1100 | 1056 | public function cleanup_cache(): void { |
| 1101 | 1057 | // WordPress handles transient cleanup automatically |
| 1102 | 1058 | // This method is for future custom cache cleanup if needed |
| 1103 | - } | |
| 1104 | - | |
| 1105 | - // ======================================== | |
| 1106 | - // SEO Intelligence Enhancement Methods | |
| 1107 | - // ======================================== | |
| 1108 | - | |
| 1109 | - /** | |
| 1110 | - * Get intelligent dashboard data with trends and insights | |
| 1111 | - * | |
| 1112 | - * @param string $date_range Date range for analysis | |
| 1113 | - * @return array Enhanced dashboard data with intelligence | |
| 1114 | - */ | |
| 1115 | - public function get_intelligent_dashboard_data(string $date_range = '30d'): array { | |
| 1116 | - // Get base dashboard data | |
| 1117 | - $dashboard_data = $this->get_dashboard_data($date_range); | |
| 1118 | - | |
| 1119 | - // Check if there's an error in the data | |
| 1120 | - if (isset($dashboard_data['error'])) { | |
| 1121 | - return [ | |
| 1122 | - 'success' => false, | |
| 1123 | - 'data' => null, | |
| 1124 | - 'message' => 'Failed to retrieve dashboard data: ' . $dashboard_data['error'], | |
| 1125 | - 'timestamp' => current_time('mysql') | |
| 1126 | - ]; | |
| 1127 | - } | |
| 1128 | - | |
| 1129 | - // Check if we have real data available | |
| 1130 | - if (!$this->has_real_data($dashboard_data)) { | |
| 1131 | - return [ | |
| 1132 | - 'success' => false, | |
| 1133 | - 'data' => null, | |
| 1134 | - 'message' => 'No analytics data available yet. Please ensure your Google Analytics and Search Console are properly configured and have collected data.', | |
| 1135 | - 'timestamp' => current_time('mysql') | |
| 1136 | - ]; | |
| 1137 | - } | |
| 1138 | - | |
| 1139 | - // Intelligence engine is a Pro-only feature. The four SEO_* classes ship | |
| 1140 | - // in Free too (the PSR-4 autoloader would resolve them), so class_exists() | |
| 1141 | - // can't gate this — check the real Pro signal instead. | |
| 1142 | - if (!Plan_Config::is_pro()) { | |
| 1143 | - return [ | |
| 1144 | - 'success' => false, | |
| 1145 | - 'data' => null, | |
| 1146 | - 'message' => 'Intelligent dashboard requires ThinkRank Pro.', | |
| 1147 | - 'timestamp' => current_time('mysql') | |
| 1148 | - ]; | |
| 1149 | - } | |
| 1150 | - | |
| 1151 | - $trend_analyzer = new SEO_Trend_Analyzer(); | |
| 1152 | - $scoring_engine = new SEO_Scoring_Engine(); | |
| 1153 | - $insight_generator = new SEO_Insight_Generator(); | |
| 1154 | - | |
| 1155 | - $data = $dashboard_data; | |
| 1156 | - | |
| 1157 | - // Generate trend analysis | |
| 1158 | - $current_data = $data; | |
| 1159 | - $historical_data = $this->get_historical_data($date_range); | |
| 1160 | - | |
| 1161 | - $trends = [ | |
| 1162 | - 'traffic_trends' => $trend_analyzer->analyze_traffic_trends($current_data, $historical_data), | |
| 1163 | - 'keyword_trends' => $trend_analyzer->analyze_keyword_trends($data['search_performance'] ?? [], $date_range), | |
| 1164 | - 'content_trends' => $trend_analyzer->analyze_content_trends($data, $data['search_performance'] ?? []) | |
| 1165 | - ]; | |
| 1166 | - | |
| 1167 | - // Calculate SEO health score | |
| 1168 | - $seo_health = $scoring_engine->calculate_seo_health_score($data, $data['search_performance'] ?? []); | |
| 1169 | - | |
| 1170 | - // Generate insights | |
| 1171 | - $insights = [ | |
| 1172 | - 'traffic_insights' => $insight_generator->generate_traffic_insights($trends['traffic_trends']), | |
| 1173 | - 'keyword_insights' => $insight_generator->generate_keyword_insights($trends['keyword_trends']), | |
| 1174 | - 'content_insights' => $insight_generator->generate_content_insights($trends['content_trends']) | |
| 1175 | - ]; | |
| 1176 | - | |
| 1177 | - // Combine all intelligence data | |
| 1178 | - $enhanced_data = array_merge($data, [ | |
| 1179 | - 'intelligence' => [ | |
| 1180 | - 'trends' => $trends, | |
| 1181 | - 'seo_health_score' => $seo_health, | |
| 1182 | - 'insights' => $insights, | |
| 1183 | - 'last_analyzed' => current_time('mysql') | |
| 1184 | - ] | |
| 1185 | - ]); | |
| 1186 | - | |
| 1187 | - return [ | |
| 1188 | - 'success' => true, | |
| 1189 | - 'data' => $enhanced_data, | |
| 1190 | - 'message' => 'Intelligent dashboard data retrieved successfully' | |
| 1191 | - ]; | |
| 1192 | - } | |
| 1193 | - | |
| 1194 | - /** | |
| 1195 | - * Get intelligent SEO opportunities with prioritization | |
| 1196 | - * | |
| 1197 | - * @param string $date_range Date range for analysis | |
| 1198 | - * @return array Enhanced opportunities with intelligence | |
| 1199 | - */ | |
| 1200 | - public function get_intelligent_seo_opportunities(string $date_range = '30d'): array { | |
| 1201 | - // Get base opportunities data | |
| 1202 | - $opportunities_data = $this->get_seo_opportunities($date_range); | |
| 1203 | - | |
| 1204 | - // Check if there's an error in the data | |
| 1205 | - if (isset($opportunities_data['error'])) { | |
| 1206 | - return [ | |
| 1207 | - 'success' => false, | |
| 1208 | - 'data' => null, | |
| 1209 | - 'message' => 'Failed to retrieve opportunities data: ' . $opportunities_data['error'], | |
| 1210 | - 'timestamp' => current_time('mysql') | |
| 1211 | - ]; | |
| 1212 | - } | |
| 1213 | - | |
| 1214 | - // The opportunities payload itself has no search_performance key — that | |
| 1215 | - // data lives in the (cached) dashboard payload. Pull it from there both | |
| 1216 | - // for the availability check and as input for the opportunity detectors; | |
| 1217 | - // checking $opportunities_data['search_performance'] here used to make | |
| 1218 | - // this method always bail with "No Search Console data available". | |
| 1219 | - $dashboard_data = $this->get_dashboard_data($date_range); | |
| 1220 | - $search_performance = $dashboard_data['search_performance'] ?? []; | |
| 1221 | - $opportunities_data['search_performance'] = $search_performance; | |
| 1222 | - | |
| 1223 | - $has_search_data = !empty($search_performance['rows']) || | |
| 1224 | - ($search_performance['total_clicks'] ?? 0) > 0 || | |
| 1225 | - ($search_performance['total_impressions'] ?? 0) > 0; | |
| 1226 | - | |
| 1227 | - if (!$has_search_data) { | |
| 1228 | - return [ | |
| 1229 | - 'success' => false, | |
| 1230 | - 'data' => null, | |
| 1231 | - 'message' => 'No Search Console data available yet. Please ensure your Search Console is properly configured and has collected data.', | |
| 1232 | - 'timestamp' => current_time('mysql') | |
| 1233 | - ]; | |
| 1234 | - } | |
| 1235 | - | |
| 1236 | - // Intelligence engine is a Pro-only feature — gate on the real Pro signal, | |
| 1237 | - // not class_exists() (the classes ship in Free and would autoload). | |
| 1238 | - if (!Plan_Config::is_pro()) { | |
| 1239 | - return [ | |
| 1240 | - 'success' => false, | |
| 1241 | - 'data' => null, | |
| 1242 | - 'message' => 'Intelligent opportunities require ThinkRank Pro.', | |
| 1243 | - 'timestamp' => current_time('mysql') | |
| 1244 | - ]; | |
| 1245 | - } | |
| 1246 | - | |
| 1247 | - $opportunity_detector = new SEO_Opportunity_Detector(); | |
| 1248 | - $scoring_engine = new SEO_Scoring_Engine(); | |
| 1249 | - | |
| 1250 | - $data = $opportunities_data; | |
| 1251 | - | |
| 1252 | - // Detect intelligent opportunities | |
| 1253 | - $search_console_data = $data['search_performance'] ?? []; | |
| 1254 | - $analytics_data = $data; | |
| 1255 | - | |
| 1256 | - $intelligent_opportunities = [ | |
| 1257 | - 'quick_wins' => $opportunity_detector->detect_quick_wins($search_console_data, $analytics_data), | |
| 1258 | - 'content_opportunities' => $opportunity_detector->identify_content_opportunities($search_console_data, $analytics_data), | |
| 1259 | - 'keyword_opportunities' => $scoring_engine->score_keyword_opportunities($search_console_data) | |
| 1260 | - ]; | |
| 1261 | - | |
| 1262 | - // Prioritize all opportunities. prioritize_opportunities() expects | |
| 1263 | - // category => [opportunities]; calculate_impact_effort_matrix() expects a flat list. | |
| 1264 | - $opportunities_by_category = [ | |
| 1265 | - 'quick_wins' => $intelligent_opportunities['quick_wins']['opportunities'] ?? [], | |
| 1266 | - 'content' => $intelligent_opportunities['content_opportunities']['opportunities'] ?? [], | |
| 1267 | - 'keywords' => $intelligent_opportunities['keyword_opportunities']['opportunities'] ?? [], | |
| 1268 | - ]; | |
| 1269 | - $all_opportunities = array_merge(...array_values($opportunities_by_category)); | |
| 1270 | - | |
| 1271 | - $prioritized = $opportunity_detector->prioritize_opportunities($opportunities_by_category); | |
| 1272 | - $impact_matrix = $opportunity_detector->calculate_impact_effort_matrix($all_opportunities); | |
| 1273 | - | |
| 1274 | - // Enhance original data with intelligence | |
| 1275 | - $enhanced_data = array_merge($data, [ | |
| 1276 | - 'intelligent_opportunities' => $intelligent_opportunities, | |
| 1277 | - 'prioritized_opportunities' => $prioritized, | |
| 1278 | - 'impact_effort_matrix' => $impact_matrix, | |
| 1279 | - 'opportunity_summary' => $this->generate_opportunity_summary($intelligent_opportunities), | |
| 1280 | - 'last_analyzed' => current_time('mysql') | |
| 1281 | - ]); | |
| 1282 | - | |
| 1283 | - return [ | |
| 1284 | - 'success' => true, | |
| 1285 | - 'data' => $enhanced_data, | |
| 1286 | - 'message' => 'Intelligent SEO opportunities retrieved successfully' | |
| 1287 | - ]; | |
| 1288 | - } | |
| 1289 | - | |
| 1290 | - /** | |
| 1291 | - * Get SEO performance insights | |
| 1292 | - * | |
| 1293 | - * @param string $date_range Date range for analysis | |
| 1294 | - * @return array SEO insights data | |
| 1295 | - */ | |
| 1296 | - public function get_seo_insights(string $date_range = '30d'): array { | |
| 1297 | - $cache_key = "seo_insights_{$date_range}"; | |
| 1298 | - $cached_data = get_transient($cache_key); | |
| 1299 | - | |
| 1300 | - if ($cached_data !== false) { | |
| 1301 | - return [ | |
| 1302 | - 'success' => true, | |
| 1303 | - 'data' => $cached_data, | |
| 1304 | - 'cached' => true, | |
| 1305 | - 'message' => 'SEO insights retrieved from cache' | |
| 1306 | - ]; | |
| 1307 | - } | |
| 1308 | - | |
| 1309 | - try { | |
| 1310 | - // Get dashboard data for analysis | |
| 1311 | - $dashboard_result = $this->get_intelligent_dashboard_data($date_range); | |
| 1312 | - | |
| 1313 | - if (!$dashboard_result['success']) { | |
| 1314 | - return $dashboard_result; | |
| 1315 | - } | |
| 1316 | - | |
| 1317 | - $dashboard_data = $dashboard_result['data']; | |
| 1318 | - $intelligence = $dashboard_data['intelligence'] ?? []; | |
| 1319 | - | |
| 1320 | - // Insights are a Pro-only feature — gate on the real Pro signal, | |
| 1321 | - // not class_exists() (SEO_Insight_Generator ships in Free too). | |
| 1322 | - if (!Plan_Config::is_pro()) { | |
| 1323 | - return [ | |
| 1324 | - 'success' => false, | |
| 1325 | - 'data' => null, | |
| 1326 | - 'message' => 'SEO insights require ThinkRank Pro.', | |
| 1327 | - 'timestamp' => current_time('mysql') | |
| 1328 | - ]; | |
| 1329 | - } | |
| 1330 | - | |
| 1331 | - $insight_generator = new SEO_Insight_Generator(); | |
| 1332 | - | |
| 1333 | - // Collect all insights | |
| 1334 | - $all_insights = []; | |
| 1335 | - | |
| 1336 | - if (!empty($intelligence['insights']['traffic_insights']['insights'])) { | |
| 1337 | - $all_insights = array_merge($all_insights, $intelligence['insights']['traffic_insights']['insights']); | |
| 1338 | - } | |
| 1339 | - | |
| 1340 | - if (!empty($intelligence['insights']['keyword_insights']['insights'])) { | |
| 1341 | - $all_insights = array_merge($all_insights, $intelligence['insights']['keyword_insights']['insights']); | |
| 1342 | - } | |
| 1343 | - | |
| 1344 | - if (!empty($intelligence['insights']['content_insights']['insights'])) { | |
| 1345 | - $all_insights = array_merge($all_insights, $intelligence['insights']['content_insights']['insights']); | |
| 1346 | - } | |
| 1347 | - | |
| 1348 | - // Format and prioritize insights | |
| 1349 | - $formatted_insights = $insight_generator->format_insights_for_display($all_insights); | |
| 1350 | - $prioritized_insights = $insight_generator->prioritize_insights_by_impact($formatted_insights); | |
| 1351 | - | |
| 1352 | - $insights_data = [ | |
| 1353 | - 'insights' => $prioritized_insights['prioritized_insights'], | |
| 1354 | - 'summary' => [ | |
| 1355 | - 'total_insights' => count($formatted_insights), | |
| 1356 | - 'high_impact_count' => $prioritized_insights['high_impact_count'], | |
| 1357 | - 'action_required_count' => $prioritized_insights['action_required_count'] | |
| 1358 | - ], | |
| 1359 | - 'seo_health_score' => $intelligence['seo_health_score'] ?? null, | |
| 1360 | - 'generated_at' => current_time('mysql') | |
| 1361 | - ]; | |
| 1362 | - | |
| 1363 | - // Cache the results | |
| 1364 | - set_transient($cache_key, $insights_data, $this->cache_duration); | |
| 1365 | - | |
| 1366 | - return [ | |
| 1367 | - 'success' => true, | |
| 1368 | - 'data' => $insights_data, | |
| 1369 | - 'cached' => false, | |
| 1370 | - 'message' => 'SEO insights generated successfully' | |
| 1371 | - ]; | |
| 1372 | - } catch (\Exception $e) { | |
| 1373 | - return [ | |
| 1374 | - 'success' => false, | |
| 1375 | - 'error' => 'Failed to generate SEO insights: ' . $e->getMessage(), | |
| 1376 | - 'data' => null | |
| 1377 | - ]; | |
| 1378 | - } | |
| 1379 | - } | |
| 1380 | - | |
| 1381 | - /** | |
| 1382 | - * Check if real analytics data is available | |
| 1383 | - * | |
| 1384 | - * @param array $dashboard_data Dashboard data to check | |
| 1385 | - * @return bool True if real data is available | |
| 1386 | - */ | |
| 1387 | - private function has_real_data(array $dashboard_data): bool { | |
| 1388 | - // Check if we have meaningful traffic data | |
| 1389 | - $traffic = $dashboard_data['traffic'] ?? []; | |
| 1390 | - $search_performance = $dashboard_data['search_performance'] ?? []; | |
| 1391 | - | |
| 1392 | - $has_traffic = !empty($traffic) && ( | |
| 1393 | - ($traffic['sessions'] ?? 0) > 0 || | |
| 1394 | - ($traffic['pageviews'] ?? 0) > 0 || | |
| 1395 | - ($traffic['active_users'] ?? 0) > 0 | |
| 1396 | - ); | |
| 1397 | - | |
| 1398 | - $has_search_data = !empty($search_performance) && ( | |
| 1399 | - !empty($search_performance['rows']) || | |
| 1400 | - ($search_performance['total_clicks'] ?? 0) > 0 || | |
| 1401 | - ($search_performance['total_impressions'] ?? 0) > 0 | |
| 1402 | - ); | |
| 1403 | - | |
| 1404 | - return $has_traffic || $has_search_data; | |
| 1405 | - } | |
| 1406 | - | |
| 1407 | - /** | |
| 1408 | - * Get historical data for trend comparison | |
| 1409 | - * | |
| 1410 | - * @param string $current_range Current date range | |
| 1411 | - * @return array Historical data | |
| 1412 | - */ | |
| 1413 | - private function get_historical_data(string $current_range): array { | |
| 1414 | - // Calculate previous period based on current range | |
| 1415 | - $previous_range = $this->calculate_previous_period($current_range); | |
| 1416 | - | |
| 1417 | - // Try to get actual historical data from previous period | |
| 1418 | - $historical_data = $this->get_dashboard_data($previous_range); | |
| 1419 | - | |
| 1420 | - // Return the actual historical data (may be empty if no real data available) | |
| 1421 | - return [ | |
| 1422 | - 'sessions' => $historical_data['traffic']['sessions'] ?? 0, | |
| 1423 | - 'pageviews' => $historical_data['traffic']['pageviews'] ?? 0, | |
| 1424 | - 'organic_traffic' => $historical_data['organic_traffic'] ?? ['organic_traffic' => ['sessions' => 0]], | |
| 1425 | - 'bounce_rate' => $historical_data['traffic']['bounce_rate'] ?? 0, | |
| 1426 | - 'avg_session_duration' => $historical_data['traffic']['avg_session_duration'] ?? 0 | |
| 1427 | - ]; | |
| 1428 | - } | |
| 1429 | - | |
| 1430 | - /** | |
| 1431 | - * Calculate previous period for comparison | |
| 1432 | - * | |
| 1433 | - * @param string $current_range Current range | |
| 1434 | - * @return string Previous period range | |
| 1435 | - */ | |
| 1436 | - private function calculate_previous_period(string $current_range): string { | |
| 1437 | - // Simple mapping for now - could be enhanced with actual date calculations | |
| 1438 | - $period_mapping = [ | |
| 1439 | - '7d' => '14d', | |
| 1440 | - '30d' => '60d', | |
| 1441 | - '90d' => '180d' | |
| 1442 | - ]; | |
| 1443 | - | |
| 1444 | - return $period_mapping[$current_range] ?? '60d'; | |
| 1445 | - } | |
| 1446 | - | |
| 1447 | - /** | |
| 1448 | - * Generate opportunity summary | |
| 1449 | - * | |
| 1450 | - * @param array $opportunities All opportunities | |
| 1451 | - * @return array Opportunity summary | |
| 1452 | - */ | |
| 1453 | - private function generate_opportunity_summary(array $opportunities): array { | |
| 1454 | - $quick_wins_count = count($opportunities['quick_wins']['opportunities'] ?? []); | |
| 1455 | - $content_opportunities_count = count($opportunities['content_opportunities']['opportunities'] ?? []); | |
| 1456 | - $keyword_opportunities_count = count($opportunities['keyword_opportunities']['opportunities'] ?? []); | |
| 1457 | - | |
| 1458 | - $total_opportunities = $quick_wins_count + $content_opportunities_count + $keyword_opportunities_count; | |
| 1459 | - | |
| 1460 | - $potential_clicks = 0; | |
| 1461 | - if (!empty($opportunities['quick_wins']['potential_additional_clicks'])) { | |
| 1462 | - $potential_clicks = $opportunities['quick_wins']['potential_additional_clicks']; | |
| 1463 | - } | |
| 1464 | - | |
| 1465 | - return [ | |
| 1466 | - 'total_opportunities' => $total_opportunities, | |
| 1467 | - 'quick_wins_count' => $quick_wins_count, | |
| 1468 | - 'content_opportunities_count' => $content_opportunities_count, | |
| 1469 | - 'keyword_opportunities_count' => $keyword_opportunities_count, | |
| 1470 | - 'potential_additional_clicks' => $potential_clicks, | |
| 1471 | - 'priority_recommendation' => $quick_wins_count > 0 ? | |
| 1472 | - 'Focus on quick wins first for immediate impact' : | |
| 1473 | - 'Focus on content optimization for long-term growth' | |
| 1474 | - ]; | |
| 1475 | - } | |
| 1476 | - | |
| 1477 | - /** | |
| 1478 | - * Clear intelligence cache | |
| 1479 | - * | |
| 1480 | - * @return array Clear result | |
| 1481 | - */ | |
| 1482 | - public function clear_intelligence_cache(): array { | |
| 1483 | - $intelligence_cache_keys = [ | |
| 1484 | - 'seo_insights_7d', | |
| 1485 | - 'seo_insights_30d', | |
| 1486 | - 'seo_insights_90d', | |
| 1487 | - 'intelligent_dashboard_7d', | |
| 1488 | - 'intelligent_dashboard_30d', | |
| 1489 | - 'intelligent_dashboard_90d', | |
| 1490 | - 'intelligent_opportunities_7d', | |
| 1491 | - 'intelligent_opportunities_30d', | |
| 1492 | - 'intelligent_opportunities_90d' | |
| 1493 | - ]; | |
| 1494 | - | |
| 1495 | - $cleared = 0; | |
| 1496 | - foreach ($intelligence_cache_keys as $key) { | |
| 1497 | - if (delete_transient($key)) { | |
| 1498 | - $cleared++; | |
| 1499 | - } | |
| 1500 | - } | |
| 1501 | - | |
| 1502 | - return [ | |
| 1503 | - 'success' => true, | |
| 1504 | - 'message' => "Cleared {$cleared} intelligence cache entries", | |
| 1505 | - 'cleared_count' => $cleared, | |
| 1506 | - 'timestamp' => current_time('mysql') | |
| 1507 | - ]; | |
| 1508 | 1059 | } |
| 1509 | 1060 | } |