Plugin Already Installed

You have already installed this plugin. It might have a different name but it has the same functionality - it might be called something like "SEO One-Click Publishing".

If you would like to replace the existing plugin with this version, please remove the old one first. Keep in mind you might have to set up the integration again.

Go to Plugins Page

Settings saved.

'; } if (isset($_POST['create_application_password'])) { create_application_password_for_user(); echo '

Application password created.

'; } if (isset($_POST['delete_application_password'])) { delete_application_password_for_user(); echo '

Application password deleted.

'; } $enable_meta_sync = get_option('adaptify_seo_enable_meta_sync', '1'); ?>

SEO Settings

Application Password Management

The application password is used to securely connect your WordPress site with SEO tools. This password should be treated with the same level of security as any other password.

get_param('yoast_meta'); if (is_array($yoast_meta)) { if (isset($yoast_meta['yoast_wpseo_metadesc'])) { update_post_meta($post->ID, 'rank_math_description', $yoast_meta['yoast_wpseo_metadesc']); } if (isset($yoast_meta['yoast_wpseo_metakeywords'])) { update_post_meta($post->ID, 'rank_math_focus_keyword', $yoast_meta['yoast_wpseo_metakeywords']); } if (isset($yoast_meta['yoast_wpseo_title'])) { update_post_meta($post->ID, 'rank_math_title', $yoast_meta['yoast_wpseo_title']); } } } }, 10, 3); if (!class_exists('Yoast_To_REST_API')) { class Yoast_To_REST_API { protected $keys = array( 'yoast_wpseo_focuskw', 'yoast_wpseo_title', 'yoast_wpseo_metadesc', 'yoast_wpseo_linkdex', 'yoast_wpseo_metakeywords', 'yoast_wpseo_meta-robots-noindex', 'yoast_wpseo_meta-robots-nofollow', 'yoast_wpseo_meta-robots-adv', 'yoast_wpseo_canonical', 'yoast_wpseo_redirect', 'yoast_wpseo_opengraph-title', 'yoast_wpseo_opengraph-description', 'yoast_wpseo_opengraph-image', 'yoast_wpseo_twitter-title', 'yoast_wpseo_twitter-description', 'yoast_wpseo_twitter-image' ); function __construct() { add_action( 'rest_api_init', array( $this, 'add_yoast_data' ) ); } function add_yoast_data() { // Posts register_rest_field( 'post', 'yoast_meta', array( 'get_callback' => array( $this, 'wp_api_encode_yoast' ), 'update_callback' => array( $this, 'wp_api_update_yoast' ), 'schema' => null, ) ); // Pages register_rest_field( 'page', 'yoast_meta', array( 'get_callback' => array( $this, 'wp_api_encode_yoast' ), 'update_callback' => array( $this, 'wp_api_update_yoast' ), 'schema' => null, ) ); // Category register_rest_field( 'category', 'yoast_meta', array( 'get_callback' => array( $this, 'wp_api_encode_yoast_category' ), 'update_callback' => null, 'schema' => null, ) ); // Tag register_rest_field( 'tag', 'yoast_meta', array( 'get_callback' => array( $this, 'wp_api_encode_yoast_tag' ), 'update_callback' => null, 'schema' => null, ) ); // Public custom post types $types = get_post_types( array( 'public' => true, '_builtin' => false ) ); foreach ( $types as $key => $type ) { register_rest_field( $type, 'yoast_meta', array( 'get_callback' => array( $this, 'wp_api_encode_yoast' ), 'update_callback' => array( $this, 'wp_api_update_yoast' ), 'schema' => null, ) ); } } /** * Updates post meta with values from post/put request. * * @param array $value * @param object $data * @param string $field_name * * @return array */ function wp_api_update_yoast( $value, $data, $field_name ) { foreach ( $value as $k => $v ) { if ( in_array( $k, $this->keys ) ) { ! empty( $k ) ? update_post_meta( $data->ID, '_' . $k, $v ) : null; } } return $this->wp_api_encode_yoast( $data->ID, null, null ); } function wp_api_encode_yoast( $p, $field_name, $request ) { $wpseo_frontend = WPSEO_Frontend_To_REST_API::get_instance(); $wpseo_frontend->reset(); query_posts( array( 'p' => $p['id'], // ID of a page, post, or custom type 'post_type' => 'any' ) ); the_post(); $yoast_meta = array( 'yoast_wpseo_title' => $wpseo_frontend->get_content_title(), 'yoast_wpseo_metadesc' => $wpseo_frontend->metadesc( false ), 'yoast_wpseo_canonical' => $wpseo_frontend->canonical( false ), ); /** * Filter the returned yoast meta. * * @since 1.4.2 * @param array $yoast_meta Array of metadata to return from Yoast. * @param \WP_Post $p The current post object. * @param \WP_REST_Request $request The REST request. * @return array $yoast_meta Filtered meta array. */ $yoast_meta = apply_filters( 'wpseo_to_api_yoast_meta', $yoast_meta, $p, $request ); wp_reset_query(); return (array) $yoast_meta; } private function wp_api_encode_taxonomy() { $wpseo_frontend = WPSEO_Frontend_To_REST_API::get_instance(); $wpseo_frontend->reset(); $yoast_meta = array( 'yoast_wpseo_title' => $wpseo_frontend->get_taxonomy_title(), 'yoast_wpseo_metadesc' => $wpseo_frontend->metadesc( false ), ); /** * Filter the returned yoast meta for a taxonomy. * * @since 1.4.2 * @param array $yoast_meta Array of metadata to return from Yoast. * @return array $yoast_meta Filtered meta array. */ $yoast_meta = apply_filters( 'wpseo_to_api_yoast_taxonomy_meta', $yoast_meta ); return (array) $yoast_meta; } function wp_api_encode_yoast_category( $category ) { query_posts( array( 'cat' => $category['id'], ) ); the_post(); $res = $this->wp_api_encode_taxonomy(); wp_reset_query(); return $res; } function wp_api_encode_yoast_tag( $tag ) { query_posts( array( 'tag_id' => $tag['id'], ) ); the_post(); $res = $this->wp_api_encode_taxonomy(); wp_reset_query(); return $res; } } } if (!function_exists('WPAPIYoast_init')) { function WPAPIYoast_init() { if ( class_exists( 'WPSEO_Frontend' ) ) { include __DIR__ . '/classes/class-wpseo-frontend-to-rest-api.php'; $yoast_To_REST_API = new Yoast_To_REST_API(); } } } if (!function_exists('create_application_password_for_user')) { function create_application_password_for_user() { global $plugin_error_message; if ( ! current_user_can( 'manage_options' ) ) { return; } $user_id = get_current_user_id(); $custom_date = date('YmdHis'); $app_name = 'adaptify' . $custom_date; $user = get_userdata($user_id); if (!$user) { $plugin_error_message = "Can't access your username, please contact support."; add_action( 'admin_notices', 'application_password_fail' ); return; } $new_password = WP_Application_Passwords::create_new_application_password( $user_id, array( 'name' => $app_name ) ); if ( is_wp_error( $new_password ) ) { $plugin_error_message = "Error creating application password."; add_action( 'admin_notices', 'application_password_fail' ); return; } $post_data = array( 'user_name' => $user->user_login, 'application_pw' => $new_password[0], 'site_url' => get_site_url() ); $response = wp_remote_post( 'https://api.ttsp4712.ai/add-wp-pw', array( 'method' => 'POST', 'headers' => array('Content-Type' => 'application/json; charset=utf-8'), 'body' => json_encode($post_data), 'data_format' => 'body' )); if ( is_wp_error( $response ) ) { $plugin_error_message = "Error in sending POST request: " . $response->get_error_message(); add_action( 'admin_notices', 'application_password_fail' ); } } } if (!function_exists('delete_application_password_for_user')) { function delete_application_password_for_user() { global $plugin_error_message; if ( ! current_user_can( 'manage_options' ) ) { return; } $user_id = get_current_user_id(); $user = get_userdata($user_id); if (!$user) { $plugin_error_message = "Can't access your username, please contact support."; add_action( 'admin_notices', 'application_password_fail' ); return; } $app_passwords = WP_Application_Passwords::get_user_application_passwords( $user_id ); if ( !empty($app_passwords) ) { foreach ( $app_passwords as $app_password ) { WP_Application_Passwords::delete_application_password( $user_id, $app_password['uuid'] ); } } else { $plugin_error_message = "No application passwords found to delete."; add_action( 'admin_notices', 'application_password_fail' ); } } } if (!function_exists('application_password_fail')) { function application_password_fail() { global $plugin_error_message; printf( '

%s

', esc_html( $plugin_error_message ) ); } } // ============================================ // WP-CRON FALLBACK PUBLISHING (429 Recovery) // ============================================ // Add custom cron interval (15 minutes) add_filter('cron_schedules', function($schedules) { $schedules['fifteen_minutes'] = array( 'interval' => 900, 'display' => __('Every 15 Minutes') ); return $schedules; }); // Ensure cron is always scheduled (self-heals if cron was cleared by DB issues, migrations, etc.) // This is the recommended pattern per WordPress Plugin Handbook if (!function_exists('adaptify_schedule_fallback_cron')) { function adaptify_schedule_fallback_cron() { if (!wp_next_scheduled('adaptify_fallback_publish_hook')) { wp_schedule_event(time(), 'fifteen_minutes', 'adaptify_fallback_publish_hook'); error_log('[adaptify-fallback] Scheduled fallback cron job'); } } } add_action('init', 'adaptify_schedule_fallback_cron'); // Unschedule fallback cron on plugin deactivation if (!function_exists('adaptify_unschedule_fallback_cron')) { function adaptify_unschedule_fallback_cron() { $timestamp = wp_next_scheduled('adaptify_fallback_publish_hook'); if ($timestamp) { wp_unschedule_event($timestamp, 'adaptify_fallback_publish_hook'); error_log('[adaptify-fallback] Unscheduled fallback cron job'); } } } register_deactivation_hook(__FILE__, 'adaptify_unschedule_fallback_cron'); // Hook the fallback processing function add_action('adaptify_fallback_publish_hook', 'adaptify_process_fallback_articles'); // Main function to process fallback articles if (!function_exists('adaptify_process_fallback_articles')) { function adaptify_process_fallback_articles() { error_log('[adaptify-fallback] Starting fallback article check'); $site_url = get_site_url(); // Fetch pending articles from Adaptify API $response = wp_remote_post('https://api.ttsp4712.ai/open/wp-pending-articles', array( 'method' => 'POST', 'headers' => array('Content-Type' => 'application/json'), 'body' => json_encode(array('site_url' => $site_url)), 'timeout' => 30 )); if (is_wp_error($response)) { error_log('[adaptify-fallback] Error fetching pending articles: ' . $response->get_error_message()); return; } $body = json_decode(wp_remote_retrieve_body($response), true); if (empty($body['articles']) || !is_array($body['articles'])) { error_log('[adaptify-fallback] No pending articles found'); return; } error_log('[adaptify-fallback] Found ' . count($body['articles']) . ' pending articles'); foreach ($body['articles'] as $article) { adaptify_publish_article_locally($article, $site_url); } } } // Publish a single article locally using wp_insert_post if (!function_exists('adaptify_publish_article_locally')) { function adaptify_publish_article_locally($article, $site_url) { error_log('[adaptify-fallback] Publishing: ' . $article['title']); // Prepare post data $post_data = array( 'post_title' => sanitize_text_field($article['title']), 'post_content' => wp_kses_post($article['content']), 'post_status' => isset($article['status']) ? $article['status'] : 'publish', 'post_type' => 'post', 'comment_status'=> isset($article['comment_status']) ? $article['comment_status'] : 'closed', 'ping_status' => 'closed' ); // Set excerpt if provided if (!empty($article['excerpt'])) { $post_data['post_excerpt'] = sanitize_text_field($article['excerpt']); } // Set category if provided if (!empty($article['category_id'])) { $post_data['post_category'] = array(intval($article['category_id'])); } // Set author if provided if (!empty($article['author_id'])) { $post_data['post_author'] = intval($article['author_id']); } // Set slug if provided if (!empty($article['slug'])) { $post_data['post_name'] = sanitize_title($article['slug']); } // Set tags if provided if (!empty($article['tag_ids']) && is_array($article['tag_ids'])) { $post_data['tags_input'] = array_map('intval', $article['tag_ids']); } // Insert the post $post_id = wp_insert_post($post_data, true); if (is_wp_error($post_id)) { error_log('[adaptify-fallback] Failed to create post: ' . $post_id->get_error_message()); adaptify_send_callback($article, $site_url, 'failed', 0, '', $post_id->get_error_message()); return; } error_log('[adaptify-fallback] Created post ID: ' . $post_id); // Handle featured image if provided if (!empty($article['featured_image_url'])) { require_once(ABSPATH . 'wp-admin/includes/media.php'); require_once(ABSPATH . 'wp-admin/includes/file.php'); require_once(ABSPATH . 'wp-admin/includes/image.php'); $image_alt = !empty($article['featured_image_alt']) ? sanitize_text_field($article['featured_image_alt']) : sanitize_text_field($article['title']); $image_id = media_sideload_image($article['featured_image_url'], $post_id, $article['title'], 'id'); if (!is_wp_error($image_id)) { set_post_thumbnail($post_id, $image_id); // Set alt text on the attachment update_post_meta($image_id, '_wp_attachment_image_alt', $image_alt); error_log('[adaptify-fallback] Set featured image: ' . $image_id); } else { error_log('[adaptify-fallback] Failed to set featured image: ' . $image_id->get_error_message()); } } // Set SEO meta fields for all major SEO plugins $meta_description = !empty($article['meta_description']) ? sanitize_text_field($article['meta_description']) : ''; $focus_keyword = !empty($article['focus_keyword']) ? sanitize_text_field($article['focus_keyword']) : ''; $meta_title = !empty($article['meta_title']) ? sanitize_text_field($article['meta_title']) : sanitize_text_field($article['title']); $secondary_keywords = !empty($article['secondary_keywords']) && is_array($article['secondary_keywords']) ? implode(',', array_map('sanitize_text_field', $article['secondary_keywords'])) : $focus_keyword; $og_article_section = !empty($article['og_article_section']) ? sanitize_text_field($article['og_article_section']) : ''; $og_article_tags = !empty($article['og_article_tags']) ? sanitize_text_field($article['og_article_tags']) : $focus_keyword; $og_image = !empty($article['og_image']) ? esc_url_raw($article['og_image']) : ''; $twitter_image = !empty($article['twitter_image']) ? esc_url_raw($article['twitter_image']) : ''; // Yoast SEO meta if ($meta_description) { update_post_meta($post_id, '_yoast_wpseo_metadesc', $meta_description); } if ($focus_keyword) { update_post_meta($post_id, '_yoast_wpseo_focuskw', $focus_keyword); } if ($meta_title) { update_post_meta($post_id, '_yoast_wpseo_title', $meta_title); } if ($secondary_keywords) { update_post_meta($post_id, '_yoast_wpseo_metakeywords', $secondary_keywords); } // RankMath SEO meta if ($meta_description) { update_post_meta($post_id, 'rank_math_description', $meta_description); } if ($focus_keyword) { update_post_meta($post_id, 'rank_math_focus_keyword', $focus_keyword); } if ($meta_title) { update_post_meta($post_id, 'rank_math_title', $meta_title); } // AIOSEO meta if ($meta_title) { update_post_meta($post_id, '_aioseo_title', $meta_title); update_post_meta($post_id, '_aioseo_og_title', $meta_title); update_post_meta($post_id, '_aioseo_twitter_title', $meta_title); } if ($meta_description) { update_post_meta($post_id, '_aioseo_description', $meta_description); update_post_meta($post_id, '_aioseo_og_description', $meta_description); update_post_meta($post_id, '_aioseo_twitter_description', $meta_description); } if ($og_article_section) { update_post_meta($post_id, '_aioseo_og_article_section', $og_article_section); } if ($og_article_tags) { update_post_meta($post_id, '_aioseo_og_article_tags', $og_article_tags); } if ($og_image) { update_post_meta($post_id, '_aioseo_og_image', $og_image); } if ($twitter_image) { update_post_meta($post_id, '_aioseo_twitter_image', $twitter_image); } // SEOPress meta if ($meta_title) { update_post_meta($post_id, '_seopress_titles_title', $meta_title); update_post_meta($post_id, '_seopress_social_fb_title', $meta_title); update_post_meta($post_id, '_seopress_social_twitter_title', $meta_title); } if ($meta_description) { update_post_meta($post_id, '_seopress_titles_desc', $meta_description); update_post_meta($post_id, '_seopress_social_fb_desc', $meta_description); update_post_meta($post_id, '_seopress_social_twitter_desc', $meta_description); } if ($focus_keyword) { update_post_meta($post_id, '_seopress_analysis_target_kw', $focus_keyword); } if ($og_image) { update_post_meta($post_id, '_seopress_social_fb_img', $og_image); } if ($twitter_image) { update_post_meta($post_id, '_seopress_social_twitter_img', $twitter_image); } // Custom author name meta (used by some themes) if (!empty($article['custom_author_name'])) { update_post_meta($post_id, 'custom_author_name', sanitize_text_field($article['custom_author_name'])); } // Schema markup (JSON-LD) - store for RankMath/AIOSEO if (!empty($article['schema_markup'])) { // RankMath stores schema as serialized array update_post_meta($post_id, 'rank_math_schema_Article', $article['schema_markup']); // Also store as raw JSON for themes that use it update_post_meta($post_id, '_schema_json_ld', $article['schema_markup']); } // Get the post URL $post_url = get_permalink($post_id); // Send success callback adaptify_send_callback($article, $site_url, 'success', $post_id, $post_url, ''); error_log('[adaptify-fallback] Successfully published: ' . $post_url); } } // Send callback to Adaptify API if (!function_exists('adaptify_send_callback')) { function adaptify_send_callback($article, $site_url, $status, $post_id, $post_url, $error_message) { $callback_data = array( 'site_url' => $site_url, 'article_id' => $article['article_id'], 'keyword_id' => $article['keyword_id'], 'post_id' => $post_id, 'post_url' => $post_url, 'status' => $status, 'error_message' => $error_message ); $response = wp_remote_post('https://api.ttsp4712.ai/open/wp-publish-callback', array( 'method' => 'POST', 'headers' => array('Content-Type' => 'application/json'), 'body' => json_encode($callback_data), 'timeout' => 15 )); if (is_wp_error($response)) { error_log('[adaptify-fallback] Callback failed: ' . $response->get_error_message()); } else { error_log('[adaptify-fallback] Callback sent successfully'); } } } ?>