'','client_id'=>'','secret'=>'','marketplace'=>'www.amazon.com')); } /** A site counts as set up once it has an Amazon tag or Creators API credentials. */ function azlinkpro_setup_configured() { $options = azlinkpro_setup_amazon_options(); return $options['tag'] !== '' || $options['client_id'] !== ''; } function azlinkpro_setup_status() { $options = azlinkpro_setup_amazon_options(); // Paid builds add the AI keys (includes/premium/setup-ai.php). return apply_filters('azlinkpro_setup_status', array( 'tag' => $options['tag'] !== '', 'api' => $options['client_id'] !== '' && $options['secret'] !== '', )); } /** Called on activation: open the wizard once, only on sites that are not set up yet. */ function azlinkpro_setup_flag_redirect() { if (get_option('azlinkpro_setup_state', '') !== '' || azlinkpro_setup_configured()) { return; } set_transient('azlinkpro_setup_redirect', 1, 5 * MINUTE_IN_SECONDS); } function azlinkpro_setup_maybe_redirect() { if (!get_transient('azlinkpro_setup_redirect')) { return; } // Freemius shows its opt-in or license screen first, then opens the Dashboard; the wizard follows. if (function_exists('azlinkpro_fs') && azlinkpro_fs()->is_activation_mode()) { return; } delete_transient('azlinkpro_setup_redirect'); if (wp_doing_ajax() || is_network_admin() || isset($_GET['activate-multi']) || !current_user_can('manage_options')) { return; } // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- WordPress's own bulk-activation flag wp_safe_redirect(azlinkpro_setup_url()); exit; } add_action('admin_init', 'azlinkpro_setup_maybe_redirect'); function azlinkpro_setup_menu() { add_submenu_page('azlinkpro', 'AzlinkPRO Setup', 'Setup Wizard', 'manage_options', 'azlinkpro-setup', 'azlinkpro_setup_page'); } add_action('admin_menu', 'azlinkpro_setup_menu', 20); /** Opened from the Dashboard and Settings, so it stays out of the menu. Removed after the page title is set. */ function azlinkpro_setup_hide_menu() { remove_submenu_page('azlinkpro', 'azlinkpro-setup'); } add_action('admin_head', 'azlinkpro_setup_hide_menu'); function azlinkpro_setup_notice() { if (!current_user_can('manage_options') || get_option('azlinkpro_setup_state', '') !== '' || azlinkpro_setup_configured()) { return; } $screen = function_exists('get_current_screen') ? get_current_screen() : null; if (!$screen || strpos((string) $screen->id, 'azlinkpro') === false || $screen->id === 'azlinkpro_page_azlinkpro-setup') { return; } echo '

Welcome to AzlinkPRO. Connect your Amazon account in a few short steps. Run the setup wizard

'; } add_action('admin_notices', 'azlinkpro_setup_notice'); function azlinkpro_setup_assets($hook) { if ($hook !== 'azlinkpro_page_azlinkpro-setup') { return; } $main = AZLINKPRO_PATH . 'azlinkpro.php'; wp_enqueue_style('azlinkpro-setup', plugins_url('assets/setup-wizard.css', $main), array(), AZLINKPRO_VERSION); wp_enqueue_script('azlinkpro-setup', plugins_url('assets/setup-wizard.js', $main), array('jquery'), AZLINKPRO_VERSION, true); wp_localize_script('azlinkpro-setup', 'azlinkproSetup', array( 'ajax' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('azlinkpro_setup'), // The Amazon connection test reuses the Settings handler. 'amazonNonce' => wp_create_nonce('azlinkpro_amazon_test'), 'status' => azlinkpro_setup_status(), 'overview' => admin_url('admin.php?page=azlinkpro'), )); } add_action('admin_enqueue_scripts', 'azlinkpro_setup_assets'); function azlinkpro_setup_page() { if (!current_user_can('manage_options')) { return; } $options = azlinkpro_setup_amazon_options(); $status = azlinkpro_setup_status(); $client_fixed = defined('ATP_AMAZON_CLIENT_ID') && ATP_AMAZON_CLIENT_ID; $secret_fixed = defined('ATP_AMAZON_CLIENT_SECRET') && ATP_AMAZON_CLIENT_SECRET; // Paid builds add an AI writing step (includes/premium/setup-ai.php); the free build goes from the API keys to Finish. $has_ai = function_exists('azlinkpro_setup_ai_step'); $steps = $has_ai ? array(1 => 'Welcome', 2 => 'Amazon Associates', 3 => 'Creators API', 4 => 'AI writing', 5 => 'Finish') : array(1 => 'Welcome', 2 => 'Amazon Associates', 3 => 'Creators API', 5 => 'Finish'); $ai_allowed = $has_ai && azlinkpro_can('ai_pros_cons'); $after_api = $has_ai ? 4 : 5; $start = array_filter(array( array('Comparison table', 'Compare several products side by side.', admin_url('post-new.php?post_type=azlinkpro_table'), ''), array('Product Showcase', 'Feature one product with its photo and highlights.', admin_url('post-new.php?post_type=azlinkpro_showcase'), 'showcase'), array('Product image', 'A clickable Amazon photo with a Check Price button.', admin_url('post-new.php?post_type=azlinkpro_image'), ''), array('Pros & Cons card', 'Balanced pros and cons, written by hand or with AI.', admin_url('post-new.php?post_type=azlinkpro_proscons'), 'pros_cons'), array('AI review article', 'Turn a comparison table into a full review post.', admin_url('admin.php?page=azlinkpro-ai-builder'), 'ai_review_builder'), ), function ($item) { return azlinkpro_can($item[3]); }); ?>

AzlinkPRO Setup

    $label): ?>

Welcome to AzlinkPRO

AzlinkPRO builds Amazon comparison tables, product Showcases, clickable product images and pros & cons cards, and can write full review articles with AI. Setup takes about five minutes.

AzlinkPRO builds Amazon comparison tables and clickable product images. Setup takes about five minutes.

You'll need:

  • Your Amazon Associates account and its tracking ID.
  • Creators API keys from Associates Central, so AzlinkPRO can load product titles, photos and features.
  • Optional: an OpenAI (ChatGPT) or Anthropic (Claude) API key for AI-written reviews and pros & cons.

You can change anything later under AzlinkPRO → Settings.

'Administrator permission required.'), 403); } $op = isset($_POST['op']) && is_string($_POST['op']) ? sanitize_key(wp_unslash($_POST['op'])) : ''; if ($op === 'amazon') { $existing = get_option('azlinkpro_amazon_settings', array()); $existing = is_array($existing) ? $existing : array(); // Fields a step does not send keep their saved value. Saved values are re-slashed // because the shared validator unslashes everything, like a normal form post. // The nonce is checked at the top of this handler. Values stay slashed here because // azlinkpro_validated_configuration() unslashes, validates and sanitizes every field. // phpcs:disable WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.MissingUnslash $field = function ($name, $saved) { return isset($_POST[$name]) && is_string($_POST[$name]) ? $_POST[$name] : wp_slash((string) $saved); }; $input = array( 'azp_settings_form_version' => '1', 'azp_tag' => $field('tag', $existing['tag'] ?? ''), 'azp_marketplace' => $field('marketplace', $existing['marketplace'] ?? 'www.amazon.com'), 'azp_client' => $field('client', $existing['client_id'] ?? ''), // An empty secret keeps the saved one, as on the Settings page. 'azp_secret' => isset($_POST['secret']) && is_string($_POST['secret']) ? $_POST['secret'] : '', 'azp_css_loading' => azlinkpro_asset_mode(), ); // phpcs:enable WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.MissingUnslash if (get_option('azlinkpro_bold_feature_labels', '1') === '1') { $input['azp_bold_colon_labels'] = '1'; } $result = azlinkpro_validated_configuration($input, $existing); if (is_wp_error($result)) { $messages = array( 'invalid_tag' => "That tracking ID doesn't look right. It uses letters, numbers and dashes, like yourstore-20.", 'invalid_marketplace' => 'Choose Amazon.com or Amazon.ca.', 'invalid_credentials' => 'The Credential ID or Secret is too long or contains characters Amazon does not use. Copy them again from Associates Central.', ); $code = $result->get_error_code(); wp_send_json_error(array('message' => $messages[$code] ?? 'Those details could not be saved. Reload the page and try again.')); } azlinkpro_apply_configuration($result, $existing); wp_send_json_success(array('message' => 'Saved.', 'status' => azlinkpro_setup_status())); } if ($op === 'ai' && function_exists('azlinkpro_setup_ai_save')) { azlinkpro_setup_ai_save(); } if ($op === 'finish') { $state = isset($_POST['state']) && $_POST['state'] === 'skipped' ? 'skipped' : 'done'; update_option('azlinkpro_setup_state', $state, false); wp_send_json_success(array('status' => azlinkpro_setup_status())); } wp_send_json_error(array('message' => 'Unknown setup step.'), 400); } add_action('wp_ajax_azlinkpro_setup', 'azlinkpro_setup_ajax');