class BotTracker {
private $bot_map;
public function __construct() {
$this->bot_map = [
'Googlebot' => __('Googlebot', 'your-textdomain'),
'Bingbot' => __('Bingbot', 'your-textdomain'),
'Slurp' => __('Yahoo!', 'your-textdomain'),
'DuckDuckBot' => __('DuckDuckBot', 'your-textdomain'),
'Baiduspider' => __('Baiduspider', 'your-textdomain'),
'YandexBot' => __('YandexBot', 'your-textdomain'),
'Sogou' => __('Sogou', 'your-textdomain'),
'Exabot' => __('Exabot', 'your-textdomain'),
'ia_archiver' => __('Alexa/Archive', 'your-textdomain'),
'GPTBot' => __('ChatGPT', 'your-textdomain'),
'ChatGPT-User' => __('ChatGPT User', 'your-textdomain'),
'ClaudeBot' => __('Claude (Anthropic)', 'your-textdomain'),
'Google-Extended' => __('Google AI (Gemini)', 'your-textdomain'),
'CCBot' => __('Common Crawl', 'your-textdomain'),
'facebookexternalhit'=> __('Facebook', 'your-textdomain'),
'Twitterbot' => __('Twitter/X', 'your-textdomain'),
'LinkedInBot' => __('LinkedIn', 'your-textdomain'),
'Pinterestbot' => __('Pinterest', 'your-textdomain'),
'Slackbot' => __('Slack', 'your-textdomain'),
'TelegramBot' => __('Telegram', 'your-textdomain'),
'Applebot' => __('Applebot', 'your-textdomain'),
];
add_action('init', [$this, 'track_bots']);
add_action('wp_dashboard_setup', [$this, 'register_dashboard_widget']);
add_action('wp_ajax_get_bot_stats', [$this, 'ajax_get_stats']);
add_action('wp_ajax_reset_bot_stats', [$this, 'ajax_reset_stats']);
}
public function get_tracked_bots_map() {
return $this->bot_map;
}
public function track_bots() {
$user_agent = $_SERVER['HTTP_USER_AGENT'] ?? '';
if (empty($user_agent)) return;
foreach ($this->bot_map as $key => $name) {
if (stripos($user_agent, $key) !== false) {
update_option("last_visit_{$name}", current_time('M j, Y - g:i a'));
$count = (int) get_option("visit_count_{$name}", 0);
update_option("visit_count_{$name}", $count + 1);
break;
}
}
}
public function ajax_get_stats() {
if (!current_user_can('manage_options')) {
wp_die(__('Unauthorized', 'your-textdomain'));
}
ob_start();
?>
<table class="wp-list-table widefat fixed striped">
<thead>
<tr>
<th><?php _e('Bot', 'your-textdomain'); ?></th>
<th><?php _e('Last Visit', 'your-textdomain'); ?></th>
<th><?php _e('Hits', 'your-textdomain'); ?></th>
</tr>
</thead>
<tbody>
<?php
foreach ($this->bot_map as $key => $name) :
$time = get_option("last_visit_{$name}", __('Never', 'your-textdomain'));
$count = get_option("visit_count_{$name}", 0);
?>
<tr>
<td><strong><?php echo esc_html($name); ?></strong></td>
<td><?php echo esc_html($time); ?></td>
<td><span class="badge" style="background:#2271b1; color:#fff; padding:2px 8px; border-radius:10px;"><?php echo esc_html($count); ?></span></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php
echo ob_get_clean();
wp_die();
}
public function ajax_reset_stats() {
check_ajax_referer('reset_bot_stats_nonce');
if (!current_user_can('manage_options')) wp_die(__('Unauthorized', 'your-textdomain'));
foreach ($this->bot_map as $key => $name) {
delete_option("last_visit_{$name}");
delete_option("visit_count_{$name}");
}
wp_send_json_success();
}
public function register_dashboard_widget() {
if (current_user_can('manage_options')) {
wp_add_dashboard_widget(
'bot_indexer_tracker_widget',
__('🚀 Live Search & AI Tracker', 'your-textdomain'),
[$this, 'render_widget']
);
}
}
public function render_widget() {
?>
<div id="bot-tracker-container" style="max-height: 400px; overflow-y: auto;">
<p><?php _e('Connecting to tracker...', 'your-textdomain'); ?></p>
</div>
<hr />
<button id="reset-bot-stats" class="button button-link-delete" style="color: #d63638;">
<?php _e('Reset All Bot Data', 'your-textdomain'); ?>
</button>
<script type="text/javascript">
(function($) {
function updateBotStats() {
$.post(ajaxurl, { action: 'get_bot_stats' }, function(response) {
$('#bot-tracker-container').html(response);
});
}
updateBotStats();
setInterval(updateBotStats, 10000);
$('#reset-bot-stats').on('click', function(e) {
e.preventDefault();
if (confirm('<?php echo esc_js(__('Clear all timestamps and counters?', 'your-textdomain')); ?>')) {
$.post(ajaxurl, {
action: 'reset_bot_stats',
_ajax_nonce: '<?php echo wp_create_nonce("reset_bot_stats_nonce"); ?>'
}, function() {
updateBotStats();
});
}
});
})(jQuery);
</script>
<?php
}
}
new BotTracker();