PluginProbe
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO / 2.7.0
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO v2.7.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 1.1.0 1.10.0 All 48 releases
← All changes | includes/api/class-site-identity-endpoint.php +41 -1 2.2.02.7.0 View file →
@@ -383,11 +383,17 @@
383 383 // static file directly (bypassing the robots_txt filter), so without
384 384 // this the file goes stale and /robots.txt shows the old content
385 385 // while the textarea shows the new — regardless of what the frontend
386 386 // believed about the file's existence.
387 + //
388 + // ai_crawler_rules counts as a robots.txt change even though it is
389 + // not the body: the directives it produces are composed into the
390 + // served output at render time, so a physical file left alone here
391 + // would keep serving the previous allow/block set (#657).
387 392 if ($context_type === 'site'
388 393 && (array_key_exists('robots_txt_content', $settings)
389 - || array_key_exists('robots_txt_enabled', $settings))
394 + || array_key_exists('robots_txt_enabled', $settings)
395 + || array_key_exists('ai_crawler_rules', $settings))
390 396 ) {
391 397 $this->identity_manager->sync_robots_txt_file();
392 398 }
393 399
@@ -565,8 +571,24 @@
565 571 // show the served output next to the editable body and flag a
566 572 // physical file in the web root that has drifted from the settings.
567 573 $robots_data['effective'] = $this->identity_manager->get_robots_txt_delivery();
568 574
575 + // The per-agent AI crawler surface (#657). The registry ships with
576 + // the response rather than being duplicated in the bundle, so a
577 + // crawler added by the `thinkrank_ai_crawlers` filter appears in
578 + // the UI without a rebuild. Rules are returned normalised, so a
579 + // crawler with nothing stored comes back explicitly allowed rather
580 + // than as an absence the client has to interpret.
581 + $settings = $this->identity_manager->get_settings('site');
582 + $rules = \ThinkRank\SEO\AI_Crawlers::normalize_rules($settings['ai_crawler_rules'] ?? []);
583 +
584 + $robots_data['ai_crawlers'] = \ThinkRank\SEO\AI_Crawlers::for_display();
585 + $robots_data['ai_crawler_rules'] = [];
586 +
587 + foreach ($robots_data['ai_crawlers'] as $agent) {
588 + $robots_data['ai_crawler_rules'][$agent['slug']] = $rules[$agent['slug']] ?? 'allow';
589 + }
590 +
569 591 return new WP_REST_Response([
570 592 'success' => true,
571 593 'data' => $robots_data,
572 594 'message' => 'Robots.txt data retrieved successfully'
@@ -622,8 +644,17 @@
622 644 }
623 645
624 646 $settings = ['robots_txt_enabled' => $enable_management];
625 647
648 + // Per-agent AI crawler rules (#657). Only written when the caller
649 + // sends them: this route is also the plain "re-sync the file" save,
650 + // and defaulting a missing parameter to an empty map there would
651 + // unblock every crawler the site had blocked.
652 + $ai_rules = $request->get_param('ai_crawler_rules');
653 + if (null !== $ai_rules) {
654 + $settings['ai_crawler_rules'] = \ThinkRank\SEO\AI_Crawlers::normalize_rules($ai_rules);
655 + }
656 +
626 657 if ($regenerate) {
627 658 // Generate and validate robots.txt from the rules.
628 659 $robots_data = $this->identity_manager->generate_robots_txt($custom_rules);
629 660
@@ -1105,8 +1136,17 @@
1105 1136 // sends it, and "false" is a non-empty string — truthy — so the
1106 1137 // file was written when the caller had asked it not to be. ("0" is
1107 1138 // falsy, which is why the failure was asymmetric.) Registering it
1108 1139 // gets core's boolean coercion (#394).
1140 + 'ai_crawler_rules' => [
1141 + 'required' => false,
1142 + 'type' => 'object',
1143 + 'description' => 'Per-agent AI crawler rules, keyed by crawler slug, each "allow" or "block".',
1144 + 'additionalProperties' => [
1145 + 'type' => 'string',
1146 + 'enum' => ['allow', 'block'],
1147 + ],
1148 + ],
1109 1149 'write_to_file' => [
1110 1150 'required' => false,
1111 1151 'type' => 'boolean',
1112 1152 'default' => true,