post_type, self::indexable_types(), true ) ) return; $url = get_permalink( $post->ID ); if ( $url ) self::submit( [ $url ] ); } /** * Fires when an already-published post is updated. */ public static function on_post_updated( $post_id, $post_after, $post_before ) { if ( $post_after->post_status !== 'publish' ) return; if ( ! self::auto_enabled() ) return; if ( wp_is_post_revision( $post_after ) ) return; if ( ! in_array( $post_after->post_type, self::indexable_types(), true ) ) return; $url = get_permalink( $post_id ); if ( $url ) self::submit( [ $url ] ); } /* Core submit ---------------------------------------------------------- */ /** * Submits one or more URLs to IndexNow. * * @param string[] $urls Absolute URLs. * @return true|WP_Error */ public static function submit( array $urls ) { $urls = array_values( array_unique( array_filter( $urls ) ) ); if ( empty( $urls ) ) return new WP_Error( 'no_urls', 'No URLs provided.' ); $key = self::get_key(); $host = parse_url( home_url(), PHP_URL_HOST ); $payload = wp_json_encode( [ 'host' => $host, 'key' => $key, 'keyLocation' => self::key_file_url(), 'urlList' => $urls, ] ); $response = wp_remote_post( self::INDEXNOW_URL, [ 'headers' => [ 'Content-Type' => 'application/json; charset=utf-8' ], 'body' => $payload, 'timeout' => 15, ] ); if ( is_wp_error( $response ) ) { self::log_entries( $urls, 'error', 0 ); return $response; } $code = (int) wp_remote_retrieve_response_code( $response ); $success = in_array( $code, [ 200, 202 ], true ); self::log_entries( $urls, $success ? 'submitted' : 'failed', $code ); if ( ! $success ) { return new WP_Error( 'indexnow_' . $code, "IndexNow returned HTTP {$code}." ); } return true; } /* Log ------------------------------------------------------------------ */ private static function log_entries( array $urls, $status, $code ) { $log = get_option( self::OPT_LOG, [] ); $now = time(); foreach ( array_reverse( $urls ) as $url ) { array_unshift( $log, [ 'url' => $url, 'status' => $status, 'code' => $code, 'time' => $now, ] ); } update_option( self::OPT_LOG, array_slice( $log, 0, self::LOG_LIMIT ), false ); } public static function get_log() { return get_option( self::OPT_LOG, [] ); } /* Helpers -------------------------------------------------------------- */ public static function auto_enabled() { // Default is OFF ('0') - user must explicitly enable auto-submit in Settings. return (bool) get_option( self::OPT_AUTO, '0' ); } public static function indexable_types() { return array_values( get_post_types( [ 'public' => true ], 'names' ) ); } /* AJAX handlers -------------------------------------------------------- */ public static function ajax_submit() { check_ajax_referer( 'awbseo_nonce', 'nonce' ); if ( ! current_user_can( 'manage_options' ) ) wp_send_json_error( 'Forbidden', 403 ); $raw = isset( $_POST['urls'] ) ? (array) $_POST['urls'] : []; $urls = array_filter( array_map( 'esc_url_raw', $raw ) ); if ( empty( $urls ) ) wp_send_json_error( 'No valid URLs provided.' ); $result = self::submit( array_values( $urls ) ); if ( is_wp_error( $result ) ) wp_send_json_error( $result->get_error_message() ); wp_send_json_success( [ 'submitted' => count( $urls ) ] ); } public static function ajax_submit_all() { check_ajax_referer( 'awbseo_nonce', 'nonce' ); if ( ! current_user_can( 'manage_options' ) ) wp_send_json_error( 'Forbidden', 403 ); $posts = get_posts( [ 'post_type' => self::indexable_types(), 'post_status' => 'publish', 'posts_per_page' => 500, 'fields' => 'ids', ] ); $urls = []; foreach ( $posts as $id ) { $u = get_permalink( $id ); if ( $u ) $urls[] = $u; } if ( empty( $urls ) ) wp_send_json_error( 'No published posts found.' ); // IndexNow allows up to 10,000 URLs per call - submit in batches of 200. $chunks = array_chunk( $urls, 200 ); $errors = []; $success = 0; foreach ( $chunks as $chunk ) { $r = self::submit( $chunk ); if ( is_wp_error( $r ) ) { $errors[] = $r->get_error_message(); } else { $success += count( $chunk ); } } wp_send_json_success( [ 'submitted' => $success, 'errors' => $errors, 'total' => count( $urls ), ] ); } public static function ajax_generate_key() { check_ajax_referer( 'awbseo_nonce', 'nonce' ); if ( ! current_user_can( 'manage_options' ) ) wp_send_json_error( 'Forbidden', 403 ); $key = self::make_key(); update_option( self::OPT_KEY, $key, false ); // Clear log - old key is now invalid. update_option( self::OPT_LOG, [], false ); wp_send_json_success( [ 'key' => $key, 'file_url' => home_url( '/' . $key . '.txt' ), ] ); } public static function ajax_clear_log() { check_ajax_referer( 'awbseo_nonce', 'nonce' ); if ( ! current_user_can( 'manage_options' ) ) wp_send_json_error( 'Forbidden', 403 ); update_option( self::OPT_LOG, [], false ); wp_send_json_success(); } /* Meta box ------------------------------------------------------------- */ public static function register_meta_box() { foreach ( self::indexable_types() as $pt ) { add_meta_box( 'awbseo_instant_indexing', '⚡ Instant Indexing', [ __CLASS__, 'render_meta_box' ], $pt, 'side', 'high' ); } } public static function render_meta_box( $post ) { $permalink = get_permalink( $post->ID ); $published = $post->post_status === 'publish'; $nonce = wp_create_nonce( 'awbseo_nonce' ); // Find last log entry for this URL. $last = null; foreach ( self::get_log() as $entry ) { if ( $entry['url'] === $permalink ) { $last = $entry; break; } } $green = '#04785b'; $red = '#aa3535'; $muted = '#7c706c'; ?>
· ago
Not yet submitted to IndexNow.
Publish this post to enable instant indexing.