admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce( self::NONCE_KEY ), 'action' => self::AJAX_ACTION, 'pluginBase' => plugin_basename( AI_SEARCH_PATH . 'ai-search.php' ), 'i18n' => [ 'title' => __( 'Before you leave — help us improve AI Search', 'ai-search' ), 'intro' => __( 'What was the main reason for deactivating? This takes 5 seconds and shapes the next release.', 'ai-search' ), 'reasons' => [ 'too_complicated' => __( 'Too complicated to set up or use', 'ai-search' ), 'poor_results' => __( 'Search results were poor', 'ai-search' ), 'broke' => __( 'Something broke or errored on my site', 'ai-search' ), 'switched' => __( 'Switched to another plugin', 'ai-search' ), 'testing' => __( 'Just testing / temporary site', 'ai-search' ), 'other' => __( 'Other', 'ai-search' ), ], 'competitorLabel' => __( 'Which plugin? (optional)', 'ai-search' ), 'commentLabel' => __( 'Anything else you want to share? (optional)', 'ai-search' ), 'submit' => __( 'Send and deactivate', 'ai-search' ), 'skip' => __( 'Skip and deactivate', 'ai-search' ), 'cancel' => __( 'Cancel', 'ai-search' ), 'thanks' => __( 'Thanks — deactivating…', 'ai-search' ), ], ] ); } /** * Modal markup, hidden by default. Rendered once in the plugins.php * footer so the JS can toggle its visibility without extra requests. * All copy is injected via JS (from wp_localize_script) so the modal * remains fully translatable. */ public function render_modal() { ?> 10, 'blocking' => true, 'headers' => [ 'Content-Type' => 'application/json' ], 'body' => wp_json_encode( [ 'origin' => home_url(), 'token' => $token, 'reason' => $reason, 'competitor' => $competitor, 'comment' => $comment, ] ), ] ); if ( is_wp_error( $response ) ) { error_log( '[ai-search] deactivation feedback forward failed: ' . $response->get_error_message() ); } wp_send_json_success(); } }