'installed', 'button_text' => esc_html__('Activate WooCommerce Now', 'ai-flash-tune'), 'action_url' => esc_url($activate_url), 'notice_text' => esc_html__('WooCommerce is installed but not currently active. Please activate it to enable this page.', 'ai-flash-tune') ]; } else { return [ 'status' => 'not_installed', 'button_text' => esc_html__('Install WooCommerce Now', 'ai-flash-tune'), 'action_url' => esc_url($aiflt_install_url), 'notice_text' => esc_html__('This page requires WooCommerce to be installed and active. Please install it to continue.', 'ai-flash-tune') ]; } } /** * Display a custom, well-designed admin notice if WooCommerce is not active. */ function aiflt_woocommerce_missing_notice() { $aiflt_install_url = admin_url('plugin-install.php?s=woocommerce&tab=search&type=term'); ?>

'free'|'pro' */ function aiflt_features() { return (array) apply_filters('aiflt_features', [ 'recovery_reminders' => 'free', 'recovery_coupons' => 'free', ]); } function aiflt_has_feature($feature) { $tier = aiflt_features()[$feature] ?? 'free'; return $tier === 'free' || aiflt_is_pro_active(); } function aiflt_ajax_test_ai_provider() { check_ajax_referer('aiflt-test-ai-provider-nonce', '_ajax_nonce'); if (!current_user_can('manage_options')) { wp_send_json_error(['message' => __('Permission denied.', 'ai-flash-tune')]); } if (!class_exists('AIFLT_AI_Service')) { wp_send_json_error(['message' => __('AI service is not loaded.', 'ai-flash-tune')]); } $result = AIFLT_AI_Service::test_provider(); if (in_array($result['status'], ['success', 'local'], true)) { wp_send_json_success($result); } wp_send_json_error($result); } // ---> MODIFIED: Removed the gate. The plugin will now always initialize. add_action('plugins_loaded', 'aiflt_initialize_plugin'); add_filter('cron_schedules', 'aiflt_add_weekly_cron_schedule'); /** * Detect AI Flash Tune admin screens for plugin-specific admin chrome. * * This is intentionally page-slug based so it also covers add-on screens * registered under the AI Flash Tune menu. * * @return bool */ function aiflt_is_plugin_admin_page() { if (!is_admin()) { return false; } $core_pages = [ 'ai_flash_tune', 'ai-flash-tune', 'aiflt_settings', ]; // Every other AI Flash Tune (and Pro) page slug starts with "aiflt-" or "aift". $page = isset($_GET['page']) ? sanitize_key(wp_unslash($_GET['page'])) : ''; if ($page !== '') { if (in_array($page, $core_pages, true) || strpos($page, 'aift') === 0) { return true; } } if (function_exists('get_current_screen')) { $screen = get_current_screen(); if ($screen && !empty($screen->id)) { $screen_id = (string) $screen->id; $screen_fragments = [ 'toplevel_page_ai_flash_tune', 'ai_flash_tune_page_', 'ai-flash-tune_page_', '_page_aiflt', '_page_aift', 'admin_page_aift', ]; foreach ($screen_fragments as $fragment) { if (strpos($screen_id, $fragment) !== false) { return true; } } } } return false; } /** * Replace the WordPress version footer on AI Flash Tune screens only. * * The standard admin footer shows the WordPress version. On branded AI Flash * Tune screens this looked like a plugin version mismatch, so we show the * current AI Flash Tune version instead. * * @param string $text Existing update footer text. * @return string */ function aiflt_admin_update_footer($text) { if (!aiflt_is_plugin_admin_page()) { return $text; } return sprintf( /* translators: %s: AI Flash Tune plugin version. */ esc_html__('AI Flash Tune %s', 'ai-flash-tune'), esc_html(AIFLT_VERSION) ); } add_filter('update_footer', 'aiflt_admin_update_footer', PHP_INT_MAX); /** * JavaScript fallback for admin footer text when WordPress/core/admin plugins * overwrite update_footer after our filter. * * @return void */ function aiflt_admin_footer_version_fallback() { if (!aiflt_is_plugin_admin_page()) { return; } $footer_text = sprintf( /* translators: %s: AI Flash Tune plugin version. */ __('AI Flash Tune %s', 'ai-flash-tune'), AIFLT_VERSION ); ?> WEEK_IN_SECONDS, 'display' => __('Once Weekly', 'ai-flash-tune'), ]; } return $schedules; } function aiflt_activate_plugin() { // Set a transient flag for the welcome redirect. set_transient('aiflt_welcome_redirect', true, 30); // Schedule the daily cleanup event if it's not already scheduled. if (!wp_next_scheduled('aiflt_daily_cleanup_event')) { wp_schedule_event(time(), 'daily', 'aiflt_daily_cleanup_event'); } // Store activation timestamp if it doesn't exist if (false === get_option('aiflt_activation_time')) { add_option('aiflt_activation_time', time()); } // One schema definition for fresh installs and upgrades. require_once AIFLT_PLUGIN_PATH . 'includes/AIFLT_AI_Usage_Log.php'; require_once AIFLT_PLUGIN_PATH . 'includes/AIFLT_AI_Report_Log.php'; require_once AIFLT_PLUGIN_PATH . 'includes/AIFLT_World_Class_Tools.php'; require_once AIFLT_PLUGIN_PATH . 'includes/AIFLT-Updates.php'; aiflt_run_database_updates(get_option('aiflt_db_version', '0')); update_option('aiflt_db_version', AIFLT_DB_VERSION); update_option('aiflt_db_health_version', AIFLT_DB_VERSION); AIFLT_World_Class_Tools::reschedule_weekly_email(); } function aiflt_deactivate_plugin() { wp_clear_scheduled_hook('aiflt_daily_cleanup_event'); wp_clear_scheduled_hook('aiflt_weekly_summary_email_event'); wp_clear_scheduled_hook('aiflt_recovery_tick'); wp_clear_scheduled_hook('aiflt_review_tick'); // Left by versions before 1.0.4, which ran the licence client in this plugin. wp_clear_scheduled_hook('aiflt_weekly_license_check_event'); wp_clear_scheduled_hook('aiflt_twicedaily_addon_update_check_event'); } function aiflt_welcome_redirect_handler() { // Check if our transient is set. if (get_transient('aiflt_welcome_redirect')) { // Delete the transient so this process only runs once. delete_transient('aiflt_welcome_redirect'); // Ensure the current user has permissions before redirecting. if (current_user_can('manage_options')) { // Perform a safe redirect to the main plugin dashboard. wp_safe_redirect(admin_url('admin.php?page=ai_flash_tune')); exit; } } } function aiflt_run_daily_cleanup_cron() { // --- REVISED: Read the correct individual database option --- $retention_days = get_option('aiflt_data_retention', 30); $retention_days = intval($retention_days); // A value of 0 means 'Forever', so we only run if it's a positive number. if ($retention_days > 0) { global $wpdb; $funnel_table = $wpdb->prefix . 'aiflt_funnel_data'; $behavior_table = $wpdb->prefix . 'aiflt_behavior_data'; // Calculate the cutoff date $cutoff_date = gmdate('Y-m-d H:i:s', strtotime("-$retention_days days")); // Delete old data from the funnel table $wpdb->query( $wpdb->prepare( "DELETE FROM {$funnel_table} WHERE timestamp < %s", $cutoff_date ) ); // Delete old data from the behavior table $wpdb->query( $wpdb->prepare( "DELETE FROM {$behavior_table} WHERE timestamp < %s", $cutoff_date ) ); } // Finished cart reminders (kept at least 90 days for the reports). if (class_exists('AIFLT_Cart_Recovery')) { AIFLT_Cart_Recovery::cleanup_old_rows(); } } /** * Register the core plugin settings and their sanitization callbacks. * Hooked to admin_init. */ function aiflt_register_core_settings() { // Register settings for the 'general' tab group // Each setting needs its own register_setting call. // The first argument is the 'option group' name used in settings_fields(). // The second argument is the actual 'option name' stored in wp_options. // The third argument is an array for arguments like sanitize_callback. register_setting('aiflt_settings_group_general', 'aiflt_ai_provider', [ 'type' => 'string', 'sanitize_callback' => 'sanitize_key', 'default' => 'local' ]); register_setting('aiflt_settings_group_general', 'aiflt_ai_external_consent', [ 'type' => 'integer', 'sanitize_callback' => 'absint', 'default' => 0 ]); register_setting('aiflt_settings_group_general', 'aiflt_ai_aggregate_only', [ 'type' => 'integer', 'sanitize_callback' => 'absint', 'default' => 1 ]); register_setting('aiflt_settings_group_general', 'aiflt_free_ai_monthly_limit', [ 'type' => 'integer', 'sanitize_callback' => 'absint', 'default' => 0 ]); register_setting('aiflt_settings_group_general', 'aiflt_ai_api_key', [ 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field', 'default' => '' ]); register_setting('aiflt_settings_group_general', 'aiflt_zywrap_api_key', [ 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field', 'default' => '' ]); // Zywrap proxy endpoint is fixed in code: https://api.zywrap.com/v1/proxy // Developers can override it with AIFLT_ZYWRAP_PROXY_ENDPOINT or the aiflt_zywrap_proxy_endpoint filter. register_setting('aiflt_settings_group_general', 'aiflt_ai_model', [ 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field', 'default' => 'gpt-4o-mini' ]); register_setting('aiflt_settings_group_general', 'aiflt_ai_response_language', [ 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field', 'default' => 'auto' ]); register_setting('aiflt_settings_group_general', 'aiflt_data_retention', [ 'type' => 'string', // Stored as string, but represents number or '0' 'sanitize_callback' => 'sanitize_text_field', 'default' => '30' ]); register_setting('aiflt_settings_group_general', 'aiflt_delete_data_on_uninstall', [ 'type' => 'integer', // Checkbox value is 1 or 0 'sanitize_callback' => 'absint', 'default' => 0 ]); register_setting('aiflt_settings_group_general', 'aiflt_anonymize_ip', [ 'type' => 'integer', 'sanitize_callback' => 'absint', 'default' => 1 ]); register_setting('aiflt_settings_group_general', 'aiflt_enable_tracking', [ 'type' => 'integer', 'sanitize_callback' => 'absint', 'default' => 1 ]); register_setting('aiflt_settings_group_general', 'aiflt_excluded_roles', [ 'type' => 'array', 'sanitize_callback' => 'aiflt_sanitize_roles_array', // Use your existing sanitize function 'default' => ['administrator', 'shop_manager'] ]); register_setting('aiflt_settings_group_general', 'aiflt_excluded_ips', [ 'type' => 'string', 'sanitize_callback' => 'aiflt_sanitize_ip_textarea', // Use your existing sanitize function 'default' => '' ]); // Hook for addons to register their settings (using their own option groups) do_action('aiflt_register_addon_settings'); } /** * Helper sanitize callback for roles array (already exists in ai-flash-tune.php) */ function aiflt_sanitize_roles_array($input) { $sanitized = []; if (is_array($input)) { foreach ($input as $role) { // Ensure only valid role keys are saved if (get_role($role)) { $sanitized[] = sanitize_key($role); } } } return $sanitized; } /** * Helper sanitize callback for IP textarea (already exists in ai-flash-tune.php) */ function aiflt_sanitize_ip_textarea($input) { $ips_array = explode("\n", trim($input)); $sanitized_ips = []; foreach ($ips_array as $ip) { $trimmed_ip = trim($ip); if (!empty($trimmed_ip)) { // Basic sanitization, could add IP validation if needed $sanitized_ips[] = sanitize_text_field($trimmed_ip); } } // Store as a single string separated by newlines return implode("\n", $sanitized_ips); } /** * Handles the manual triggering of cron jobs from the System Info page. */ function aiflt_handle_manual_cron_trigger() { if (isset($_GET['trigger_cron']) && isset($_GET['_wpnonce'])) { if (!current_user_can('manage_options')) { return; } if (!wp_verify_nonce(sanitize_text_field(wp_unslash($_GET['_wpnonce'])), 'aiflt_trigger_cron')) { return; } $cron_type = sanitize_key(wp_unslash($_GET['trigger_cron'])); if ($cron_type === 'cleanup') { // Run the cleanup function manually aiflt_run_daily_cleanup_cron(); // Add a success notice and redirect add_action('admin_notices', function() { echo '

' . esc_html__('The daily data cleanup job has been run successfully.', 'ai-flash-tune') . '

'; }); } // We can add more cron triggers here in the future } } // Enqueue scripts and styles for the admin side function aiflt_enqueue_admin_scripts($hook) { if (!aiflt_is_plugin_admin_page()) { return; } // Every screen uses aiflt-admin.css and inline SVG icons (AIFLT_UI::icon()). wp_enqueue_style('aiflt-admin', AIFLT_PLUGIN_URL . 'includes/css/aiflt-admin.css', [], AIFLT_VERSION); if (!aiflt_is_woocommerce_active()) { return; } // Enqueue the main jQuery script wp_enqueue_script('ai-flash-tune-main-js', AIFLT_PLUGIN_URL . 'includes/js/ai-flash-tune-main.js', ['jquery'], AIFLT_VERSION, true); // Prepare data to pass to JavaScript (wp_localize_script remains the same as previous step) $aiflt_start_date = isset($_GET['start_date']) ? sanitize_text_field(wp_unslash($_GET['start_date'])) : gmdate('Y-m-d', strtotime('-29 days')); $aiflt_end_date = isset($_GET['end_date']) ? sanitize_text_field(wp_unslash($_GET['end_date'])) : gmdate('Y-m-d'); $aiflt_current_device = isset($_GET['device']) ? sanitize_key(wp_unslash($_GET['device'])) : 'desktop'; $aiflt_current_device = in_array($aiflt_current_device, ['all', 'desktop', 'mobile'], true) ? $aiflt_current_device : 'desktop'; $activation_time = get_option('aiflt_activation_time', time()); $min_date = gmdate('Y-m-d', $activation_time); // Pass PHP data to the JavaScript file (using aiflt_ajax_object and corrected nonce actions) wp_localize_script('ai-flash-tune-main-js', 'aiflt_ajax_object', [ // Use the corrected object name here 'ajax_url' => admin_url('admin-ajax.php'), // Ensure ALL these nonce actions match the check_ajax_referer() calls 'tracking_nonce' => wp_create_nonce('aiflt-tracking-nonce'), // For frontend 'ai_analysis_nonce' => wp_create_nonce('aiflt-ai-analysis-nonce'), // Core AI Ask 'settings_nonce' => wp_create_nonce('aiflt-save-settings-nonce'), // Core Settings Save 'get_funnel_nonce' => wp_create_nonce('aiflt-get-funnel-nonce'), // Core Get Funnel Data // Keep addon nonces specific for clarity, assuming checks use these specific actions 'aiftaa_nonce' => wp_create_nonce('aiftaa-generate-report-nonce'), // AI Analysis Addon 'smart_suggestions_nonce' => wp_create_nonce('aiftss-get-suggestion-nonce'), // Smart Suggestions Addon 'aiftco_nonce' => wp_create_nonce('aiftco-get-analysis-nonce'), // Checkout Optimizer Addon 'aiftap_nonce' => wp_create_nonce('aiftap-get-prediction-nonce'), // Abandonment Predictor Addon 'aiftpd_nonce' => wp_create_nonce('aiftpd-get-diagnosis-nonce'), // Product Doctor Addon 'aiftce_nonce' => wp_create_nonce('aiftce-get-copy-suggestion-nonce'), // Copy Enhancer Addon 'aiftfs_nonce' => wp_create_nonce('aiftfs-get-segmented-nonce'), // Funnel Segmentation Addon 'aiftcr_test_email_nonce' => wp_create_nonce('aiftcr-test-email-nonce'), // Cart Recovery Test Email 'aiftac_nonce' => wp_create_nonce('aiftac-action-center-nonce'), 'aiftpo_nonce' => wp_create_nonce('aiftpo-product-optimizer-nonce'), 'aiftcr_nonce' => wp_create_nonce('aiftcr-recovery-center-nonce'), 'aiftas_nonce' => wp_create_nonce('aiftas-segmentation-nonce'), 'aiftal_nonce' => wp_create_nonce('aiftal-alert-center-nonce'), 'aiftrp_nonce' => wp_create_nonce('aiftrp-reports-nonce'), 'aiflt_test_ai_provider_nonce' => wp_create_nonce('aiflt-test-ai-provider-nonce'), 'privacy_nonce' => wp_create_nonce('aiflt_privacy_actions'), // <-- NEW NONCE // KEEP other localized variables 'current_device_type' => $aiflt_current_device, 'start_date' => $aiflt_start_date, 'end_date' => $aiflt_end_date, 'min_date_limit' => $min_date, // Pass the formatted date 'is_admin' => true, 'admin_base_url' => admin_url('admin.php'), // Section list shared by the PHP and JavaScript answer renderers. 'answerSections' => class_exists('AIFLT_UI') ? AIFLT_UI::answer_sections() : [], 'i18n' => [ 'saving' => __('Saving...', 'ai-flash-tune'), 'saveSettings' => __('Save Settings', 'ai-flash-tune'), 'saveError' => __('Error: Could not save settings.', 'ai-flash-tune'), 'unknownError' => __('An unexpected error occurred. Please try again.', 'ai-flash-tune'), 'sending' => __('Sending...', 'ai-flash-tune'), // For test email 'installing' => __('Installing', 'ai-flash-tune'), 'activating' => __('Activating', 'ai-flash-tune'), 'deactivating' => __('Deactivating', 'ai-flash-tune'), // Diagnosis & Suggestions (AIFT, AIFTSS, AIFTPD) 'diagnosis' => __('Diagnosis', 'ai-flash-tune'), 'confidence' => __('Confidence Score', 'ai-flash-tune'), 'whySuggestion' => __('Why this suggestion?', 'ai-flash-tune'), 'recommendations' => __('Recommendations', 'ai-flash-tune'), 'aiAnalyzingSuggestions' => __('Our AI is analyzing your data to generate suggestions...', 'ai-flash-tune'), 'aiDiagnosingProduct' => __('AI is diagnosing the product...', 'ai-flash-tune'), 'aiGeneratingCopy' => __('Generating copy...', 'ai-flash-tune'), // AI Analysis & Checkout (AIFTAA, AIFTCO) 'generating' => __('Generating...', 'ai-flash-tune'), 'analyzing' => __('Analyzing...', 'ai-flash-tune'), 'aiAnalyzingData' => __('Our AI is analyzing your data...', 'ai-flash-tune'), 'aiAnalyzingCheckout' => __('Our AI is analyzing your checkout process...', 'ai-flash-tune'), // Abandonment Predictor (AIFTAP) 'predicting' => __('Predicting...', 'ai-flash-tune'), 'aiAnalyzingPrediction' => __('AI is analyzing your data...', 'ai-flash-tune'), // Funnel Messages 'loadingFunnel' => __('Loading Funnel Data...', 'ai-flash-tune'), 'noFunnelData' => __('Funnel tracking is ready, but this range needs activity', 'ai-flash-tune'), 'noFunnelTraffic' => __('Run one guest test: visit a product page, add it to cart, open checkout, then refresh this report. Real shopper activity will appear here after it is recorded.', 'ai-flash-tune'), 'noFunnelRange' => __('No funnel events were recorded in this date range. Expand the date range or run a guest product → cart → checkout test to confirm tracking.', 'ai-flash-tune'), 'funnelError' => __('Error loading funnel data.', 'ai-flash-tune'), 'funnelNetworkError' => __('Error loading funnel data. Please check your network connection.', 'ai-flash-tune'), // Ask AI 'aiPromptEmpty' => __('Please enter a question for the AI.', 'ai-flash-tune'), 'details' => __('Details', 'ai-flash-tune'), 'close' => __('Close', 'ai-flash-tune'), 'copied' => __('Copied', 'ai-flash-tune'), 'aiWorking' => __('Working on the answer…', 'ai-flash-tune'), 'aiNoAnswer' => __('No answer came back. Try another question.', 'ai-flash-tune'), 'aiError' => __('The answer could not be created:', 'ai-flash-tune'), 'ansSummary' => __('Summary', 'ai-flash-tune'), 'ansDetails' => __('Details', 'ai-flash-tune'), 'ansEvidence' => __('What the numbers show', 'ai-flash-tune'), 'ansCauses' => __('Likely causes to check', 'ai-flash-tune'), 'ansFixes' => __('Fixes, in order', 'ai-flash-tune'), 'ansChecks' => __('Next checks', 'ai-flash-tune'), 'ansNextSteps' => __('Next steps', 'ai-flash-tune'), 'ansNotYet' => __('Do not change yet', 'ai-flash-tune'), 'ansMore' => __('More details', 'ai-flash-tune'), 'ansConfidence' => __('Confidence:', 'ai-flash-tune'), 'ansReadiness' => __('Data:', 'ai-flash-tune'), 'ansImpact' => __('Impact:', 'ai-flash-tune'), 'ansEffort' => __('Effort:', 'ai-flash-tune'), 'ansRisk' => __('Risk:', 'ai-flash-tune'), 'aiThinking' => __('Thinking...', 'ai-flash-tune'), 'aiNetworkError' => __('Error: Could not retrieve AI response. Please check your network connection.', 'ai-flash-tune'), 'noSegmentData' => __('No data available for this segment in the selected date range.', 'ai-flash-tune'), 'segmentA' => __('Segment A', 'ai-flash-tune'), 'segmentB' => __('Segment B', 'ai-flash-tune'), 'getAiDiagnosis' => __('Get AI Diagnosis', 'ai-flash-tune'), 'landingPage' => __('Landing Page', 'ai-flash-tune'), 'productPage' => __('Product Page', 'ai-flash-tune'), 'addedToCart' => __('Added to Cart', 'ai-flash-tune'), 'checkoutPage' => __('Checkout Page', 'ai-flash-tune'), 'unknownError' => __('An unknown error occurred.', 'ai-flash-tune'), 'users' => __('Users', 'ai-flash-tune'), 'loadingSegmentedData...' => __('Loading segmented data...', 'ai-flash-tune'), 'dropOff' => __('Drop-Off', 'ai-flash-tune'), 'visitors' => __('Visitors', 'ai-flash-tune'), 'start' => __('Start', 'ai-flash-tune'), 'conversion' => __('Conversion', 'ai-flash-tune'), 'dropOffCartTooltip' => __('Percentage of users who left after adding to the Cart.', 'ai-flash-tune'), 'dropOffProductTooltip' => __('Percentage of users who left after showing Product Interest.', 'ai-flash-tune'), 'dropOffLandingTooltip' => __('Percentage of users who left after the Landing Page.', 'ai-flash-tune'), 'sales' => __('Sales', 'ai-flash-tune'), 'checkouts' => __('Checkouts', 'ai-flash-tune'), 'carts' => __('Carts', 'ai-flash-tune'), 'guestUsers' => __('Guest Users', 'ai-flash-tune'), 'registeredUsers' => __('Registered Users', 'ai-flash-tune'), 'desktop' => __('Desktop', 'ai-flash-tune'), 'mobile' => __('Mobile', 'ai-flash-tune'), 'purchaseComplete' => __('Purchase Complete', 'ai-flash-tune'), 'productInterest' => __('Product Interest', 'ai-flash-tune'), 'views' => __('Views', 'ai-flash-tune'), 'entries' => __('Entries', 'ai-flash-tune'), ], ]); } // Enqueue the storefront tracking script. // The hook is registered only while WooCommerce is active in aiflt_initialize_plugin(). function aiflt_enqueue_frontend_scripts() { if (!class_exists('AIFLT_Funnel_Analyzer_Logic') || !AIFLT_Funnel_Analyzer_Logic::is_tracking_enabled()) { return; } // Excluded roles and IPs never load the script. (Consent is checked in the // browser, and again on the server for every request.) if (is_user_logged_in()) { $excluded_roles = (array) get_option('aiflt_excluded_roles', ['administrator', 'shop_manager']); if (array_intersect((array) wp_get_current_user()->roles, $excluded_roles)) { return; } } $user_ip = AIFLT_Funnel_Analyzer_Logic::client_ip(); $excluded_ips_raw = (string) get_option('aiflt_excluded_ips', ''); if ($user_ip !== '' && $excluded_ips_raw !== '') { $excluded_ips = array_map('trim', explode("\n", str_replace("\r", '', $excluded_ips_raw))); if (in_array($user_ip, $excluded_ips, true)) { return; } } wp_enqueue_script('ai-flash-tune-tracking', AIFLT_PLUGIN_URL . 'includes/js/ai-flash-tune-tracking.js', ['jquery'], AIFLT_VERSION, true); // Nothing visitor-specific is printed into the page, so full-page caches // can serve it to everyone. The session lives in a first-party cookie. wp_localize_script('ai-flash-tune-tracking', 'aiflt_tracking', [ 'ajax_url' => admin_url('admin-ajax.php'), 'tracking_nonce' => wp_create_nonce('aiflt-tracking-nonce'), 'require_consent' => (int) get_option('aiflt_require_consent', 0) === 1, 'capture_guest_email' => (bool) apply_filters('aiflt_capture_guest_email', true), // Cart reminders: the short note under the checkout email field, with a "No thanks" link. 'reminder_notice' => class_exists('AIFLT_Cart_Recovery') && AIFLT_Cart_Recovery::is_enabled() && !empty(AIFLT_Cart_Recovery::settings()['notice']) ? AIFLT_Cart_Recovery::settings()['notice_text'] : '', 'reminder_decline' => __('No thanks', 'ai-flash-tune'), 'reminder_declined' => __('OK, we won\'t send reminders.', 'ai-flash-tune'), 'save_cart' => aiflt_save_cart_config(), 'cookie_path' => defined('COOKIEPATH') && COOKIEPATH ? COOKIEPATH : '/', 'cookie_lifetime' => (int) apply_filters('aiflt_session_cookie_lifetime', 30 * DAY_IN_SECONDS), ]); } /** * Texts and switches for the "Save my cart" box and the exit popup, or false * when neither is on. The same for every visitor, so pages stay cacheable. * * @return array|false */ function aiflt_save_cart_config() { if (!class_exists('AIFLT_Cart_Recovery') || !AIFLT_Cart_Recovery::save_cart_enabled()) { return false; } return [ 'box' => AIFLT_Cart_Recovery::save_cart_enabled('box'), 'exit' => AIFLT_Cart_Recovery::save_cart_enabled('exit'), 'title' => __('Not ready to buy yet?', 'ai-flash-tune'), 'exit_title' => __('Before you go, save your cart?', 'ai-flash-tune'), 'text' => __('Get a link to this cart by email and pick it up later, on any device.', 'ai-flash-tune'), 'label' => __('Your email', 'ai-flash-tune'), 'button' => __('Email me my cart', 'ai-flash-tune'), 'note' => __('You may get a couple of reminders about this cart. Every email has an unsubscribe link.', 'ai-flash-tune'), 'done' => __('Sent. Check your inbox for the link to your cart.', 'ai-flash-tune'), 'error' => __('That didn\'t work. Please check the email address and try again.', 'ai-flash-tune'), 'close' => __('Close', 'ai-flash-tune'), 'no_thanks' => __('No thanks', 'ai-flash-tune'), // Asked only when the popup is about to open: is there anything in the cart? 'cart_api' => esc_url_raw(rest_url('wc/store/v1/cart')), ]; } /** * Tell the WP Consent API that this plugin checks consent itself. */ add_filter('wp_consent_api_registered_' . plugin_basename(__FILE__), '__return_true'); /** * Describe the tracking cookie to consent plugins that list cookies. */ function aiflt_register_consent_cookie_info() { if (function_exists('wp_add_cookie_info')) { wp_add_cookie_info( 'aiflt_session_id', 'AI Flash Tune', 'statistics', __('30 days', 'ai-flash-tune'), __('Groups page views, cart and checkout steps of one visit so the store owner can see where shoppers drop off.', 'ai-flash-tune'), false, false, false ); } } add_action('plugins_loaded', 'aiflt_register_consent_cookie_info', 20);