__( 'LAST 30 DAYS', 'agentic-commerce-for-woocommerce' ),
'title' => __( 'What the AI channel actually earned', 'agentic-commerce-for-woocommerce' ),
'sub' => __( 'Measured against your real WooCommerce orders — not a projection, and not the ad platform\'s own scorecard. Where we cannot explain an order, we say so.', 'agentic-commerce-for-woocommerce' ),
'figure' => $d['attributed'] ? Xpay_UI::money( $d['revenue'] ) : '',
'figure_label' => $d['attributed'] ? __( 'AI-attributed revenue', 'agentic-commerce-for-woocommerce' ) : '',
)
);
if ( 0 === $d['orders'] ) {
echo '
';
Xpay_UI::empty_state(
__( 'No orders in the last 30 days', 'agentic-commerce-for-woocommerce' ),
__( 'There is nothing to attribute yet. This screen fills in as orders arrive — no setup needed.', 'agentic-commerce-for-woocommerce' )
);
echo '
';
Xpay_UI::close();
return;
}
self::summary( $d );
self::by_source( $d );
self::unattributed( $d );
Xpay_UI::close();
}
/**
* Headline tiles.
*
* @param array $d Rollup.
* @return void
*/
private static function summary( $d ) {
$unmatched = max( 0, $d['orders'] - $d['attributed'] );
echo '';
Xpay_UI::stat(
__( 'Orders in window', 'agentic-commerce-for-woocommerce' ),
number_format_i18n( $d['orders'] ),
$d['truncated']
? __( 'newest 500 — your store had more', 'agentic-commerce-for-woocommerce' )
: __( 'your real WooCommerce orders', 'agentic-commerce-for-woocommerce' ),
$d['truncated'] ? 'med' : 'info'
);
Xpay_UI::stat(
__( 'Traced to an AI assistant', 'agentic-commerce-for-woocommerce' ),
number_format_i18n( $d['attributed'] ),
sprintf(
/* translators: %s: match rate percentage. */
__( '%s%% match rate', 'agentic-commerce-for-woocommerce' ),
number_format_i18n( (float) $d['match_rate'], 1 )
),
$d['attributed'] ? 'pass' : 'low'
);
Xpay_UI::stat(
__( 'Could not be traced', 'agentic-commerce-for-woocommerce' ),
number_format_i18n( $unmatched ),
__( 'shown below with likely causes', 'agentic-commerce-for-woocommerce' ),
$unmatched ? 'med' : 'pass'
);
Xpay_UI::stat(
__( 'AI-attributed revenue', 'agentic-commerce-for-woocommerce' ),
$d['attributed'] ? Xpay_UI::money( $d['revenue'] ) : '',
sprintf(
/* translators: %s: match rate percentage. */
__( 'covers %s%% of orders', 'agentic-commerce-for-woocommerce' ),
number_format_i18n( (float) $d['match_rate'], 1 )
),
$d['attributed'] ? 'pass' : 'low',
__( 'None traced', 'agentic-commerce-for-woocommerce' )
);
echo '
';
}
/**
* Split by assistant.
*
* @param array $d Rollup.
* @return void
*/
private static function by_source( $d ) {
Xpay_UI::section(
__( 'Which assistant sent them', 'agentic-commerce-for-woocommerce' ),
__( 'Revenue is the order total at the time of purchase, in your store currency.', 'agentic-commerce-for-woocommerce' )
);
if ( ! $d['by_source'] ) {
echo '';
Xpay_UI::empty_state(
__( 'No order carried an AI signal', 'agentic-commerce-for-woocommerce' ),
__( 'Attribution fires when a shopper arrives from an assistant. None did in this window — a genuine result, not a gap in the plugin.', 'agentic-commerce-for-woocommerce' )
);
echo '
';
return;
}
echo '';
echo '| ' . esc_html__( 'Assistant', 'agentic-commerce-for-woocommerce' ) . ' | ';
echo '' . esc_html__( 'Orders', 'agentic-commerce-for-woocommerce' ) . ' | ';
echo '' . esc_html__( 'Revenue', 'agentic-commerce-for-woocommerce' ) . ' | ';
echo '' . esc_html__( 'Share of all orders', 'agentic-commerce-for-woocommerce' ) . ' | ';
echo '
';
foreach ( $d['by_source'] as $key => $row ) {
$share = $d['orders'] ? round( ( $row['n'] / $d['orders'] ) * 100, 1 ) : 0;
echo '';
echo '| ' . esc_html( Xpay_Local_Stats::source_label( $key ) ) . ' | ';
echo '' . esc_html( number_format_i18n( $row['n'] ) ) . ' | ';
echo '' . esc_html( Xpay_UI::money( $row['rev'] ) ) . ' | ';
echo '' . esc_html( number_format_i18n( $share, 1 ) ) . '% | ';
echo '
';
}
echo '
';
}
/**
* The honest part: what we could not explain, and why it happens.
*
* @param array $d Rollup.
* @return void
*/
private static function unattributed( $d ) {
$unmatched = max( 0, $d['orders'] - $d['attributed'] );
if ( ! $unmatched ) {
return;
}
Xpay_UI::section(
__( 'The orders we could not trace', 'agentic-commerce-for-woocommerce' ),
sprintf(
/* translators: %d: count of unattributed orders. */
__( '%d orders in this window carried no AI signal. Most of them are simply not from AI — but these are the reasons a real one can go missing.', 'agentic-commerce-for-woocommerce' ),
$unmatched
)
);
$causes = array(
array(
__( 'The shopper genuinely came from somewhere else', 'agentic-commerce-for-woocommerce' ),
__( 'Search, email, paid social or a direct visit. This is the majority, and it is the correct answer.', 'agentic-commerce-for-woocommerce' ),
),
array(
__( 'The assistant sent no referrer', 'agentic-commerce-for-woocommerce' ),
__( 'Some assistants strip the referring page for privacy. The visit is real; the evidence is not there to claim it.', 'agentic-commerce-for-woocommerce' ),
),
array(
__( 'A page cache stripped our tracking parameter', 'agentic-commerce-for-woocommerce' ),
__( 'Aggressive caching can drop query parameters before WordPress sees them. Our marker is excluded from the cache key where we can detect the plugin.', 'agentic-commerce-for-woocommerce' ),
),
array(
__( 'The shopper researched on one device and bought on another', 'agentic-commerce-for-woocommerce' ),
__( 'No browser-based attribution can follow that, ours included. We would rather leave it uncounted than guess.', 'agentic-commerce-for-woocommerce' ),
),
);
echo '';
foreach ( $causes as $c ) {
Xpay_UI::check( 'low', $c[0], $c[1] );
}
echo '
';
echo '' . esc_html__( 'Why the match rate matters', 'agentic-commerce-for-woocommerce' ) . '';
echo '
' . esc_html__( 'A tool that only counts the orders it can claim will always make a channel look better than it is. The match rate tells you how much of your store this number actually covers — so you know whether you are looking at the whole picture or a corner of it before you spend against it.', 'agentic-commerce-for-woocommerce' ) . '
';
}
}