human label. */ private const SOURCES = [ 'ai2web' => 'Agent checkout', 'ai2web-acp' => 'ACP (ChatGPT)', 'ai2web-ap2' => 'AP2 (Google)', ]; public static function boot(): void { add_action('admin_menu', [self::class, 'menu']); } public static function menu(): void { add_submenu_page( 'options-general.php', __('AI2Web Agent Sales', 'ai2web'), __('AI2Web Agent Sales', 'ai2web'), 'manage_woocommerce', 'ai2web-sales', [self::class, 'render'] ); } public static function render(): void { if (!current_user_can('manage_woocommerce')) { return; } // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only range selector. $range = isset($_GET['range']) ? absint($_GET['range']) : 30; $days = in_array($range, [7, 30, 90, 365], true) ? $range : 30; echo '
' . esc_html__('WooCommerce is not active, so there are no agent orders to show.', 'ai2web') . '
'; foreach ([7 => __('7 days', 'ai2web'), 30 => __('30 days', 'ai2web'), 90 => __('90 days', 'ai2web'), 365 => __('12 months', 'ai2web')] as $d => $label) { $url = admin_url('options-general.php?page=ai2web-sales&range=' . $d); $cur = $d === $days; echo '' . esc_html($label) . ''; if ($d !== 365) { echo ' | '; } } echo '
'; $orders = self::agent_orders($days); $stats = self::summarise($orders); // KPI cards. echo '| ' . esc_html__('Source', 'ai2web') . ' | ' . esc_html__('Orders', 'ai2web') . ' | ' . esc_html__('Paid', 'ai2web') . ' | ' . esc_html__('Revenue (paid)', 'ai2web') . ' |
|---|---|---|---|
| ' . esc_html__('No agent orders in this period yet.', 'ai2web') . ' | |||
| ' . esc_html(self::SOURCES[$via] ?? $via) . ' | ' . esc_html((string) $row['count']) . ' | ' . esc_html((string) $row['paid_count']) . ' | ' . wp_kses_post(wc_price($row['paid_revenue'])) . ' |
| ' . esc_html__('Order', 'ai2web') . ' | ' . esc_html__('Date', 'ai2web') . ' | ' . esc_html__('Source', 'ai2web') . ' | ' . esc_html__('Status', 'ai2web') . ' | ' . esc_html__('Total', 'ai2web') . ' |
|---|---|---|---|---|
| ' . esc_html__('No agent orders yet. When an AI agent buys through ACP, AP2 or agent checkout, it appears here.', 'ai2web') . ' | ||||
| #' . esc_html($o->get_order_number()) . ' | '; echo '' . esc_html($o->get_date_created() ? $o->get_date_created()->date_i18n(get_option('date_format') . ' H:i') : '-') . ' | '; echo '' . esc_html(self::SOURCES[$o->get_created_via()] ?? $o->get_created_via()) . ' | '; echo '' . esc_html(wc_get_order_status_name($o->get_status())) . ' | '; echo '' . wp_kses_post(wc_price($o->get_total(), ['currency' => $o->get_currency()])) . ' | '; echo '
' . esc_html__('All figures are computed locally from your WooCommerce orders and the AI2Web events table. Nothing is sent to any external service.', 'ai2web') . '
'; echo ''; } /** * Agent-attributed orders in the window, newest first (drafts excluded). * @return WC_Order[] */ private static function agent_orders(int $days): array { if (!function_exists('wc_get_orders')) { return []; } $orders = wc_get_orders([ 'limit' => -1, 'type' => 'shop_order', 'date_created' => '>=' . gmdate('Y-m-d', time() - $days * DAY_IN_SECONDS), 'orderby' => 'date', 'order' => 'DESC', ]); $out = []; foreach ($orders as $o) { // Filter by created_via in PHP so this is correct whether or not the query backend // supports created_via as a filter, and across HPOS / legacy storage. if ($o instanceof WC_Order && isset(self::SOURCES[$o->get_created_via()]) && $o->get_status() !== 'checkout-draft') { $out[] = $o; } } return $out; } /** * @param WC_Order[] $orders * @return array{count:int,paid_count:int,paid_revenue:float,pending_revenue:float,by_source:array' . esc_html__('Query misses are searches an agent ran that returned nothing - demand you are not yet meeting. A read-only crawl of your site cannot surface this.', 'ai2web') . '
'; } } private static function kpi(string $label, string $value, string $sub): void { echo '