PluginProbe
SEO Engine – Smart SEO with AI, Schema & Redirection for WordPress / trunk
SEO Engine – Smart SEO with AI, Schema & Redirection for WordPress vtrunk
0.9.4 0.9.3 0.9.2 0.9.1 0.9.0 0.8.9 0.8.8 0.8.7 0.8.6 0.8.5 0.8.4 0.8.2 0.8.1 0.7.9 0.8.0 0.7.7 0.7.8 0.7.6 0.7.5 0.7.4 0.7.3 0.7.2 0.7.1 0.7.0 0.6.5 All 88 releases
seo-engine / classes / modules / aiengine.php

aiengine.php in SEO Engine – Smart SEO with AI, Schema & Redirection for WordPress trunk, at classes/modules/aiengine.php

157 lines 5.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 // Feeds the SEO block in AI Engine's Modules tab through its mwai_seo_stats filter.
4 // AI Engine renders whatever tiles arrive, generically. Rule of that block: never
5 // send an invented number; an unavailable tile carries a reason code (and optionally
6 // an action link) instead of a value.
7 class Meow_MWSEO_Modules_AIEngine
8 {
9 private $core;
10
11 public function __construct( $core ) {
12 $this->core = $core;
13 add_filter( 'mwai_seo_stats', array( $this, 'mwai_seo_stats' ) );
14 }
15
16 public function mwai_seo_stats( $stats ) {
17 // Only offered when the robots.txt editor is actually enabled; AI Engine
18 // falls back to a plain "View" link on the served /robots.txt otherwise.
19 $robots_url = $this->core->get_option( 'robot_editor', false )
20 ? admin_url( 'admin.php?page=mwseo_settings&nekoTab=settings&section=technical' )
21 : null;
22 return array(
23 'provider' => array(
24 'name' => 'SEO Engine',
25 'version' => MWSEO_VERSION,
26 'admin_url' => admin_url( 'admin.php?page=mwseo_settings' ),
27 ),
28 'robots_url' => $robots_url,
29 'tiles' => array(
30 'ai_bot_visits' => $this->tile_ai_bot_visits(),
31 'ai_visibility' => $this->tile_ai_visibility(),
32 'top_ai_bots' => $this->tile_top_ai_bots(),
33 ),
34 );
35 }
36
37 private function tile( $label, $args = array() ) {
38 return array_merge( array(
39 'label' => $label,
40 'available' => false,
41 'value' => null,
42 'period' => null,
43 'reason' => null,
44 'action' => null,
45 ), $args );
46 }
47
48 private function tile_ai_bot_visits() {
49 $label = __( 'AI bot visits', 'seo-engine' );
50 // Bot tracking only depends on bots_track: general_analytics gates the human
51 // visit tracking, a separate table (see analytics.php init vs track_visit).
52 $tracking = $this->core->get_option( 'bots_track', false );
53 if ( !$tracking ) {
54 // The Track toggle lives in the Traffic Analytics settings section, which is
55 // only reachable when the Analytics module is on; otherwise land on Modules.
56 $section = $this->core->get_option( 'analytics', false ) ? 'analytics' : 'modules';
57 return $this->tile( $label, array(
58 'reason' => 'tracking_off',
59 'action' => array(
60 'label' => __( 'Enable tracking', 'seo-engine' ),
61 'url' => admin_url( 'admin.php?page=mwseo_settings&nekoTab=settings&section=' . $section ),
62 ),
63 ) );
64 }
65 // The analytics module is private on core; this public wrapper returns an
66 // empty array when the module is unavailable, which lands on no_data below.
67 $data = $this->core->query_bot_traffic( array(
68 'bot_type' => 'ai',
69 'start_date' => date( 'Y-m-d', strtotime( '-7 days' ) ),
70 ) );
71 $visits = isset( $data['aggregates']['total_visits'] ) ? (int) $data['aggregates']['total_visits'] : 0;
72 if ( $visits === 0 ) {
73 return $this->tile( $label, array( 'reason' => 'no_data' ) );
74 }
75 return $this->tile( $label, array(
76 'available' => true,
77 'value' => $visits,
78 'period' => __( '7 days', 'seo-engine' ),
79 ) );
80 }
81
82 private function tile_ai_visibility() {
83 $label = __( 'AI visibility', 'seo-engine' );
84 if ( !isset( $this->core->pro->ai_visibility ) ) {
85 return $this->tile( $label, array( 'reason' => 'pro_required' ) );
86 }
87 $module = $this->core->pro->ai_visibility;
88 if ( !$module->is_enabled() ) {
89 // AI Engine has no dedicated copy for this code and falls back to its
90 // generic empty state, which is what we want; the action link does the work.
91 return $this->tile( $label, array(
92 'reason' => 'disabled',
93 'action' => array(
94 'label' => __( 'Enable AI Visibility', 'seo-engine' ),
95 'url' => admin_url( 'admin.php?page=mwseo_settings&nekoTab=settings&section=modules' ),
96 ),
97 ) );
98 }
99 $overview = $module->get_overview();
100 if ( empty( $overview['brand_count'] ) ) {
101 return $this->tile( $label, array(
102 'reason' => 'no_brand',
103 'action' => array(
104 'label' => __( 'Set up your brand', 'seo-engine' ),
105 'url' => admin_url( 'admin.php?page=mwseo_settings&nekoTab=ai-visibility' ),
106 ),
107 ) );
108 }
109 if ( !isset( $overview['global_score'] ) ) {
110 return $this->tile( $label, array( 'reason' => 'no_data' ) );
111 }
112 return $this->tile( $label, array(
113 'available' => true,
114 'value' => (int) $overview['global_score'],
115 'period' => __( 'score', 'seo-engine' ),
116 ) );
117 }
118
119 // A `list` tile: AI Engine renders the rows (label + value) instead of one big number.
120 private function tile_top_ai_bots() {
121 $label = __( 'Top AI bots', 'seo-engine' );
122 if ( !$this->core->get_option( 'bots_track', false ) ) {
123 $section = $this->core->get_option( 'analytics', false ) ? 'analytics' : 'modules';
124 return $this->tile( $label, array(
125 'reason' => 'tracking_off',
126 'action' => array(
127 'label' => __( 'Enable tracking', 'seo-engine' ),
128 'url' => admin_url( 'admin.php?page=mwseo_settings&nekoTab=settings&section=' . $section ),
129 ),
130 ) );
131 }
132 $ai_bots = $this->core->get_bots_by_type( 'ai' );
133 $summary = $this->core->get_ai_agents_summary( date( 'Y-m-d', strtotime( '-7 days' ) ) );
134 $top = array();
135 foreach ( (array) $summary as $row ) {
136 // The summary covers every tracked crawler; keep only the AI ones here.
137 if ( in_array( $row['bot_name'], $ai_bots, true ) ) {
138 $top[] = array(
139 'label' => $row['bot_name'],
140 'value' => (int) $row['visit_count'],
141 );
142 }
143 if ( count( $top ) >= 3 ) {
144 break;
145 }
146 }
147 if ( empty( $top ) ) {
148 return $this->tile( $label, array( 'reason' => 'no_data' ) );
149 }
150 return $this->tile( $label, array(
151 'available' => true,
152 'list' => $top,
153 'period' => __( '7 days', 'seo-engine' ),
154 ) );
155 }
156 }
157