Skip to content
McStay Designs

Wordpress tech Development

McStay Designs

Wordpress tech Development

  • Network benchmark
  • Get a Quote
  • Free code Projects
  • Free plugins
  • About
  • Network benchmark
  • Get a Quote
  • Free code Projects
  • Free plugins
  • About
McStay Designs

Wordpress tech Development

McStay Designs

Wordpress tech Development

  • Network benchmark
  • Get a Quote
  • Free code Projects
  • Free plugins
  • About
  • Network benchmark
  • Get a Quote
  • Free code Projects
  • Free plugins
  • About
Home/Free code Projects/bot tacker
Free code Projects

bot tacker

By mkmcst
September 4, 2026 3 Min Read
0
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'),
            'Amazon'              => __('Amazon.com', 'your-textdomain'),
        ];

        // Only run the migration check once; skips instantly on future loads
        if (!get_option('bot_tracker_migrated', false)) {
            $this->rescue_and_migrate_stats();
        }

        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']);
    }

    private function rescue_and_migrate_stats() {
        global $wpdb;

        $existing_stats = get_option('bot_tracker_stats', []);
        
        $old_options = $wpdb->get_results(
            "SELECT option_name, option_value FROM {$wpdb->options} WHERE option_name LIKE 'last_visit\_%' OR option_name LIKE 'visit_count\_%'"
        );

        $migrated_stats = $existing_stats;
        $legacy_keys_to_delete = [];

        if (!empty($old_options)) {
            foreach ($old_options as $opt) {
                if (strpos($opt->option_name, 'last_visit_') === 0) {
                    $bot_name = str_replace('last_visit_', '', $opt->option_name);
                    if (!isset($migrated_stats[$bot_name])) {
                        $migrated_stats[$bot_name] = ['last_visit' => __('Never', 'your-textdomain'), 'count' => 0];
                    }
                    $migrated_stats[$bot_name]['last_visit'] = $opt->option_value;
                    $legacy_keys_to_delete[] = $opt->option_name;
                } elseif (strpos($opt->option_name, 'visit_count_') === 0) {
                    $bot_name = str_replace('visit_count_', '', $opt->option_name);
                    if (!isset($migrated_stats[$bot_name])) {
                        $migrated_stats[$bot_name] = ['last_visit' => __('Never', 'your-textdomain'), 'count' => 0];
                    }
                    $migrated_stats[$bot_name]['count'] = (int) $opt->option_value;
                    $legacy_keys_to_delete[] = $opt->option_name;
                }
            }
        }

        // Save migrated stats (non-autoloaded) and mark migration as complete
        update_option('bot_tracker_stats', $migrated_stats, false);
        update_option('bot_tracker_migrated', true, true);

        // Clean up legacy individual database rows
        if (!empty($legacy_keys_to_delete)) {
            foreach ($legacy_keys_to_delete as $old_key) {
                delete_option($old_key);
            }
        }
    }

    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) {
                $stats = get_option('bot_tracker_stats', []);
                
                if (!isset($stats[$name])) {
                    $stats[$name] = ['last_visit' => __('Never', 'your-textdomain'), 'count' => 0];
                }

                $stats[$name]['last_visit'] = current_time('M j, Y - g:i a');
                $stats[$name]['count']++;

                update_option('bot_tracker_stats', $stats, false);
                break;
            }
        }
    }

    public function ajax_get_stats() {
        if (!current_user_can('manage_options')) {
            wp_die(__('Unauthorized', 'your-textdomain'));
        }

        $stats = get_option('bot_tracker_stats', []);

        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 = $stats[$name]['last_visit'] ?? __('Never', 'your-textdomain');
                    $count = $stats[$name]['count'] ?? 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'));

        delete_option('bot_tracker_stats');
        delete_option('bot_tracker_migrated'); // Reset migration flag if they reset stats

        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, 60000);

                $('#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();
Author

mkmcst

test test test

Follow Me
Other Articles
Previous

Automated New England Amber Alert Banner

Next

GeoBlocker Pro System

No Comment! Be the first one.

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Legal

  • Terms of Service
  • Privacy Policy
Copyright 2026 — McStay Designs. All rights reserved.McStay Media
🚀 Upgrade Your Site: 20% Off Custom WordPress Plugins, Security Cleanup & Performance Tuning!Get a Free Quote →