admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce( 'replyvane_kb' ), // Ticks "refresh questions" on the first scan, when there are no questions yet. 'firstRun' => 0 === count( Replyvane_Store::items() ) ? '1' : '0', 'i18n' => array( 'stopped' => __( 'The scan stopped. Please try again.', 'replyvane-chat-support' ), 'reading' => __( 'Reading pages…', 'replyvane-chat-support' ), 'of' => __( 'of', 'replyvane-chat-support' ), 'done' => __( 'Done. Reloading…', 'replyvane-chat-support' ), 'finding' => __( 'Finding public pages…', 'replyvane-chat-support' ), 'noStart' => __( 'Could not start the scan.', 'replyvane-chat-support' ), 'noPages' => __( 'No public pages found.', 'replyvane-chat-support' ), ), ) ); } private static function url( array $args = array() ) { return add_query_arg( array_merge( array( 'page' => self::SLUG ), $args ), admin_url( 'admin.php' ) ); } public static function menu() { add_submenu_page( 'replyvane', 'Website knowledge', 'Website knowledge', 'manage_options', self::SLUG, array( __CLASS__, 'render' ), 1 ); } /** Progress and results messages on the plugin's own screens. */ public static function notices() { $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null; if ( ! $screen || false === strpos( (string) $screen->id, 'replyvane' ) || ! current_user_can( 'manage_options' ) ) { return; } $report = get_option( 'replyvane_autogen_report' ); if ( is_array( $report ) ) { delete_option( 'replyvane_autogen_report' ); printf( '

Your website has been read. %d questions were created or refreshed from its pages. Review them and edit anything you like; edited questions are never overwritten.

', (int) $report['added'] + (int) $report['updated'], esc_url( admin_url( 'admin.php?page=replyvane' ) ) ); return; } $stats = Replyvane_Knowledge::stats(); // Never read yet (for example because WP-Cron doesn't run on this host): // offer to read it now, which works without WP-Cron. if ( 0 === (int) $stats['pages'] && 0 === (int) $stats['remaining'] && ! isset( $_GET['autoscan'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification printf( '

The chatbot hasn\'t read your website yet, so typed questions can only be matched to your FAQ list. Read my website now

', esc_url( self::url( array( 'autoscan' => 1 ) ) ) ); return; } $left = (int) $stats['remaining']; if ( $left > 0 && ! get_transient( Replyvane_Knowledge::LOCK ) ) { // Keep a stalled scan moving while you're on these screens. Replyvane_Knowledge::process_batch( 2 ); $left = Replyvane_Knowledge::remaining(); } if ( get_option( 'replyvane_autogen_pending' ) || $left > 0 ) { printf( '

Reading your website… %s See progress

', $left > 0 ? esc_html( sprintf( '%d pages left.', $left ) ) : 'This starts within a minute.', esc_url( self::url() ) ); } } public static function ajax_start() { check_ajax_referer( 'replyvane_kb' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( array( 'message' => 'Not allowed.' ), 403 ); } if ( ! empty( $_POST['regenerate'] ) ) { update_option( 'replyvane_autogen_pending', 1, false ); } delete_transient( Replyvane_Knowledge::LOCK ); $total = Replyvane_Knowledge::start_full_reindex(); if ( 0 === $total ) { // Nothing public to read; still let generation run (it will find little). do_action( 'replyvane_kb_scan_complete' ); } wp_send_json_success( array( 'total' => $total ) ); } public static function ajax_step() { check_ajax_referer( 'replyvane_kb' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( array( 'message' => 'Not allowed.' ), 403 ); } $remaining = Replyvane_Knowledge::process_batch( 3 ); wp_send_json_success( array_merge( Replyvane_Knowledge::stats(), array( 'remaining' => $remaining ) ) ); } public static function handle_generate() { if ( ! current_user_can( 'manage_options' ) ) { wp_die( 'You are not allowed to do this.' ); } check_admin_referer( 'replyvane_generate' ); $report = Replyvane_Generator::generate(); set_transient( 'replyvane_gen_' . get_current_user_id(), $report, 300 ); wp_safe_redirect( self::url() ); exit; } public static function render() { global $wpdb; $stats = Replyvane_Knowledge::stats(); $table = Replyvane_Knowledge::table(); $found = (int) $wpdb->get_var( $wpdb->prepare( 'SELECT COUNT(*) FROM %i', Replyvane_Knowledge::harvest_table() ) ); $auto = count( array_filter( Replyvane_Store::items(), function ( $r ) { return 'auto' === $r['source']; } ) ); $pages = $wpdb->get_results( $wpdb->prepare( "SELECT post_id, url, MIN(title) AS title, MIN(source) AS source, COUNT(*) AS chunks FROM %i GROUP BY post_id, url ORDER BY title ASC", $table ), ARRAY_A ); $test = isset( $_GET['test'] ) ? sanitize_text_field( wp_unslash( $_GET['test'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification // Start reading straight away when asked to, or when nothing has been read yet. $autoscan = isset( $_GET['autoscan'] ) || ( 0 === (int) $stats['pages'] && 0 === (int) $stats['remaining'] ); // phpcs:ignore WordPress.Security.NonceVerification $gen = get_transient( 'replyvane_gen_' . get_current_user_id() ); if ( $gen ) { delete_transient( 'replyvane_gen_' . get_current_user_id() ); } ?>

Website knowledge

See questions

The chatbot reads every public page of this website, exactly as a logged-out visitor sees it, so it can answer typed questions from your own content. Private, draft and password-protected pages, account, cart and checkout pages, anything that needs a login, and pages you keep out in Settings are never read.

What the chatbot knows

Pages it can answer from
Passages indexed
Q&A found on your pages
Questions created from the website
Last full scan
Pages waiting to be read

Scan the website

Pages are re-read automatically when you update them, and the whole site once a day. Scan now after big changes.

Create questions from the website

Builds starter questions from what was read. It uses:

  • FAQ sections and accordions already on your pages
  • your About, Contact, Prices or Plans, Services, Booking and policy pages
  • contact details and opening hours
  • shop products, if you use WooCommerce

Running it again refreshes those questions. Questions you added or edited yourself are never changed.

Try a question

See the answer a visitor would get when their typed question doesn't match one of your FAQ questions.

get_error_message() ) ); } else { echo esc_html__( 'WordPress AI was not asked: nothing on your website relates to this question.', 'replyvane-chat-support' ); } ?>

From: ' . esc_html( $src['title'] ) . ''; } echo wp_kses_post( implode( ', ', $links ) ); if ( ! empty( $result['ai'] ) ) { echo esc_html( ' · written by ' . ( ! empty( $result['provider'] ) ? $result['provider'] : Replyvane_AI::label() ) . ' from these pages' ); } else { echo esc_html( ' · built-in engine, match ' . round( $result['confidence'] * 100 ) . '%' ); } ?>

No confident answer on the website. The visitor would see the closest FAQ questions, or the "couldn't find an answer" message. Consider adding this as a question.

Pages the chatbot can use ()

If anything here should stay private, tick it under Settings → Pages to keep out. It is removed as soon as you save. "Rendered" means the page was read exactly as a visitor sees it; "Database" means the site couldn't request itself, so the content was rendered in PHP as a logged-out visitor instead.

PageAddressRead asPassages
Nothing read yet. Click "Scan website now".