WooCommerce' ); ?>

'string', 'sanitize_callback' => 'sanitize_text_field', 'default' => '', ) ); register_setting( 'magicgeo_settings', 'magicgeo_auto_schema', array( 'type' => 'boolean', 'sanitize_callback' => 'rest_sanitize_boolean', 'default' => true, ) ); } /** * Enqueue admin scripts and styles. * * @param string $hook Current admin page hook. */ function magicgeo_admin_scripts( $hook ) { if ( strpos( $hook, 'magicgeo' ) === false ) { return; } wp_enqueue_style( 'magicgeo-admin', MAGICGEO_PLUGIN_URL . 'assets/css/admin.css', array(), MAGICGEO_VERSION ); wp_enqueue_script( 'magicgeo-admin', MAGICGEO_PLUGIN_URL . 'assets/js/admin.js', array( 'jquery' ), MAGICGEO_VERSION, true ); wp_localize_script( 'magicgeo-admin', 'magicgeoAdmin', array( 'ajaxUrl' => admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce( 'magicgeo_nonce' ), 'apiUrl' => MAGICGEO_API_URL, 'strings' => array( 'optimizing' => esc_html__( 'Optimizing...', 'magicgeo' ), 'success' => esc_html__( 'Product optimized successfully!', 'magicgeo' ), 'error' => esc_html__( 'Optimization failed. Please try again.', 'magicgeo' ), ), ) ); } /** * Main admin page. */ function magicgeo_admin_page() { $api_key = get_option( 'magicgeo_api_key', '' ); if ( empty( $api_key ) ) { magicgeo_settings_page(); return; } // Get products. $products = wc_get_products( array( 'status' => 'publish', 'limit' => 50, ) ); ?>

0

get_id(), '_magicgeo_score', true ); $geo_status = get_post_meta( $product_item->get_id(), '_magicgeo_status', true ); $score_class = ''; if ( $geo_score ) { $geo_score_int = absint( $geo_score ); if ( $geo_score_int >= 70 ) { $score_class = 'good'; } elseif ( $geo_score_int >= 40 ) { $score_class = 'medium'; } else { $score_class = 'low'; } } $status_class = $geo_status ? sanitize_html_class( $geo_status ) : 'pending'; $status_label = $geo_status ? ucfirst( sanitize_text_field( $geo_status ) ) : esc_html__( 'Not analyzed', 'magicgeo' ); ?>
get_name() ); ?>
get_sku() ); ?>

' . esc_html__( 'Settings saved successfully.', 'magicgeo' ) . '

'; } $api_key = get_option( 'magicgeo_api_key', '' ); $auto_schema = get_option( 'magicgeo_auto_schema', true ); ?>

' . esc_html__( 'MagicGEO Dashboard', 'magicgeo' ) . '' ); ?>


get_id(), '_magicgeo_schema', true ); if ( ! empty( $stored_schema ) ) { echo wp_kses( $stored_schema, array( 'script' => array( 'type' => array(), ), ) ); return; } // Generate default schema if none stored. $schema = magicgeo_generate_default_schema( $product ); ?> 'https://schema.org', '@type' => 'Product', 'name' => $wc_product->get_name(), 'description' => wp_strip_all_tags( $wc_product->get_short_description() ? $wc_product->get_short_description() : $wc_product->get_description() ), 'sku' => $wc_product->get_sku(), 'url' => get_permalink( $wc_product->get_id() ), ); // Add image. $image_id = $wc_product->get_image_id(); if ( $image_id ) { $image_url = wp_get_attachment_url( $image_id ); $schema['image'] = $image_url; } // Add brand if available. $brand = $wc_product->get_attribute( 'brand' ); if ( ! empty( $brand ) ) { $schema['brand'] = array( '@type' => 'Brand', 'name' => $brand, ); } // Add offers. $schema['offers'] = array( '@type' => 'Offer', 'url' => get_permalink( $wc_product->get_id() ), 'priceCurrency' => get_woocommerce_currency(), 'price' => $wc_product->get_price(), 'availability' => $wc_product->is_in_stock() ? 'https://schema.org/InStock' : 'https://schema.org/OutOfStock', 'itemCondition' => 'https://schema.org/NewCondition', ); // Add seller. $schema['offers']['seller'] = array( '@type' => 'Organization', 'name' => get_bloginfo( 'name' ), ); return $schema; } /** * AJAX handler for product optimization. */ function magicgeo_ajax_optimize_product() { // Verify nonce. check_ajax_referer( 'magicgeo_nonce', 'nonce' ); // Check capabilities. if ( ! current_user_can( 'manage_woocommerce' ) ) { wp_send_json_error( array( 'message' => esc_html__( 'Permission denied.', 'magicgeo' ) ) ); } // Validate and sanitize product ID. if ( ! isset( $_POST['product_id'] ) ) { wp_send_json_error( array( 'message' => esc_html__( 'Invalid product ID.', 'magicgeo' ) ) ); } $product_id = absint( wp_unslash( $_POST['product_id'] ) ); if ( ! $product_id ) { wp_send_json_error( array( 'message' => esc_html__( 'Invalid product ID.', 'magicgeo' ) ) ); } $product_obj = wc_get_product( $product_id ); if ( ! $product_obj ) { wp_send_json_error( array( 'message' => esc_html__( 'Product not found.', 'magicgeo' ) ) ); } $api_key = get_option( 'magicgeo_api_key', '' ); if ( empty( $api_key ) ) { wp_send_json_error( array( 'message' => esc_html__( 'API key not configured.', 'magicgeo' ) ) ); } // Prepare product data. $product_data = array( 'id' => $product_obj->get_id(), 'title' => $product_obj->get_name(), 'description' => $product_obj->get_description(), 'sku' => $product_obj->get_sku(), 'price' => $product_obj->get_price(), 'categories' => wp_get_post_terms( $product_obj->get_id(), 'product_cat', array( 'fields' => 'names' ) ), ); // Call MagicGEO API. $response = wp_remote_post( MAGICGEO_API_URL . '/woocommerce-optimize', array( 'timeout' => 60, 'headers' => array( 'Content-Type' => 'application/json', 'Authorization' => 'Bearer ' . $api_key, ), 'body' => wp_json_encode( $product_data ), ) ); if ( is_wp_error( $response ) ) { wp_send_json_error( array( 'message' => esc_html( $response->get_error_message() ) ) ); } $body = json_decode( wp_remote_retrieve_body( $response ), true ); if ( isset( $body['error'] ) ) { wp_send_json_error( array( 'message' => esc_html( $body['error'] ) ) ); } // Save optimization results. if ( isset( $body['geo_score'] ) ) { update_post_meta( $product_id, '_magicgeo_score', absint( $body['geo_score'] ) ); } if ( isset( $body['status'] ) ) { update_post_meta( $product_id, '_magicgeo_status', sanitize_text_field( $body['status'] ) ); } if ( isset( $body['schema_markup'] ) ) { update_post_meta( $product_id, '_magicgeo_schema', wp_kses_post( $body['schema_markup'] ) ); } if ( isset( $body['seo_description'] ) ) { update_post_meta( $product_id, '_magicgeo_seo_description', sanitize_textarea_field( $body['seo_description'] ) ); } wp_send_json_success( array( 'message' => esc_html__( 'Product optimized successfully!', 'magicgeo' ), 'geo_score' => isset( $body['geo_score'] ) ? absint( $body['geo_score'] ) : 0, 'status' => isset( $body['status'] ) ? sanitize_text_field( $body['status'] ) : 'optimized', ) ); } add_action( 'wp_ajax_magicgeo_optimize_product', 'magicgeo_ajax_optimize_product' ); /** * AJAX handler for product analysis. */ function magicgeo_ajax_analyze_product() { // Verify nonce. check_ajax_referer( 'magicgeo_nonce', 'nonce' ); // Check capabilities. if ( ! current_user_can( 'manage_woocommerce' ) ) { wp_send_json_error( array( 'message' => esc_html__( 'Permission denied.', 'magicgeo' ) ) ); } // Validate and sanitize product ID. if ( ! isset( $_POST['product_id'] ) ) { wp_send_json_error( array( 'message' => esc_html__( 'Invalid product ID.', 'magicgeo' ) ) ); } $product_id = absint( wp_unslash( $_POST['product_id'] ) ); if ( ! $product_id ) { wp_send_json_error( array( 'message' => esc_html__( 'Invalid product ID.', 'magicgeo' ) ) ); } $product_obj = wc_get_product( $product_id ); if ( ! $product_obj ) { wp_send_json_error( array( 'message' => esc_html__( 'Product not found.', 'magicgeo' ) ) ); } // Calculate local GEO score. $score = 0; $issues = array(); // Check title length (10 points). $title_length = strlen( $product_obj->get_name() ); if ( $title_length >= 30 && $title_length <= 60 ) { $score += 10; } else { $issues[] = esc_html__( 'Title should be between 30-60 characters', 'magicgeo' ); } // Check description (20 points). $description = $product_obj->get_description(); if ( strlen( $description ) >= 150 ) { $score += 20; } else { $issues[] = esc_html__( 'Description should be at least 150 characters', 'magicgeo' ); } // Check short description (15 points). $short_desc = $product_obj->get_short_description(); if ( strlen( $short_desc ) >= 50 ) { $score += 15; } else { $issues[] = esc_html__( 'Short description should be at least 50 characters', 'magicgeo' ); } // Check images (15 points). $gallery_ids = $product_obj->get_gallery_image_ids(); $image_count = $product_obj->get_image_id() ? count( $gallery_ids ) + 1 : count( $gallery_ids ); if ( $image_count >= 3 ) { $score += 15; } elseif ( $image_count >= 1 ) { $score += 7; $issues[] = esc_html__( 'Add more product images (3+ recommended)', 'magicgeo' ); } else { $issues[] = esc_html__( 'Add product images', 'magicgeo' ); } // Check SKU (10 points). if ( ! empty( $product_obj->get_sku() ) ) { $score += 10; } else { $issues[] = esc_html__( 'Add a SKU for better indexing', 'magicgeo' ); } // Check categories (15 points). $categories = wp_get_post_terms( $product_obj->get_id(), 'product_cat' ); if ( ! is_wp_error( $categories ) && count( $categories ) >= 1 ) { $score += 15; } else { $issues[] = esc_html__( 'Assign product to at least one category', 'magicgeo' ); } // Check price (15 points). if ( $product_obj->get_price() > 0 ) { $score += 15; } else { $issues[] = esc_html__( 'Set a product price', 'magicgeo' ); } // Save analysis results. update_post_meta( $product_id, '_magicgeo_score', $score ); if ( $score >= 70 ) { $status = 'optimized'; } elseif ( $score >= 40 ) { $status = 'needs_work'; } else { $status = 'critical'; } update_post_meta( $product_id, '_magicgeo_status', $status ); wp_send_json_success( array( 'message' => esc_html__( 'Analysis complete!', 'magicgeo' ), 'geo_score' => $score, 'issues' => $issues, 'status' => $status, ) ); } add_action( 'wp_ajax_magicgeo_analyze_product', 'magicgeo_ajax_analyze_product' ); /** * Add settings link on plugins page. * * @param array $links Existing plugin action links. * @return array Modified links. */ function magicgeo_plugin_action_links( $links ) { $settings_link = '' . esc_html__( 'Settings', 'magicgeo' ) . ''; array_unshift( $links, $settings_link ); return $links; } add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), 'magicgeo_plugin_action_links' ); /** * Plugin activation hook. */ function magicgeo_activate() { // Create necessary options. add_option( 'magicgeo_api_key', '' ); add_option( 'magicgeo_auto_schema', true ); add_option( 'magicgeo_version', MAGICGEO_VERSION ); } register_activation_hook( __FILE__, 'magicgeo_activate' ); /** * Plugin deactivation hook. */ function magicgeo_deactivate() { // Cleanup if needed. } register_deactivation_hook( __FILE__, 'magicgeo_deactivate' );