You can calculate total sales by state in WooCommerce by querying completed orders for a given year and grouping their totals by billing state, since this breakdown isn’t available in WooCommerce’s built-in reports by default — useful for state-level tax filing or regional performance review.
Why You Need Sales Broken Down by State
- State-level sales tax filing requirements in many US jurisdictions
- Understanding which regions drive the most revenue for marketing decisions
- WooCommerce’s core reporting doesn’t group revenue by billing state out of the box
Step 1: Add a Custom Admin Report Page
/** Add a "Sales by State" report under the WooCommerce admin menu */
add_action( 'admin_menu', 'register_sales_by_state_report_page', 9999 );
function register_sales_by_state_report_page() {
add_submenu_page(
'woocommerce',
'Sales by State',
'Sales by State',
'manage_woocommerce',
'sales_by_state_report',
'render_sales_by_state_report'
);
}Step 2: Query and Group Orders by Billing State
/** Calculate and display total sales grouped by billing state for a given year */
function render_sales_by_state_report() {
$report_year = 2024;
$sales_by_state = array();
echo "<h3>Sales by State for {$report_year} (\$)</h3>";
$orders = wc_get_orders( array(
'billing_country' => 'US',
'status' => array( 'wc-completed' ),
'limit' => -1,
'return' => 'ids',
'date_created' => strtotime( "first day of january {$report_year}" ) . '...' . strtotime( "last day of december {$report_year} 23:59:59" ),
) );
foreach ( $orders as $order_id ) {
$order = wc_get_order( $order_id );
$state = $order->get_billing_state();
$sales_by_state[ $state ] = isset( $sales_by_state[ $state ] )
? $sales_by_state[ $state ] + $order->get_total()
: $order->get_total();
}
ksort( $sales_by_state );
echo '<pre style="font-size:15px">';
print_r( $sales_by_state );
echo '</pre>';
}
Troubleshooting
Report Page Loads Slowly
Looping through every order for the full year can be slow on high-volume stores — consider limiting the query with pagination or caching results in a transient that refreshes periodically rather than recalculating on every page load.
Some States Show as Blank
Orders missing a billing state (often guest checkouts with incomplete address data) group under an empty key — filter those out or handle them as a separate “Unknown” bucket if needed.
Only Want to Include Certain Order Statuses
Adjust the status array to match how your business defines a completed sale — some stores also want to include “processing” orders in this kind of report.
Frequently Asked Questions
Does this work for countries other than the US?
Yes — change the billing_country argument to any other country code; the state/province grouping logic works the same way.
Can I export this report to a spreadsheet?
Yes — replace the print_r() output with a CSV export function that writes the same array to a downloadable file instead.
Is there a built-in WooCommerce report for this?
Not by billing state specifically — WooCommerce Analytics offers various breakdowns, but a direct state-level sales report typically requires this kind of custom snippet.
Conclusion
Calculating total sales by state in WooCommerce requires a custom admin report page combined with a query that groups completed orders by billing state. Adjust the year, country, and order statuses to match exactly what your business needs to report on.
See also How to Get Total Sales by Product Category in WooCommerce.
Prefer no code? All-in-One Utilities Woo Add-on handles this kind of change from a settings screen. Its Sales by state and order export guide also shows how.