__( 'Archive conversion rates', 'ai-eshop-optimizer' ), 'description' => __( 'For `source=archive` cart-adds, break down by archive term (pa_need / product_brand / product_cat) so the merchant can see which archives drive the most cart-adds. Parses `source_meta` JSON.', 'ai-eshop-optimizer' ), 'category' => \AIEO\Claude\Bootstrap::CATEGORY, 'input_schema' => self::input_schema(), 'output_schema' => array( 'type' => 'object' ), 'execute_callback' => array( __CLASS__, 'execute' ), 'permission_callback' => array( __CLASS__, 'permission_check' ), 'meta' => array( 'annotations' => array( 'readonly' => true, 'idempotent' => true, ), 'show_in_rest' => true, ), ) ); } public static function permission_check( $input = null ) { unset( $input ); return current_user_can( 'manage_woocommerce' ); } private static function input_schema() { return array( 'default' => array(), 'type' => 'object', 'properties' => array( 'period' => array( 'type' => 'string', 'default' => 'last_30_days', 'enum' => PeriodHelper::ALLOWED, ), 'taxonomy' => array( 'type' => 'string', 'enum' => array( 'all', 'pa_need', 'product_brand', 'product_cat', 'product_tag' ), 'default' => 'all', 'description' => 'Limit to one archive taxonomy, or `all`.', ), 'limit' => array( 'type' => 'integer', 'minimum' => 1, 'maximum' => 100, 'default' => 25, ), ), ); } public static function execute( $input ) { global $wpdb; $input = is_array( $input ) ? $input : array(); $period = PeriodHelper::resolve( $input['period'] ?? 'last_30_days' ); $tax = isset( $input['taxonomy'] ) ? sanitize_key( (string) $input['taxonomy'] ) : 'all'; $limit = isset( $input['limit'] ) ? max( 1, min( 100, (int) $input['limit'] ) ) : 25; $table = $wpdb->prefix . 'aieo_attribution_daily'; $exists = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = %s", $table ) ); if ( ! $exists ) { return array( 'period' => $period, 'rows' => array(), 'note' => __( 'wp_aieo_attribution_daily not installed.', 'ai-eshop-optimizer' ) ); } $rows = $wpdb->get_results( $wpdb->prepare( "SELECT archive_term_id, archive_term_tax, SUM(cart_adds) AS cart_adds, SUM(units) AS units, SUM(revenue) AS revenue FROM {$table} WHERE date BETWEEN DATE(%s) AND DATE(%s) AND source = 'archive' AND archive_term_id > 0 AND ( %s = 'all' OR archive_term_tax = %s ) GROUP BY archive_term_id, archive_term_tax", $period['since'], $period['until'], $tax, $tax ), ARRAY_A ); $buckets = array(); foreach ( (array) $rows as $r ) { $tid = (int) $r['archive_term_id']; $tx = (string) $r['archive_term_tax']; if ( $tid <= 0 || $tx === '' ) { continue; } $term = get_term( $tid, $tx ); $is_term = $term instanceof \WP_Term; $buckets[] = array( 'taxonomy' => $tx, 'term_id' => $tid, 'name' => $is_term ? (string) $term->name : '', 'archive_url' => $is_term ? get_term_link( $term ) : '', 'cart_adds' => (int) $r['cart_adds'], 'units' => (int) $r['units'], 'revenue' => (float) $r['revenue'], ); } usort( $buckets, static function ( $a, $b ) { return $b['cart_adds'] <=> $a['cart_adds']; } ); return array( 'period' => $period, 'taxonomy' => $tax, 'rows' => array_slice( array_values( $buckets ), 0, $limit ), ); } }