PluginProbe
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO / 2.9.0
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO v2.9.0
2.9.0 2.8.0 2.7.0 2.6.0 2.5.0 2.4.0 2.3.0 2.2.0 2.1.1 2.1.0 2.0.2 2.0.1 2.0.0 1.32.0 1.31.0 1.30.0 1.29.0 1.28.0 1.27.0 1.26.0 1.25.0 trunk 1.0.0 1.0.1 1.0.2 All 50 releases
← All changes | includes/seo/class-ai-traffic-tracker.php +8 -29 2.3.0 → 2.9.0 View file →
@@ -97,36 +97,8 @@
97 97 'kimi.com' => 'kimi',
98 98 ];
99 99
100 100 /**
101 - * User-agent fragments → AI crawler slug. Case-insensitive substring
102 - * match. Order matters where one token contains another — more specific
103 - * entries first.
104 - *
105 - * @var array<string, string>
106 - */
107 - private const CRAWLER_AGENTS = [
108 - 'OAI-SearchBot' => 'oai-searchbot',
109 - 'ChatGPT-User' => 'chatgpt-user',
110 - 'GPTBot' => 'gptbot',
111 - 'Perplexity-User' => 'perplexity-user',
112 - 'PerplexityBot' => 'perplexitybot',
113 - 'Claude-SearchBot' => 'claude-searchbot',
114 - 'Claude-User' => 'claude-user',
115 - 'ClaudeBot' => 'claudebot',
116 - 'anthropic-ai' => 'anthropic-ai',
117 - 'Google-Extended' => 'google-extended',
118 - 'Applebot-Extended' => 'applebot-extended',
119 - 'meta-externalagent' => 'meta-externalagent',
120 - 'meta-externalfetcher' => 'meta-externalfetcher',
121 - 'Bytespider' => 'bytespider',
122 - 'Amazonbot' => 'amazonbot',
123 - 'CCBot' => 'ccbot',
124 - 'cohere-ai' => 'cohere-ai',
125 - 'MistralAI-User' => 'mistral-user',
126 - ];
127 -
128 - /**
129 101 * Wire the front-end recorder and the retention cron.
130 102 *
131 103 * @return void
132 104 */
@@ -169,8 +141,12 @@
169 141
170 142 /**
171 143 * Classify a user agent as an AI crawler.
172 144 *
145 + * The agent list is `AI_Crawlers`, shared with the robots.txt panel — the
146 + * two must agree about which bots exist, or a site blocks a crawler it is
147 + * not counting (#657).
148 + *
173 149 * @param string $user_agent Raw user agent (may be empty).
174 150 * @return string|null Crawler slug, or null when not a known AI crawler.
175 151 */
176 152 public static function classify_crawler(string $user_agent): ?string {
@@ -177,9 +153,12 @@
177 153 if ('' === $user_agent) {
178 154 return null;
179 155 }
180 156
181 - foreach (self::CRAWLER_AGENTS as $fragment => $slug) {
157 + // Token order is significant and owned by the registry: the first
158 + // token found wins, so `Claude-SearchBot` has to be tested before
159 + // `ClaudeBot`. See AI_Crawlers::AGENTS.
160 + foreach (AI_Crawlers::token_map() as $fragment => $slug) {
182 161 if (false !== stripos($user_agent, $fragment)) {
183 162 return $slug;
184 163 }
185 164 }