Plugin Directory

Changeset 3475304


Ignore:
Timestamp:
03/05/2026 08:35:27 AM (4 weeks ago)
Author:
bsolveit
Message:

v1.2.0: Add review prompt banner with interactive star rating

Location:
ai-discovery-files
Files:
2 added
16 edited
1 copied

Legend:

Unmodified
Added
Removed
  • ai-discovery-files/tags/1.2.0/admin/class-admin.php

    r3474794 r3475304  
    3737        add_action( 'wp_ajax_aidf_dismiss_welcome', array( __CLASS__, 'ajax_dismiss_welcome' ) );
    3838        add_action( 'wp_ajax_aidf_save_verify_code', array( __CLASS__, 'ajax_save_verify_code' ) );
     39        add_action( 'wp_ajax_aidf_dismiss_review', array( __CLASS__, 'ajax_dismiss_review' ) );
    3940        add_action( 'admin_notices', array( __CLASS__, 'maybe_show_welcome_notice' ) );
    4041        add_action( 'admin_notices', array( __CLASS__, 'maybe_show_conflict_notice' ) );
     
    519520        wp_send_json_success();
    520521    }
     522
     523    /**
     524     * Check whether the review prompt banner should display.
     525     *
     526     * @return bool
     527     */
     528    public static function should_show_review_banner() {
     529        if ( ! current_user_can( 'manage_options' ) ) {
     530            return false;
     531        }
     532
     533        // Condition 1: settings saved at least once.
     534        $saved_at = get_option( 'aidf_settings_saved_at' );
     535        if ( false === $saved_at ) {
     536            return false;
     537        }
     538
     539        // Condition 2: 2+ active files.
     540        $settings     = get_option( 'aidf_settings', array() );
     541        $active_files = isset( $settings['active_files'] ) ? (array) $settings['active_files'] : array();
     542        if ( count( $active_files ) < 2 ) {
     543            return false;
     544        }
     545
     546        // Condition 3: 3+ days since activation.
     547        $activated_at = get_option( 'aidf_activated_at' );
     548        if ( false === $activated_at || ( time() - (int) $activated_at ) < ( 3 * DAY_IN_SECONDS ) ) {
     549            return false;
     550        }
     551
     552        // Condition 4: not permanently dismissed.
     553        $user_id   = get_current_user_id();
     554        $dismissed = get_user_meta( $user_id, 'aidf_review_dismissed', true );
     555        if ( in_array( $dismissed, array( 'done', 'low' ), true ) ) {
     556            return false;
     557        }
     558
     559        // Condition 5: not snoozed (or 90+ days elapsed).
     560        $snoozed = get_user_meta( $user_id, 'aidf_review_snoozed', true );
     561        if ( $snoozed && ( time() - (int) $snoozed ) < ( 90 * DAY_IN_SECONDS ) ) {
     562            return false;
     563        }
     564
     565        return true;
     566    }
     567
     568    /**
     569     * AJAX handler: dismiss the review prompt.
     570     *
     571     * @return void
     572     */
     573    public static function ajax_dismiss_review() {
     574        check_ajax_referer( 'aidf_admin_nonce', 'nonce' );
     575
     576        if ( ! current_user_can( 'manage_options' ) ) {
     577            wp_send_json_error();
     578        }
     579
     580        $reason  = isset( $_POST['reason'] ) ? sanitize_text_field( wp_unslash( $_POST['reason'] ) ) : '';
     581        $user_id = get_current_user_id();
     582
     583        switch ( $reason ) {
     584            case 'done':
     585            case 'reviewed':
     586            case 'low':
     587                update_user_meta( $user_id, 'aidf_review_dismissed', $reason );
     588                delete_user_meta( $user_id, 'aidf_review_snoozed' );
     589                break;
     590
     591            case 'snooze':
     592                update_user_meta( $user_id, 'aidf_review_snoozed', time() );
     593                break;
     594
     595            default:
     596                wp_send_json_error( 'Invalid reason.' );
     597        }
     598
     599        wp_send_json_success();
     600    }
    521601}
  • ai-discovery-files/tags/1.2.0/admin/class-settings.php

    r3472434 r3475304  
    282282        flush_rewrite_rules();
    283283
     284        // Record the first time settings were saved (for review prompt trigger).
     285        if ( false === get_option( 'aidf_settings_saved_at' ) ) {
     286            update_option( 'aidf_settings_saved_at', time(), false );
     287        }
     288
    284289        return $clean;
    285290    }
  • ai-discovery-files/tags/1.2.0/admin/css/admin.css

    r3472434 r3475304  
    14421442
    14431443.aidf-btn--sm {
    1444     padding: 3px var(--aidf-sp-3);
     1444    padding: var(--aidf-sp-1) var(--aidf-sp-3);
    14451445    font-size: var(--aidf-text-xs);
     1446    min-height: auto;
     1447    white-space: nowrap;
    14461448}
    14471449
     
    22492251
    22502252/* --------------------------------------------------------
    2251    24. Responsive
     2253   24. Review Prompt Banner
     2254   -------------------------------------------------------- */
     2255.aidf-review-banner {
     2256    margin: 0 0 var(--aidf-sp-4);
     2257    padding: var(--aidf-sp-3) var(--aidf-sp-5);
     2258    background: linear-gradient(135deg, var(--aidf-orange-light) 0%, #fffcf8 50%, #fff9f2 100%);
     2259    border: 1px solid rgba(231, 125, 21, 0.15);
     2260    border-left: 3px solid var(--aidf-orange);
     2261    border-radius: var(--aidf-radius-md);
     2262    box-shadow: var(--aidf-shadow-sm), inset 0 1px 0 rgba(255, 255, 255, 0.7);
     2263    animation: aidfBannerIn 0.4s cubic-bezier(0.22, 1, 0.36, 1) both;
     2264    overflow: hidden;
     2265}
     2266
     2267@keyframes aidfBannerIn {
     2268    from {
     2269        opacity: 0;
     2270        transform: translateY(-8px);
     2271        max-height: 0;
     2272        padding-top: 0;
     2273        padding-bottom: 0;
     2274        margin-bottom: 0;
     2275    }
     2276    to {
     2277        opacity: 1;
     2278        transform: translateY(0);
     2279        max-height: 80px;
     2280        padding-top: var(--aidf-sp-3);
     2281        padding-bottom: var(--aidf-sp-3);
     2282        margin-bottom: var(--aidf-sp-4);
     2283    }
     2284}
     2285
     2286.aidf-review-banner--out {
     2287    animation: aidfBannerOut 0.3s ease forwards;
     2288}
     2289
     2290@keyframes aidfBannerOut {
     2291    to {
     2292        opacity: 0;
     2293        transform: translateY(-8px);
     2294        max-height: 0;
     2295        padding-top: 0;
     2296        padding-bottom: 0;
     2297        margin-bottom: 0;
     2298    }
     2299}
     2300
     2301.aidf-review-banner__content {
     2302    display: flex;
     2303    align-items: center;
     2304    gap: var(--aidf-sp-3);
     2305    min-height: 32px;
     2306}
     2307
     2308.aidf-review-banner__content[hidden] {
     2309    display: none;
     2310}
     2311
     2312.aidf-review-banner__response {
     2313    animation: aidfFadeIn 0.3s ease both;
     2314}
     2315
     2316.aidf-review-banner__response .aidf-btn {
     2317    flex-shrink: 0;
     2318}
     2319
     2320.aidf-review-banner .aidf-review-banner__response a.aidf-btn--primary {
     2321    color: #ffffff;
     2322}
     2323
     2324.aidf-review-banner .aidf-review-banner__response a.aidf-btn--primary:hover {
     2325    color: #ffffff;
     2326}
     2327
     2328@keyframes aidfFadeIn {
     2329    from { opacity: 0; transform: translateY(-4px); }
     2330    to { opacity: 1; transform: translateY(0); }
     2331}
     2332
     2333.aidf-review-banner__icon {
     2334    color: var(--aidf-orange);
     2335    font-size: 18px;
     2336    width: 18px;
     2337    height: 18px;
     2338    flex-shrink: 0;
     2339}
     2340
     2341.aidf-review-banner__text {
     2342    font-size: var(--aidf-text-sm);
     2343    font-weight: 500;
     2344    color: var(--aidf-text);
     2345    white-space: nowrap;
     2346}
     2347
     2348/* Stars container */
     2349.aidf-review-banner__stars {
     2350    display: flex;
     2351    gap: var(--aidf-sp-1);
     2352    margin: 0 var(--aidf-sp-1);
     2353}
     2354
     2355/* Individual star button */
     2356.aidf-review-star {
     2357    display: flex;
     2358    align-items: center;
     2359    justify-content: center;
     2360    padding: 2px;
     2361    background: none;
     2362    border: none;
     2363    cursor: pointer;
     2364    color: var(--aidf-border);
     2365    transition: color var(--aidf-transition), transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);
     2366    border-radius: var(--aidf-radius-sm);
     2367}
     2368
     2369.aidf-review-star:focus-visible {
     2370    outline: 2px solid var(--aidf-orange);
     2371    outline-offset: 2px;
     2372}
     2373
     2374.aidf-review-star svg {
     2375    width: 22px;
     2376    height: 22px;
     2377    transition: fill var(--aidf-transition), filter var(--aidf-transition);
     2378    fill: transparent;
     2379}
     2380
     2381/* Hover: fill stars up to hovered one */
     2382.aidf-review-banner__stars:hover .aidf-review-star {
     2383    color: var(--aidf-orange);
     2384}
     2385
     2386.aidf-review-banner__stars:hover .aidf-review-star svg {
     2387    fill: var(--aidf-orange);
     2388}
     2389
     2390.aidf-review-banner__stars:hover .aidf-review-star:hover {
     2391    transform: scale(1.2);
     2392}
     2393
     2394.aidf-review-banner__stars:hover .aidf-review-star:hover svg {
     2395    filter: drop-shadow(0 1px 3px rgba(231, 125, 21, 0.35));
     2396}
     2397
     2398.aidf-review-banner__stars:hover .aidf-review-star:hover ~ .aidf-review-star {
     2399    color: var(--aidf-border);
     2400}
     2401
     2402.aidf-review-banner__stars:hover .aidf-review-star:hover ~ .aidf-review-star svg {
     2403    fill: transparent;
     2404}
     2405
     2406/* Dismiss links */
     2407.aidf-review-banner__dismiss {
     2408    display: flex;
     2409    align-items: center;
     2410    gap: var(--aidf-sp-2);
     2411    margin-left: auto;
     2412    flex-shrink: 0;
     2413}
     2414
     2415.aidf-review-dismiss {
     2416    background: rgba(0, 0, 0, 0.04);
     2417    border: 1px solid var(--aidf-border);
     2418    border-radius: var(--aidf-radius-sm);
     2419    padding: var(--aidf-sp-1) var(--aidf-sp-3);
     2420    cursor: pointer;
     2421    font-size: var(--aidf-text-xs);
     2422    color: var(--aidf-text-secondary);
     2423    text-decoration: none;
     2424    transition: all var(--aidf-transition);
     2425    white-space: nowrap;
     2426}
     2427
     2428.aidf-review-dismiss:hover {
     2429    background: rgba(0, 0, 0, 0.08);
     2430    border-color: var(--aidf-text-tertiary);
     2431    color: var(--aidf-text);
     2432}
     2433
     2434.aidf-review-banner__sep {
     2435    display: none;
     2436}
     2437
     2438/* --------------------------------------------------------
     2439   25. Responsive
    22522440   -------------------------------------------------------- */
    22532441@media (max-width: 960px) {
     
    23252513        align-items: flex-start;
    23262514    }
    2327 }
    2328 
    2329 /* --------------------------------------------------------
    2330    25. WordPress Admin Overrides
     2515
     2516    .aidf-review-banner__content {
     2517        flex-wrap: wrap;
     2518    }
     2519
     2520    .aidf-review-banner__dismiss {
     2521        margin-left: 0;
     2522        margin-top: var(--aidf-sp-1);
     2523        width: 100%;
     2524        padding-left: 30px;
     2525    }
     2526}
     2527
     2528/* --------------------------------------------------------
     2529   26. WordPress Admin Overrides
    23312530   -------------------------------------------------------- */
    23322531
     
    23572556
    23582557/* --------------------------------------------------------
    2359    26. Welcome Notice (global WP admin)
     2558   27. Welcome Notice (global WP admin)
    23602559   -------------------------------------------------------- */
    23612560.aidf-welcome-notice {
  • ai-discovery-files/tags/1.2.0/admin/js/admin.js

    r3472434 r3475304  
    543543        });
    544544
     545        /* -------------------------------------------------------
     546           Review Prompt Banner
     547           ------------------------------------------------------- */
     548        var reviewBanner = $('#aidf-review-banner');
     549
     550        if (reviewBanner.length) {
     551
     552            // Star click handler.
     553            reviewBanner.on('click', '.aidf-review-star', function () {
     554                var rating = parseInt($(this).data('rating'), 10);
     555                var reason;
     556
     557                // Hide the prompt row.
     558                $('#aidf-review-prompt').hide();
     559
     560                if (rating >= 4) {
     561                    $('#aidf-review-thanks').removeAttr('hidden').show();
     562                    reason = 'done';
     563                } else {
     564                    $('#aidf-review-support').removeAttr('hidden').show();
     565                    reason = 'low';
     566                }
     567
     568                // Dismiss via AJAX.
     569                $.post(aidfAdmin.ajaxUrl, {
     570                    action: 'aidf_dismiss_review',
     571                    nonce: aidfAdmin.nonce,
     572                    reason: reason
     573                });
     574
     575            });
     576
     577            // Dismiss link handler (Already reviewed / Not now).
     578            reviewBanner.on('click', '.aidf-review-dismiss', function () {
     579                var reason = $(this).data('reason');
     580
     581                $.post(aidfAdmin.ajaxUrl, {
     582                    action: 'aidf_dismiss_review',
     583                    nonce: aidfAdmin.nonce,
     584                    reason: reason
     585                });
     586
     587                reviewBanner.addClass('aidf-review-banner--out');
     588                setTimeout(function () { reviewBanner.remove(); }, 300);
     589            });
     590        }
     591
    545592    }); // end DOM ready
    546593
  • ai-discovery-files/tags/1.2.0/admin/views/settings-page.php

    r3472434 r3475304  
    6969    <!-- Content -->
    7070    <div class="aidf-content">
     71        <?php if ( AIDF_Admin::should_show_review_banner() ) : ?>
     72            <?php include AIDF_PLUGIN_DIR . 'admin/views/partials/review-banner.php'; ?>
     73        <?php endif; ?>
     74
    7175        <?php settings_errors( 'aidf_settings' ); ?>
    7276
  • ai-discovery-files/tags/1.2.0/ai-discovery-files.php

    r3474794 r3475304  
    44 * Plugin URI:        https://www.ai-visibility.org.uk/wordpress-plugin/ai-discovery-files/
    55 * Description:       Improve your AI Visibility by generating AI Discovery Files so AI systems like ChatGPT, Claude, and Gemini can correctly discover, interpret, and cite your website.
    6  * Version:           1.1.1
     6 * Version:           1.2.0
    77 * Requires at least: 6.2
    88 * Requires PHP:      8.0
     
    2424 * Plugin constants.
    2525 */
    26 define( 'AIDF_VERSION', '1.1.1' );
     26define( 'AIDF_VERSION', '1.2.0' );
    2727define( 'AIDF_PLUGIN_FILE', __FILE__ );
    2828define( 'AIDF_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
     
    5050    }
    5151
     52    if ( false === get_option( 'aidf_activated_at' ) ) {
     53        update_option( 'aidf_activated_at', time(), false );
     54    }
     55
    5256    set_transient( 'aidf_activation_redirect', true, 30 );
    5357}
  • ai-discovery-files/tags/1.2.0/readme.txt

    r3474794 r3475304  
    55Tested up to: 6.9
    66Requires PHP: 8.0
    7 Stable tag: 1.1.1
     7Stable tag: 1.2.0
    88License: GPLv2 or later
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
     
    167167
    168168== Changelog ==
     169
     170= 1.2.0 =
     171* Add review prompt banner on settings page with interactive star rating
     172* Smart trigger: only shows after settings saved, 2+ active files, and 3+ days active
     173* Stars 4-5 link to WordPress.org review page; stars 1-3 show support link
     174* "Already reviewed" permanently dismisses; "Not now" snoozes for 90 days
     175* Polished SVG star animations with brand-consistent design
    169176
    170177= 1.1.1 =
  • ai-discovery-files/tags/1.2.0/uninstall.php

    r3472044 r3475304  
    2020delete_metadata( 'user', 0, 'aidf_welcome_dismissed', '', true );
    2121
     22// Remove review prompt data from all users.
     23delete_metadata( 'user', 0, 'aidf_review_dismissed', '', true );
     24delete_metadata( 'user', 0, 'aidf_review_snoozed', '', true );
     25
     26// Remove review prompt options.
     27delete_option( 'aidf_activated_at' );
     28delete_option( 'aidf_settings_saved_at' );
     29
    2230// Flush rewrite rules to remove our custom rules.
    2331flush_rewrite_rules();
  • ai-discovery-files/trunk/admin/class-admin.php

    r3474794 r3475304  
    3737        add_action( 'wp_ajax_aidf_dismiss_welcome', array( __CLASS__, 'ajax_dismiss_welcome' ) );
    3838        add_action( 'wp_ajax_aidf_save_verify_code', array( __CLASS__, 'ajax_save_verify_code' ) );
     39        add_action( 'wp_ajax_aidf_dismiss_review', array( __CLASS__, 'ajax_dismiss_review' ) );
    3940        add_action( 'admin_notices', array( __CLASS__, 'maybe_show_welcome_notice' ) );
    4041        add_action( 'admin_notices', array( __CLASS__, 'maybe_show_conflict_notice' ) );
     
    519520        wp_send_json_success();
    520521    }
     522
     523    /**
     524     * Check whether the review prompt banner should display.
     525     *
     526     * @return bool
     527     */
     528    public static function should_show_review_banner() {
     529        if ( ! current_user_can( 'manage_options' ) ) {
     530            return false;
     531        }
     532
     533        // Condition 1: settings saved at least once.
     534        $saved_at = get_option( 'aidf_settings_saved_at' );
     535        if ( false === $saved_at ) {
     536            return false;
     537        }
     538
     539        // Condition 2: 2+ active files.
     540        $settings     = get_option( 'aidf_settings', array() );
     541        $active_files = isset( $settings['active_files'] ) ? (array) $settings['active_files'] : array();
     542        if ( count( $active_files ) < 2 ) {
     543            return false;
     544        }
     545
     546        // Condition 3: 3+ days since activation.
     547        $activated_at = get_option( 'aidf_activated_at' );
     548        if ( false === $activated_at || ( time() - (int) $activated_at ) < ( 3 * DAY_IN_SECONDS ) ) {
     549            return false;
     550        }
     551
     552        // Condition 4: not permanently dismissed.
     553        $user_id   = get_current_user_id();
     554        $dismissed = get_user_meta( $user_id, 'aidf_review_dismissed', true );
     555        if ( in_array( $dismissed, array( 'done', 'low' ), true ) ) {
     556            return false;
     557        }
     558
     559        // Condition 5: not snoozed (or 90+ days elapsed).
     560        $snoozed = get_user_meta( $user_id, 'aidf_review_snoozed', true );
     561        if ( $snoozed && ( time() - (int) $snoozed ) < ( 90 * DAY_IN_SECONDS ) ) {
     562            return false;
     563        }
     564
     565        return true;
     566    }
     567
     568    /**
     569     * AJAX handler: dismiss the review prompt.
     570     *
     571     * @return void
     572     */
     573    public static function ajax_dismiss_review() {
     574        check_ajax_referer( 'aidf_admin_nonce', 'nonce' );
     575
     576        if ( ! current_user_can( 'manage_options' ) ) {
     577            wp_send_json_error();
     578        }
     579
     580        $reason  = isset( $_POST['reason'] ) ? sanitize_text_field( wp_unslash( $_POST['reason'] ) ) : '';
     581        $user_id = get_current_user_id();
     582
     583        switch ( $reason ) {
     584            case 'done':
     585            case 'reviewed':
     586            case 'low':
     587                update_user_meta( $user_id, 'aidf_review_dismissed', $reason );
     588                delete_user_meta( $user_id, 'aidf_review_snoozed' );
     589                break;
     590
     591            case 'snooze':
     592                update_user_meta( $user_id, 'aidf_review_snoozed', time() );
     593                break;
     594
     595            default:
     596                wp_send_json_error( 'Invalid reason.' );
     597        }
     598
     599        wp_send_json_success();
     600    }
    521601}
  • ai-discovery-files/trunk/admin/class-settings.php

    r3472434 r3475304  
    282282        flush_rewrite_rules();
    283283
     284        // Record the first time settings were saved (for review prompt trigger).
     285        if ( false === get_option( 'aidf_settings_saved_at' ) ) {
     286            update_option( 'aidf_settings_saved_at', time(), false );
     287        }
     288
    284289        return $clean;
    285290    }
  • ai-discovery-files/trunk/admin/css/admin.css

    r3472434 r3475304  
    14421442
    14431443.aidf-btn--sm {
    1444     padding: 3px var(--aidf-sp-3);
     1444    padding: var(--aidf-sp-1) var(--aidf-sp-3);
    14451445    font-size: var(--aidf-text-xs);
     1446    min-height: auto;
     1447    white-space: nowrap;
    14461448}
    14471449
     
    22492251
    22502252/* --------------------------------------------------------
    2251    24. Responsive
     2253   24. Review Prompt Banner
     2254   -------------------------------------------------------- */
     2255.aidf-review-banner {
     2256    margin: 0 0 var(--aidf-sp-4);
     2257    padding: var(--aidf-sp-3) var(--aidf-sp-5);
     2258    background: linear-gradient(135deg, var(--aidf-orange-light) 0%, #fffcf8 50%, #fff9f2 100%);
     2259    border: 1px solid rgba(231, 125, 21, 0.15);
     2260    border-left: 3px solid var(--aidf-orange);
     2261    border-radius: var(--aidf-radius-md);
     2262    box-shadow: var(--aidf-shadow-sm), inset 0 1px 0 rgba(255, 255, 255, 0.7);
     2263    animation: aidfBannerIn 0.4s cubic-bezier(0.22, 1, 0.36, 1) both;
     2264    overflow: hidden;
     2265}
     2266
     2267@keyframes aidfBannerIn {
     2268    from {
     2269        opacity: 0;
     2270        transform: translateY(-8px);
     2271        max-height: 0;
     2272        padding-top: 0;
     2273        padding-bottom: 0;
     2274        margin-bottom: 0;
     2275    }
     2276    to {
     2277        opacity: 1;
     2278        transform: translateY(0);
     2279        max-height: 80px;
     2280        padding-top: var(--aidf-sp-3);
     2281        padding-bottom: var(--aidf-sp-3);
     2282        margin-bottom: var(--aidf-sp-4);
     2283    }
     2284}
     2285
     2286.aidf-review-banner--out {
     2287    animation: aidfBannerOut 0.3s ease forwards;
     2288}
     2289
     2290@keyframes aidfBannerOut {
     2291    to {
     2292        opacity: 0;
     2293        transform: translateY(-8px);
     2294        max-height: 0;
     2295        padding-top: 0;
     2296        padding-bottom: 0;
     2297        margin-bottom: 0;
     2298    }
     2299}
     2300
     2301.aidf-review-banner__content {
     2302    display: flex;
     2303    align-items: center;
     2304    gap: var(--aidf-sp-3);
     2305    min-height: 32px;
     2306}
     2307
     2308.aidf-review-banner__content[hidden] {
     2309    display: none;
     2310}
     2311
     2312.aidf-review-banner__response {
     2313    animation: aidfFadeIn 0.3s ease both;
     2314}
     2315
     2316.aidf-review-banner__response .aidf-btn {
     2317    flex-shrink: 0;
     2318}
     2319
     2320.aidf-review-banner .aidf-review-banner__response a.aidf-btn--primary {
     2321    color: #ffffff;
     2322}
     2323
     2324.aidf-review-banner .aidf-review-banner__response a.aidf-btn--primary:hover {
     2325    color: #ffffff;
     2326}
     2327
     2328@keyframes aidfFadeIn {
     2329    from { opacity: 0; transform: translateY(-4px); }
     2330    to { opacity: 1; transform: translateY(0); }
     2331}
     2332
     2333.aidf-review-banner__icon {
     2334    color: var(--aidf-orange);
     2335    font-size: 18px;
     2336    width: 18px;
     2337    height: 18px;
     2338    flex-shrink: 0;
     2339}
     2340
     2341.aidf-review-banner__text {
     2342    font-size: var(--aidf-text-sm);
     2343    font-weight: 500;
     2344    color: var(--aidf-text);
     2345    white-space: nowrap;
     2346}
     2347
     2348/* Stars container */
     2349.aidf-review-banner__stars {
     2350    display: flex;
     2351    gap: var(--aidf-sp-1);
     2352    margin: 0 var(--aidf-sp-1);
     2353}
     2354
     2355/* Individual star button */
     2356.aidf-review-star {
     2357    display: flex;
     2358    align-items: center;
     2359    justify-content: center;
     2360    padding: 2px;
     2361    background: none;
     2362    border: none;
     2363    cursor: pointer;
     2364    color: var(--aidf-border);
     2365    transition: color var(--aidf-transition), transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);
     2366    border-radius: var(--aidf-radius-sm);
     2367}
     2368
     2369.aidf-review-star:focus-visible {
     2370    outline: 2px solid var(--aidf-orange);
     2371    outline-offset: 2px;
     2372}
     2373
     2374.aidf-review-star svg {
     2375    width: 22px;
     2376    height: 22px;
     2377    transition: fill var(--aidf-transition), filter var(--aidf-transition);
     2378    fill: transparent;
     2379}
     2380
     2381/* Hover: fill stars up to hovered one */
     2382.aidf-review-banner__stars:hover .aidf-review-star {
     2383    color: var(--aidf-orange);
     2384}
     2385
     2386.aidf-review-banner__stars:hover .aidf-review-star svg {
     2387    fill: var(--aidf-orange);
     2388}
     2389
     2390.aidf-review-banner__stars:hover .aidf-review-star:hover {
     2391    transform: scale(1.2);
     2392}
     2393
     2394.aidf-review-banner__stars:hover .aidf-review-star:hover svg {
     2395    filter: drop-shadow(0 1px 3px rgba(231, 125, 21, 0.35));
     2396}
     2397
     2398.aidf-review-banner__stars:hover .aidf-review-star:hover ~ .aidf-review-star {
     2399    color: var(--aidf-border);
     2400}
     2401
     2402.aidf-review-banner__stars:hover .aidf-review-star:hover ~ .aidf-review-star svg {
     2403    fill: transparent;
     2404}
     2405
     2406/* Dismiss links */
     2407.aidf-review-banner__dismiss {
     2408    display: flex;
     2409    align-items: center;
     2410    gap: var(--aidf-sp-2);
     2411    margin-left: auto;
     2412    flex-shrink: 0;
     2413}
     2414
     2415.aidf-review-dismiss {
     2416    background: rgba(0, 0, 0, 0.04);
     2417    border: 1px solid var(--aidf-border);
     2418    border-radius: var(--aidf-radius-sm);
     2419    padding: var(--aidf-sp-1) var(--aidf-sp-3);
     2420    cursor: pointer;
     2421    font-size: var(--aidf-text-xs);
     2422    color: var(--aidf-text-secondary);
     2423    text-decoration: none;
     2424    transition: all var(--aidf-transition);
     2425    white-space: nowrap;
     2426}
     2427
     2428.aidf-review-dismiss:hover {
     2429    background: rgba(0, 0, 0, 0.08);
     2430    border-color: var(--aidf-text-tertiary);
     2431    color: var(--aidf-text);
     2432}
     2433
     2434.aidf-review-banner__sep {
     2435    display: none;
     2436}
     2437
     2438/* --------------------------------------------------------
     2439   25. Responsive
    22522440   -------------------------------------------------------- */
    22532441@media (max-width: 960px) {
     
    23252513        align-items: flex-start;
    23262514    }
    2327 }
    2328 
    2329 /* --------------------------------------------------------
    2330    25. WordPress Admin Overrides
     2515
     2516    .aidf-review-banner__content {
     2517        flex-wrap: wrap;
     2518    }
     2519
     2520    .aidf-review-banner__dismiss {
     2521        margin-left: 0;
     2522        margin-top: var(--aidf-sp-1);
     2523        width: 100%;
     2524        padding-left: 30px;
     2525    }
     2526}
     2527
     2528/* --------------------------------------------------------
     2529   26. WordPress Admin Overrides
    23312530   -------------------------------------------------------- */
    23322531
     
    23572556
    23582557/* --------------------------------------------------------
    2359    26. Welcome Notice (global WP admin)
     2558   27. Welcome Notice (global WP admin)
    23602559   -------------------------------------------------------- */
    23612560.aidf-welcome-notice {
  • ai-discovery-files/trunk/admin/js/admin.js

    r3472434 r3475304  
    543543        });
    544544
     545        /* -------------------------------------------------------
     546           Review Prompt Banner
     547           ------------------------------------------------------- */
     548        var reviewBanner = $('#aidf-review-banner');
     549
     550        if (reviewBanner.length) {
     551
     552            // Star click handler.
     553            reviewBanner.on('click', '.aidf-review-star', function () {
     554                var rating = parseInt($(this).data('rating'), 10);
     555                var reason;
     556
     557                // Hide the prompt row.
     558                $('#aidf-review-prompt').hide();
     559
     560                if (rating >= 4) {
     561                    $('#aidf-review-thanks').removeAttr('hidden').show();
     562                    reason = 'done';
     563                } else {
     564                    $('#aidf-review-support').removeAttr('hidden').show();
     565                    reason = 'low';
     566                }
     567
     568                // Dismiss via AJAX.
     569                $.post(aidfAdmin.ajaxUrl, {
     570                    action: 'aidf_dismiss_review',
     571                    nonce: aidfAdmin.nonce,
     572                    reason: reason
     573                });
     574
     575            });
     576
     577            // Dismiss link handler (Already reviewed / Not now).
     578            reviewBanner.on('click', '.aidf-review-dismiss', function () {
     579                var reason = $(this).data('reason');
     580
     581                $.post(aidfAdmin.ajaxUrl, {
     582                    action: 'aidf_dismiss_review',
     583                    nonce: aidfAdmin.nonce,
     584                    reason: reason
     585                });
     586
     587                reviewBanner.addClass('aidf-review-banner--out');
     588                setTimeout(function () { reviewBanner.remove(); }, 300);
     589            });
     590        }
     591
    545592    }); // end DOM ready
    546593
  • ai-discovery-files/trunk/admin/views/settings-page.php

    r3472434 r3475304  
    6969    <!-- Content -->
    7070    <div class="aidf-content">
     71        <?php if ( AIDF_Admin::should_show_review_banner() ) : ?>
     72            <?php include AIDF_PLUGIN_DIR . 'admin/views/partials/review-banner.php'; ?>
     73        <?php endif; ?>
     74
    7175        <?php settings_errors( 'aidf_settings' ); ?>
    7276
  • ai-discovery-files/trunk/ai-discovery-files.php

    r3474794 r3475304  
    44 * Plugin URI:        https://www.ai-visibility.org.uk/wordpress-plugin/ai-discovery-files/
    55 * Description:       Improve your AI Visibility by generating AI Discovery Files so AI systems like ChatGPT, Claude, and Gemini can correctly discover, interpret, and cite your website.
    6  * Version:           1.1.1
     6 * Version:           1.2.0
    77 * Requires at least: 6.2
    88 * Requires PHP:      8.0
     
    2424 * Plugin constants.
    2525 */
    26 define( 'AIDF_VERSION', '1.1.1' );
     26define( 'AIDF_VERSION', '1.2.0' );
    2727define( 'AIDF_PLUGIN_FILE', __FILE__ );
    2828define( 'AIDF_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
     
    5050    }
    5151
     52    if ( false === get_option( 'aidf_activated_at' ) ) {
     53        update_option( 'aidf_activated_at', time(), false );
     54    }
     55
    5256    set_transient( 'aidf_activation_redirect', true, 30 );
    5357}
  • ai-discovery-files/trunk/readme.txt

    r3474794 r3475304  
    55Tested up to: 6.9
    66Requires PHP: 8.0
    7 Stable tag: 1.1.1
     7Stable tag: 1.2.0
    88License: GPLv2 or later
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
     
    167167
    168168== Changelog ==
     169
     170= 1.2.0 =
     171* Add review prompt banner on settings page with interactive star rating
     172* Smart trigger: only shows after settings saved, 2+ active files, and 3+ days active
     173* Stars 4-5 link to WordPress.org review page; stars 1-3 show support link
     174* "Already reviewed" permanently dismisses; "Not now" snoozes for 90 days
     175* Polished SVG star animations with brand-consistent design
    169176
    170177= 1.1.1 =
  • ai-discovery-files/trunk/uninstall.php

    r3472044 r3475304  
    2020delete_metadata( 'user', 0, 'aidf_welcome_dismissed', '', true );
    2121
     22// Remove review prompt data from all users.
     23delete_metadata( 'user', 0, 'aidf_review_dismissed', '', true );
     24delete_metadata( 'user', 0, 'aidf_review_snoozed', '', true );
     25
     26// Remove review prompt options.
     27delete_option( 'aidf_activated_at' );
     28delete_option( 'aidf_settings_saved_at' );
     29
    2230// Flush rewrite rules to remove our custom rules.
    2331flush_rewrite_rules();
Note: See TracChangeset for help on using the changeset viewer.