Plugin Directory

Changeset 3419567


Ignore:
Timestamp:
12/14/2025 09:18:50 PM (3 months ago)
Author:
ashleysmith1
Message:

Update to version 5.3.10

Location:
maio-the-new-ai-geo-seo-tool/trunk
Files:
5 added
2 edited

Legend:

Unmodified
Added
Removed
  • maio-the-new-ai-geo-seo-tool/trunk/maio-main.php

    r3376694 r3419567  
    44 * Plugin URI: https://maioai.com
    55 * Description: This plugin helps optimize your Website for AI-powered discovery tools such as ChatGPT, Perplexity, Claude, Google Gemini, Google AI Overviews, Meta Llama and many more. It combines the best of traditional SEO and emerging AIO strategies to ensure your brand is accurately and favorably represented in AI-generated content.
    6  * Version: 5.2.17
     6 * Version: 5.3.10
    77 * Requires at least: 5.0
    88 * Requires PHP: 7.2
     
    1616
    1717// Define plugin constants
    18 define('MAIO_VERSION', '5.2.17');
     18define('MAIO_VERSION', '5.3.10');
    1919define('MAIO_PLUGIN_DIR', plugin_dir_path(__FILE__));
    2020define('MAIO_PLUGIN_URL', plugin_dir_url(__FILE__));
    2121define('MAIO_NONCE_KEY', 'maio_nonce');
    2222
    23 require_once MAIO_PLUGIN_DIR . 'maio_analytics.php';
     23require_once MAIO_PLUGIN_DIR . 'maio_activity.php';
    2424require_once MAIO_PLUGIN_DIR . 'maio-ai-scanner.php';
    25 require_once MAIO_PLUGIN_DIR . 'maio-analytics-api.php'; // REST API endpoints for dashboard
     25require_once MAIO_PLUGIN_DIR . 'maio-activity-api.php'; // REST API endpoints for dashboard
    2626require_once MAIO_PLUGIN_DIR . 'maio-llm-referral-tracking.php'; // LLM referral tracking
    2727
     
    349349    );
    350350
    351     // Add Analytics submenu (2nd)
     351    // Add Activity submenu (2nd)
    352352    add_submenu_page(
    353353        'maio-ai-scanner',
    354         'Analytics',
    355         'Analytics',
     354        'Activity',
     355        'Activity',
    356356        'manage_options',
    357         'maio_analytics',
    358         'maio_analytics_page'
     357        'maio_activity',
     358        'maio_activity_page'
    359359    );
    360360
    361     // Add GEO Academy submenu (3rd)
     361    // Add Analytics submenu (3rd)
     362    add_submenu_page(
     363        'maio-ai-scanner',
     364        esc_html__('AI Analytics', 'maio-the-new-ai-geo-seo-tool'),
     365        esc_html__('AI Analytics', 'maio-the-new-ai-geo-seo-tool'),
     366        'manage_options',
     367        'maio-analytics',
     368        'maio_settings_page'
     369    );
     370
     371    // Add GEO Academy submenu (4th)
    362372    add_submenu_page(
    363373        'maio-ai-scanner',
     
    369379    );
    370380
    371     // Add About submenu (4th)
     381    // Add About submenu (5th)
    372382    add_submenu_page(
    373383        'maio-ai-scanner',
     
    410420});
    411421
     422/**
     423 * Make sure bridge token remains within safe limits.
     424 */
     425function maio_sanitize_bridge_token($token) {
     426    $option_name = 'maio_plugin_bridge_token';
     427    $current_value = get_option($option_name, '');
     428
     429    if (!is_string($token)) {
     430        $token = '';
     431    }
     432
     433    $token = trim(wp_unslash($token));
     434
     435    // Check if this is an intentional deletion (from the delete button)
     436    // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Handled by settings_fields()
     437    $is_delete_intent = isset($_POST['maio_delete_token_intent']) && sanitize_text_field(wp_unslash($_POST['maio_delete_token_intent'])) === '1';
     438
     439    if ($token === '') {
     440        // Allow empty value if it's an intentional deletion
     441        if ($is_delete_intent) {
     442            return ''; // Allow deletion
     443        }
     444       
     445        // Otherwise, show error and keep current value
     446        add_settings_error(
     447            'maio_settings_token_group',
     448            'maio_token_empty',
     449            esc_html__('Token field cannot be empty. Paste the token from the MAIO website dashboard.', 'maio-the-new-ai-geo-seo-tool'),
     450            'error'
     451        );
     452        return $current_value;
     453    }
     454
     455    if (!preg_match('/^[0-9a-f]{64}$/', $token)) {
     456        add_settings_error(
     457            'maio_settings_token_group',
     458            'maio_token_format',
     459            esc_html__('Token format is invalid. Token must be exactly as issued in the MAIO website dashboard.', 'maio-the-new-ai-geo-seo-tool'),
     460            'error'
     461        );
     462        return $current_value;
     463    }
     464
     465    return sanitize_text_field($token);
     466}
     467
     468/**
     469 * Determine the base MAIO API URL depending on environment.
     470 */
     471function maio_get_api_base_url() {
     472    $env_api_url = getenv('MAIO_API_URL');
     473    if ($env_api_url !== false && !empty($env_api_url)) {
     474        return rtrim($env_api_url, '/');
     475    }
     476
     477    if (defined('MAIO_API_URL')) {
     478        return rtrim(MAIO_API_URL, '/');
     479    }
     480
     481    $hostname = gethostname();
     482    if ($hostname && strpos($hostname, 'maio-wordpress') !== false) {
     483        return 'http://maio-api:5000';
     484    }
     485
     486    $host = isset($_SERVER['HTTP_HOST']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_HOST'])) : '';
     487    if (
     488        strpos($host, 'localhost') !== false ||
     489        strpos($host, '127.0.0.1') !== false ||
     490        strpos($host, '.local') !== false
     491    ) {
     492        return 'http://localhost:5000';
     493    }
     494
     495    return 'https://api.maioai.com';
     496}
     497
     498/**
     499 * Store a transient notice so the Analytics page can show token status feedback.
     500 */
     501function maio_set_bridge_token_notice($type, $message) {
     502    set_transient(
     503        'maio_settings_token_notice',
     504        array(
     505            'type'    => $type,
     506            'message' => $message,
     507            'time'    => time(),
     508        ),
     509        MINUTE_IN_SECONDS
     510    );
     511}
     512
     513/**
     514 * After the bridge token option changes, notify the MAIO API so the dashboard can trust this site.
     515 */
     516function maio_register_bridge_token_with_api($old_value, $value, $option) {
     517    if ($value === $old_value) {
     518        return;
     519    }
     520
     521    $token = trim((string) $value);
     522    if ($token === '') {
     523        // Token is being deleted - notify both Flask API and dashboard
     524        $old_token = trim((string) $old_value);
     525       
     526        if ($old_token !== '') {
     527            $site_uuid = get_option('maio_site_uuid');
     528           
     529            // Step 1: Notify Flask API about deletion
     530            if ($site_uuid) {
     531                $flask_endpoint = rtrim(maio_get_api_base_url(), '/') . '/api/v1/plugin/delete-token';
     532               
     533                $flask_payload = array(
     534                    'site_uuid' => $site_uuid,
     535                    'site_url'  => home_url(),
     536                );
     537
     538                $flask_response = wp_remote_post(
     539                    $flask_endpoint,
     540                    array(
     541                        'method'  => 'POST',
     542                        'timeout' => 10,
     543                        'headers' => array(
     544                            'Content-Type'    => 'application/json',
     545                            'X-Install-Token' => 'dummy_plugin_token',
     546                        ),
     547                        'body'    => wp_json_encode($flask_payload),
     548                    )
     549                );
     550               
     551                // Log only errors (best effort - don't block deletion)
     552                if (is_wp_error($flask_response)) {
     553                    error_log('MAIO Token Deletion: Flask API error - ' . $flask_response->get_error_message());
     554                } else {
     555                    $flask_status = wp_remote_retrieve_response_code($flask_response);
     556                    if ($flask_status < 200 || $flask_status >= 300) {
     557                        error_log('MAIO Token Deletion: Flask API returned ' . $flask_status);
     558                    }
     559                }
     560            }
     561           
     562            // Step 2: Notify maioai.com dashboard that token is deleted
     563            $dashboard_endpoint = 'https://www.maioai.com/api/plugin/token/status';
     564           
     565            $dashboard_payload = array(
     566                'token'  => $old_token,
     567                'status' => 'deleted',
     568            );
     569
     570            $dashboard_response = wp_remote_post(
     571                $dashboard_endpoint,
     572                array(
     573                    'method'  => 'POST',
     574                    'timeout' => 10,
     575                    'headers' => array(
     576                        'Content-Type'       => 'application/json',
     577                        'x-yossi-api-key'    => 'yssi_sk_live_abc123xyz789def456ghi012jkl345mno678pqr901stu234vwx567',
     578                    ),
     579                    'body'    => wp_json_encode($dashboard_payload),
     580                )
     581            );
     582
     583            // Log only errors (best effort - don't block deletion)
     584            if (is_wp_error($dashboard_response)) {
     585                error_log('MAIO Token Deletion: Dashboard API error - ' . $dashboard_response->get_error_message());
     586            } else {
     587                $dashboard_status = wp_remote_retrieve_response_code($dashboard_response);
     588                if ($dashboard_status < 200 || $dashboard_status >= 300) {
     589                    error_log('MAIO Token Deletion: Dashboard API returned ' . $dashboard_status);
     590                }
     591            }
     592        }
     593
     594        maio_set_bridge_token_notice(
     595            'success',
     596            esc_html__('Token deleted successfully. Dashboard access is now disabled.', 'maio-the-new-ai-geo-seo-tool')
     597        );
     598        return;
     599    }
     600
     601    $site_uuid = get_option('maio_site_uuid');
     602    if (!$site_uuid) {
     603        $site_uuid = wp_generate_uuid4();
     604        update_option('maio_site_uuid', $site_uuid);
     605    }
     606
     607    // Step 1: Register with Flask API (for analytics broker)
     608    $flask_endpoint = rtrim(maio_get_api_base_url(), '/') . '/api/v1/plugin/register-token';
     609
     610    $flask_payload = array(
     611        'site_uuid'      => $site_uuid,
     612        'site_url'       => home_url(),
     613        'plugin_version' => defined('MAIO_VERSION') ? MAIO_VERSION : 'dev',
     614        'wp_version'     => get_bloginfo('version'),
     615        'php_version'    => phpversion(),
     616        'bridge_token'   => $token,
     617    );
     618
     619    $flask_response = wp_remote_post(
     620        $flask_endpoint,
     621        array(
     622            'method'  => 'POST',
     623            'timeout' => 10,
     624            'headers' => array(
     625                'Content-Type'    => 'application/json',
     626                'X-Install-Token' => 'dummy_plugin_token',
     627            ),
     628            'body'    => wp_json_encode($flask_payload),
     629        )
     630    );
     631
     632    if (is_wp_error($flask_response)) {
     633        error_log('MAIO Token Registration Error: Flask API - ' . $flask_response->get_error_message());
     634        maio_set_bridge_token_notice(
     635            'error',
     636            sprintf(
     637                /* translators: %s: error message */
     638                esc_html__('Could not register token with MAIO API: %s', 'maio-the-new-ai-geo-seo-tool'),
     639                esc_html($flask_response->get_error_message())
     640            )
     641        );
     642        return;
     643    }
     644
     645    $flask_status = wp_remote_retrieve_response_code($flask_response);
     646    $flask_body = wp_remote_retrieve_body($flask_response);
     647    $flask_decoded = json_decode($flask_body, true);
     648
     649    if ($flask_status < 200 || $flask_status >= 300) {
     650        error_log('MAIO Token Registration Error: Flask API returned ' . $flask_status . ' - ' . $flask_body);
     651        $error_message = isset($flask_decoded['error']) ? $flask_decoded['error'] : $flask_body;
     652        if (!is_string($error_message) || $error_message === '') {
     653            $error_message = esc_html__('Unexpected response from MAIO API.', 'maio-the-new-ai-geo-seo-tool');
     654        }
     655
     656        maio_set_bridge_token_notice(
     657            'error',
     658            sprintf(
     659                /* translators: %s: error message */
     660                esc_html__('Token save failed: %s', 'maio-the-new-ai-geo-seo-tool'),
     661                esc_html($error_message)
     662            )
     663        );
     664        return;
     665    }
     666
     667    // Step 2: Notify maioai.com dashboard that token is configured
     668    $dashboard_endpoint = 'https://www.maioai.com/api/plugin/token/status';
     669   
     670    $dashboard_payload = array(
     671        'token'  => $token,
     672        'status' => 'configured',
     673    );
     674
     675    $dashboard_response = wp_remote_post(
     676        $dashboard_endpoint,
     677        array(
     678            'method'  => 'POST',
     679            'timeout' => 10,
     680            'headers' => array(
     681                'Content-Type'       => 'application/json',
     682                'x-yossi-api-key'    => 'yssi_sk_live_abc123xyz789def456ghi012jkl345mno678pqr901stu234vwx567',
     683            ),
     684            'body'    => wp_json_encode($dashboard_payload),
     685        )
     686    );
     687
     688    if (is_wp_error($dashboard_response)) {
     689        error_log('MAIO Token Registration Error: Dashboard API - ' . $dashboard_response->get_error_message());
     690        maio_set_bridge_token_notice(
     691            'warning',
     692            sprintf(
     693                /* translators: %s: error message */
     694                esc_html__('Token registered with API but dashboard notification failed: %s', 'maio-the-new-ai-geo-seo-tool'),
     695                esc_html($dashboard_response->get_error_message())
     696            )
     697        );
     698        return;
     699    }
     700
     701    $dashboard_status = wp_remote_retrieve_response_code($dashboard_response);
     702    $dashboard_body = wp_remote_retrieve_body($dashboard_response);
     703    $dashboard_decoded = json_decode($dashboard_body, true);
     704
     705    if ($dashboard_status >= 200 && $dashboard_status < 300) {
     706        maio_set_bridge_token_notice(
     707            'success',
     708            esc_html__('Token registered successfully. You can now view analytics on the MAIO dashboard.', 'maio-the-new-ai-geo-seo-tool')
     709        );
     710        return;
     711    }
     712
     713    // Dashboard notification failed but Flask registration succeeded
     714    $dashboard_error = isset($dashboard_decoded['error']) ? $dashboard_decoded['error'] :
     715                      (isset($dashboard_decoded['message']) ? $dashboard_decoded['message'] : 'Unknown error');
     716   
     717    error_log('MAIO Token Registration Error: Dashboard API returned ' . $dashboard_status . ' - ' . $dashboard_error);
     718   
     719    maio_set_bridge_token_notice(
     720        'warning',
     721        sprintf(
     722            /* translators: %s: error message */
     723            esc_html__('Token registered with API but dashboard returned: %s (Status: %d)', 'maio-the-new-ai-geo-seo-tool'),
     724            esc_html($dashboard_error),
     725            $dashboard_status
     726        )
     727    );
     728}
     729// Hook for updating existing token
     730add_action('update_option_maio_plugin_bridge_token', 'maio_register_bridge_token_with_api', 10, 3);
     731
     732// Hook for adding NEW token (first time save)
     733add_action('add_option_maio_plugin_bridge_token', function($option, $value) {
     734    // Call the same function but with empty old value
     735    maio_register_bridge_token_with_api('', $value, $option);
     736}, 10, 2);
     737
    412738// Register settings
    413739add_action('admin_init', function() {
     
    619945        'type' => 'string',
    620946        'sanitize_callback' => 'sanitize_textarea_field',
     947        'default' => ''
     948    ));
     949
     950    // Settings submenu: token for plugin ↔ dashboard bridge
     951    register_setting('maio_settings_token_group', 'maio_plugin_bridge_token', array(
     952        'type' => 'string',
     953        'sanitize_callback' => 'maio_sanitize_bridge_token',
    621954        'default' => ''
    622955    ));
     
    635968
    636969/**
    637  * Analytics page content
     970 * Activity page content
    638971 */
    639 function maio_analytics_page() {
     972function maio_activity_page() {
    640973    if (!current_user_can('manage_options')) {
    641974        return;
     
    644977    // Output the page wrapper
    645978    ?>
    646     <div class="wrap maio_analytics_wrapper">
    647         <h1>MAIO Analytics</h1>
    648         <?php do_action('maio_analytics_page_content'); ?>
     979    <div class="wrap maio_activity_wrapper">
     980        <h1>MAIO Activity</h1>
     981        <?php do_action('maio_activity_page_content'); ?>
    649982    </div>
    650983    <?php
     
    6691002    // Include the AI-friendly article page
    6701003    require_once MAIO_PLUGIN_DIR . 'articles/maio-ai-friendly-article.php';
     1004}
     1005
     1006// Analytics page callback
     1007function maio_settings_page() {
     1008    if (!current_user_can('manage_options')) {
     1009        return;
     1010    }
     1011
     1012    require_once MAIO_PLUGIN_DIR . 'pages/maio-settings.php';
    6711013}
    6721014
     
    18632205
    18642206    // Verify nonce
    1865     if (!isset($_POST['maio_nonce']) || !wp_verify_nonce(sanitize_key($_POST['maio_nonce']), 'maio_analytics_nonce')) {
     2207    if (!isset($_POST['maio_nonce']) || !wp_verify_nonce(sanitize_key($_POST['maio_nonce']), 'maio_activity_nonce')) {
    18662208        wp_send_json_error('Invalid nonce');
    18672209        return '';
     
    19082250
    19092251    // Verify nonce
    1910     if (!isset($_POST['maio_nonce']) || !wp_verify_nonce(sanitize_key($_POST['maio_nonce']), 'maio_analytics_nonce')) {
     2252    if (!isset($_POST['maio_nonce']) || !wp_verify_nonce(sanitize_key($_POST['maio_nonce']), 'maio_activity_nonce')) {
    19112253        wp_send_json_error('Invalid nonce');
    19122254        return;
     
    20112353}
    20122354
    2013 // Add nonce field to the analytics page
    2014 function maio_add_analytics_nonce() {
    2015     wp_nonce_field('maio_analytics_nonce', 'maio_nonce');
     2355// Add nonce field to the activity page
     2356function maio_add_activity_nonce() {
     2357    wp_nonce_field('maio_activity_nonce', 'maio_nonce');
    20162358}
    2017 add_action('admin_footer-maio_page_maio_analytics', 'maio_add_analytics_nonce');
    2018 
    2019 // Cypress/Testing: AJAX endpoint to reset all MAIO analytics/statistics (for test isolation)
    2020 add_action('wp_ajax_maio_reset_analytics', function() {
     2359add_action('admin_footer-maio_page_maio_activity', 'maio_add_activity_nonce');
     2360
     2361// Cypress/Testing: AJAX endpoint to reset all MAIO activity/statistics (for test isolation)
     2362add_action('wp_ajax_maio_reset_activity', function() {
    20212363    if (!current_user_can('manage_options')) wp_die('forbidden');
    20222364    global $wpdb;
     
    20262368    // Clear relevant caches
    20272369    wp_cache_flush();
    2028     wp_send_json_success('Analytics table truncated.');
     2370    wp_send_json_success('Activity table truncated.');
    20292371});
    20302372
     
    20352377
    20362378    // Check nonce
    2037     if (!isset($_POST['maio_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['maio_nonce'])), 'maio_analytics_nonce')) {
     2379    if (!isset($_POST['maio_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['maio_nonce'])), 'maio_activity_nonce')) {
    20382380        wp_send_json_error('Invalid nonce', 400);
    20392381    }
     
    20712413
    20722414    // Check nonce
    2073     if (!isset($_POST['maio_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['maio_nonce'])), 'maio_analytics_nonce')) {
     2415    if (!isset($_POST['maio_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['maio_nonce'])), 'maio_activity_nonce')) {
    20742416        wp_send_json_error('Invalid nonce', 400);
    20752417    }
     
    21062448
    21072449    // Check nonce
    2108     if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'maio_analytics_nonce')) {
     2450    if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'maio_activity_nonce')) {
    21092451        wp_send_json_error('Invalid nonce', 400);
    21102452    }
     
    21372479
    21382480    // Check nonce
    2139     if (!isset($_POST['maio_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['maio_nonce'])), 'maio_analytics_nonce')) {
     2481    if (!isset($_POST['maio_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['maio_nonce'])), 'maio_activity_nonce')) {
    21402482        wp_send_json_error('Invalid nonce', 400);
    21412483    }
     
    23012643    // For logged-in users, require nonce
    23022644    if (is_user_logged_in()) {
    2303         if (!isset($_POST['maio_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['maio_nonce'])), 'maio_analytics_nonce')) {
     2645        if (!isset($_POST['maio_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['maio_nonce'])), 'maio_activity_nonce')) {
    23042646            wp_send_json_error('Invalid nonce', 400);
    23052647            return;
     
    23352677add_action('wp_ajax_maio_get_nonce', function() {
    23362678    if (!current_user_can('manage_options')) wp_send_json_error('forbidden', 403);
    2337     wp_send_json_success(['nonce' => wp_create_nonce('maio_analytics_nonce')]);
     2679    wp_send_json_success(['nonce' => wp_create_nonce('maio_activity_nonce')]);
    23382680});
    23392681
  • maio-the-new-ai-geo-seo-tool/trunk/readme.txt

    r3376694 r3419567  
    11=== MAIO - The new AI GEO / SEO tool ===
    22Contributors: ashleysmith1
    3 Tags: geo, seo, ai, chatgpt, google ai overviews
     3Tags: ai, ai seo, chatgpt, claude, gemini
    44Requires at least: 5.0
    55Tested up to: 6.8.2
    6 Stable tag: 5.2.17
     6Stable tag: 5.3.10
    77License: GPLv2 or later
    88License URI: http://www.gnu.org/licenses/gpl-2.0.html
    99
    10 This plugin helps Optimize your website for AI-powered discovery tools like ChatGPT, Perplexity, Claude, Gemini, and more. AI SEO for the future.
     10This plugin helps optimize your website for AI-powered discovery tools like ChatGPT, Perplexity, Claude, Gemini, and more. AI GEO (Generative Engine Optimization) for the future.
    1111
    1212== Description ==
    1313
    14 This plugin helps optimize your Website for AI-powered discovery tools such as ChatGPT (OpenAI), Perplexity, Claude (Anthropic), Google Gemini, Meta AI, and more. It combines the best of traditional SEO and emerging AIO strategies to ensure your brand is accurately and favorably represented in AI-generated content. MAIO now includes advanced analytics and detection for the latest AI bots
     14This plugin helps optimize your Website for AI-powered discovery tools such as ChatGPT (OpenAI), Perplexity, Claude (Anthropic), Google Gemini, Meta AI, and more. MAIO focuses on AI GEO (Generative Engine Optimization) strategies to ensure your brand is accurately and favorably represented in AI-generated content. The plugin includes advanced analytics and detection for the latest AI bots and LLM crawlers
    1515
    1616== Installation ==
     
    18181. Upload the plugin files to the `/wp-content/plugins/maio-the-new-ai-geo-seo-tool` directory, or install the plugin through the WordPress plugins screen directly.
    19192. Activate the plugin through the 'Plugins' screen in WordPress
    20 3. Use the Settings->MAIO screen to configure the plugin
     203. That's it! MAIO works out of the box with no configuration needed
    2121
    2222== Frequently Asked Questions ==
     
    2424= What is MAIO? =
    2525
    26 MAIO is a WordPress plugin that helps optimize your website for AI-powered discovery tools. It combines traditional SEO with AI-specific optimization strategies, and now includes analytics and detection for the latest AI and LLM crawlers and user-initiated fetchers.
     26MAIO is a WordPress plugin that helps optimize your website for AI-powered discovery tools. It focuses on AI GEO (Generative Engine Optimization) strategies to ensure your content is discoverable and accurately represented by AI systems. The plugin includes advanced analytics and detection for the latest AI and LLM crawlers.
    2727
    2828= How does MAIO work? =
    2929
    30 MAIO adds structured data and metadata to your website that helps AI tools better understand and represent your content. It also detects and logs visits from major AI bots, including:
    31 * OpenAI
     30MAIO optimizes your website for AI discovery by adding structured signals that help AI tools accurately understand and represent your content. The plugin automatically tracks engagement from major AI systems, including:
     31* OpenAI ChatGPT
    3232* Anthropic Claude
    3333* Perplexity AI
     
    3535* Meta AI
    3636
    37 The plugin is extensible, so you can add detection for new AI bots as they appear.
     37MAIO provides real-time analytics showing which AI systems are discovering your content, what pages they're indexing, and how your brand appears in AI-generated responses.
    3838
    3939== Changelog ==
     40= 5.3.10 =
     41* Added AI Analytics submenu for MAIO web dashboard integration
     42* Analytics Dashboard Access - Direct link to view website analytics on maioai.com
    4043
    4144= 5.2.17 =
Note: See TracChangeset for help on using the changeset viewer.