Full Answer
The gap is architectural, not a plugin bug. Every client-side GA4 setup — gtag, GTM, or a tracking plugin — depends on JavaScript running in a shopper's browser. A refund has no shopper and no browser: a store admin clicks Refund inside wp-admin, WooCommerce adjusts the order, and the event that GA4 is waiting for simply has no place to execute. Google's own event reference (https://support.google.com/analytics/answer/9267735) lists refund alongside purchase as a recommended ecommerce event, complete with transaction_id matching so the original revenue is reversed cleanly. The schema is ready; the delivery mechanism isn't there.
Translation: your GA4 revenue is a gross figure wearing a net figure's name tag. Every refunded order stays counted at full value, ROAS reads higher than reality, and Smart Bidding optimises toward products that quietly come back. The same admin-side blind spot breaks order edits too — Seresa's analysis of how admin changes diverge from GA4 (https://seresa.io/blog/data-quality-validation/woocommerce-order-edits-are-permanently-breaking-your-ga4-revenue) shows how the drift builds without any error appearing anywhere.
The reliable fix runs server-side. WooCommerce fires a refund hook the moment a refund is created, and a server-side pipeline listening there can send the refund event with the matching transaction_id — no browser required. Developers can script this against the GA4 Measurement Protocol, or use tooling built for it, such as Seresa's Transmute Engine, which fires refund events from the WooCommerce refund hook to keep GA4 revenue aligned with what the store actually kept.