WooCommerce: Calculate Sales by State

You’re filing your tax returns and need to know how much you earned in each state… but then find out WooCommerce doesn’t give you this calculation by default within its reports!

Don’t worry – today I’ll share a quick snippet so that you can calculate the amount you need in a second. Feel free to change the year, the country and the states in the snippet.

If you click on the brand new “Sales by State” submenu link, you will see this custom admin page with the total amount for each state as defined inside the snippet below

PHP Snippet: Generate Sales by State Report @ Custom WooCommerce Admin Subpage

/**
 * @snippet       Get Sales by State @ WooCommerce Admin
 * @how-to        businessbloomer.com/woocommerce-customization
 * @author        Rodolfo Melogli, Business Bloomer
 * @testedwith    WooCommerce 8
 * @community     https://businessbloomer.com/club/
 */

// -----------------------
// 1. Create "Sales by State" submenu page

add_action( 'admin_menu', 'bbloomer_wp_dashboard_woocommerce_subpage', 9999 );
 
function bbloomer_wp_dashboard_woocommerce_subpage() {
	add_submenu_page( 'woocommerce', 'Sales by State', 'Sales by State', 'manage_woocommerce', 'bb_sales_by_state', 'bbloomer_yearly_sales_by_state', 9999 );
}

// -----------------------
// 2. Calculate sales for all states

function bbloomer_yearly_sales_by_state() {	
	
	$year = 2023;
	$sales_by_state = array();
	
	echo "<h3>Sales by State For Year {$year} ($)</h3>";
	
	$args = array(
		'billing_country' => 'US', // COUNTRY
		'status' => array( 'wc-completed' ),
		'type' => 'shop_order',
		'limit' => -1,
		'return' => 'ids',
		'date_created' => strtotime( "first day of january " . $year ) . '...' . strtotime( "last day of december " . $year ),
	);
	$orders = wc_get_orders( $args );

	foreach ( $orders as $order_id ) {
		$order = wc_get_order( $order_id );
		$sales_by_state[$order->get_billing_state()] = isset( $sales_by_state[$order->get_billing_state()] ) ? $sales_by_state[$order->get_billing_state()] + $order->get_total() : $order->get_total();
	}
	
	echo '<pre style="font-size: 16px">';
	ksort( $sales_by_state );
	print_r( $sales_by_state );
	echo '</pre>';
 
}

Where to add custom code?

You should place custom PHP in functions.php and custom CSS in style.css of your child theme: where to place WooCommerce customization?

This code still works, unless you report otherwise. To exclude conflicts, temporarily switch to the Storefront theme, disable all plugins except WooCommerce, and test the snippet again: WooCommerce troubleshooting 101

Related content

Rodolfo Melogli

Business Bloomer Founder

Author, WooCommerce expert and WordCamp speaker, Rodolfo has worked as an independent WooCommerce freelancer since 2011. His goal is to help entrepreneurs and developers overcome their WooCommerce nightmares. Rodolfo loves travelling, chasing tennis & soccer balls and, of course, wood fired oven pizza. Follow @rmelogli

39 thoughts on “WooCommerce: Calculate Sales by State

  1. Hello. Does this code snippet still work now that WooCommerce has done away with the Reports section and now uses the Analytics section? Thanks!

    1. Works for me – I have WooCommerce Analytics disabled lol!

  2. Don’t know how everyone got it to work. As a newbie, I don’t know where to put this code. I followed the video link which led me to an account creation page. Added details, got an email created logged in, and reset the password. Now What? I can see that there is an order created but cannot open that video. If I come back here and click the video link again, It is asking again to create an account.

    I am sure the provided code works very well but it is of no use for a newbie.

    BTW I am not looking for pointers on where to put the code, I am just bringing up the workflow of this article/site.

    1. Thanks for your feedback! I’ve revised the sign-up process, try again and let me know

  3. Is it possible to add Sales by State as the first tab? Before Sales by date?

    1. Hi, thanks so much for your comment! Yes, this is definitely possible, but I’m afraid it’s custom work. If you’d like to get a quote, feel free to contact me here. Thanks a lot for your understanding!

  4. I updated Fred D.’s code to include some line breaks for list of states, and also to edit the html code that got inserted in his post.

    /**
     * @snippet       Get Sales by State @ WooCommerce Admin
     * @how-to        businessbloomer.com/woocommerce-customization
     * @sourcecode    https://businessbloomer.com/?p=72853
     * @author        Rodolfo Melogli, Business Bloomer, update by Fred D.
     * @testedwith    WooCommerce 3.1.2
     */
     
    // -----------------------
    // 1. Create extra tab under Reports / Orders
     
    add_filter( 'woocommerce_admin_reports', 'bbloomer_admin_add_report_orders_tab' );
     
    function bbloomer_admin_add_report_orders_tab( $reports ) { 
     
    $array = array(
        'sales_by_state' => array(
            'title' => 'Sales by state',
            'description' => '',
            'hide_title' => 1,
            'callback' => 'bbloomer_yearly_sales_by_state'
        )
    );
     
    $reports['orders']['reports'] = array_merge($reports['orders']['reports'],$array);
     
    return $reports; 
    }
     
    // -----------------------
    // 2. Calculate sales by state
    
    function bbloomer_yearly_sales_by_state() {
     
        $year = 2019; // change this if needed
        $total_ca = $total_wa = 0; // add states if needed
     
        $args = [
            'post_type' => 'shop_order',
            'posts_per_page' => '-1',
            'year' => $year,
            'post_status' => ['wc-completed']
        ];
        $my_query = new WP_Query($args);
        $orders = $my_query->posts;
     
        $usArr = array();
        $caArr = array();
        $mxArr = array();
        //$salesArr = array();
         
        $usTotal = 0;
        $caTotal = 0;
        $mxTotal = 0;
             
        foreach ($orders as $order => $value) 
        {
            $order_id = $value->ID;
            $order = wc_get_order($order_id);
            $order_data = $order->get_data();
             
            if ( $order_data['billing']['country'] === 'US' ) {
                $myTotal = $order->get_total();
                $usTotal += $myTotal;
                $usArr[$order_data['billing']['state']] += $myTotal;
            }
             
            if ( $order_data['billing']['country'] === 'CA' ) {
                $myTotal = $order->get_total();
                $caTotal += $myTotal;
                $caArr[$order_data['billing']['state']] += $myTotal;
            }
             
            if ( $order_data['billing']['country'] === 'MX' ) {
                $myTotal = $order->get_total();
                $mxTotal += $myTotal;
                $mxArr[$order_data['billing']['state']] += $myTotal;
            }
        }
     
        arsort($usArr);
        arsort($caArr);
        arsort($mxArr);
         
        echo "Sales by State for Year " . $year . " for the USA:<br>";
        foreach($usArr as $usState => $usSalesValue)       
        {
            echo $usState . ": " . wc_price($usSalesValue) . "<br>";
             
        }
        echo "Total US Sales: " . $usTotal; 
        echo "</p>";    
         
        echo "Sales by Province for Year " . $year . " for Canada:<br>";
        foreach($caArr as $caState => $caSalesValue)       
        {
            echo $caState . ": " . wc_price($caSalesValue) . "<br>";
             
        }
        echo "Total Canada Sales: " . $caTotal; 
        echo "</p>";
     
        echo "Sales by State for Year " . $year . " for Mexico:<br>";
        foreach($mxArr as $mxState => $mxSalesValue)       
        {
            echo $mxState . ": " . wc_price($mxSalesValue) . "<br>";
             
        }
        echo "Total Mexico Sales: " . $mxTotal; 
        echo "</p>";
     
     
    }
    
    1. Nice!

  5. Cool, thank you!
    I updated it a bit to make it dynamically build out the states. Could modify a bit more to automatically do the countries too, but this was all I needed for now. Hope it helps:

    function bbloomer_yearly_sales_by_state() {
    
        $year = 2019; // change this if needed
        $total_ca = $total_wa = 0; // add states if needed
    
        $args = [
            'post_type' =&gt; 'shop_order',
            'posts_per_page' =&gt; '-1',
            'year' =&gt; $year,
            'post_status' =&gt; ['wc-completed']
        ];
        $my_query = new WP_Query($args);
        $orders = $my_query-&gt;posts;
    
        $usArr = array();
        $caArr = array();
        $mxArr = array();
        //$salesArr = array();
        
        $usTotal = 0;
        $caTotal = 0;
        $mxTotal = 0;
            
        foreach ($orders as $order =&gt; $value) 
        {
            $order_id = $value-&gt;ID;
            $order = wc_get_order($order_id);
            $order_data = $order-&gt;get_data();
            
            if ( $order_data['billing']['country'] === 'US' ) {
                $myTotal = $order-&gt;get_total();
                $usTotal += $myTotal;
                $usArr[$order_data['billing']['state']] += $myTotal;
            }
            
            if ( $order_data['billing']['country'] === 'CA' ) {
                $myTotal = $order-&gt;get_total();
                $caTotal += $myTotal;
                $caArr[$order_data['billing']['state']] += $myTotal;
            }
            
            if ( $order_data['billing']['country'] === 'MX' ) {
                $myTotal = $order-&gt;get_total();
                $mxTotal += $myTotal;
                $mxArr[$order_data['billing']['state']] += $myTotal;
            }
        }
    
        arsort($usArr);
        arsort($caArr);
        arsort($mxArr);
        
        echo "Sales by State for Year " . $year . " for the USA:";
        foreach($usArr as $usState =&gt; $usSalesValue)       
        {
            echo $usState . ": " . wc_price($usSalesValue) . "";
            
        }
        echo "Total US Sales: " . $usTotal; 
        echo "";    
        
        echo "Sales by Province for Year " . $year . " for Canada:";
        foreach($caArr as $caState =&gt; $caSalesValue)       
        {
            echo $caState . ": " . wc_price($caSalesValue) . "";
            
        }
        echo "Total Canada Sales: " . $caTotal; 
        echo "";
    
        echo "Sales by State for Year " . $year . " for Mexico:";
        foreach($mxArr as $mxState =&gt; $mxSalesValue)       
        {
            echo $mxState . ": " . wc_price($mxSalesValue) . "";
            
        }
        echo "Total Mexico Sales: " . $mxTotal; 
        echo "";
    
    
    }
    
    1. Awesome! All your HTML chars have been decoded and show like “&gt” for example. If you want to send a revision, feel free to do so

      1. For anyone wanting to use this code, there are some HTML entity references that were triggering a fatal error on my site. Run a search and replace for [php]>[php] and change it to [php]>[php] and this snippet will work perfectly.

        1. Ok, my comment above got auto-corrected. The HTML entity you want to replace with “>” is “>”

  6. It works great for me for all years except 2019! I don’t fully understand why, I can parse data for 2018 and 2020 but not for 2019. I get the following error: “Fatal error: Allowed memory size of 805306368 bytes exhausted (tried to allocate 20480 bytes) in /home/dermapla/public_html/wp-includes/wp-db.php on line 1995”

    Just a heads up. I do appreciate the snippet though!

    I suppose I will try to find a different solution.

    1. I guess you have too many orders in 2019 and the snippet crashes. It is definitely possible to fix this in regard to performance, but I’m afraid it’s custom work. If you’d like to get a quote, feel free to contact me here. Thanks a lot for your understanding!

  7. This code works but this is slower version. Doesn’t work with huge data. Better if this code written for Mysql Query.

    1. Ok thank you!

  8. Awesome. This helped beyond measure!

    Took some time to add all 50 states to the array but otherwise, was excellent. If you do ever build a plugin for this setup so that users could just install and enter the date range, I would pay for that! 🙂

    1. Thank you!

      1. the following line generates an error now in the current WooCommerce Orders page:

        $reports['orders']['reports'] = array_merge($reports['orders']['reports'],$array);

        Error reads:

        Warning: array_merge(): Expected parameter 1 to be an array, null given in /home/kessler5/public_html/wp-content/themes/flatsome-child/functions.php on line 135

        Line 135 is where it sits in my child theme’s functions.php file of course. From what I can tell, it is not creating any issues anywhere else.

        1. Not sure if this is due to the fact WooCommerce discontinued their reports admin. If you find a fix let me know!

          1. I have the same issue. The extra report option causes the array_merge error and I have been unable to figure out how to correct this. Any ideas? Love the snippet otherwise!!

            1. Finally found a fix. Replace this

              $reports['orders']['reports'] = array_merge($reports['orders']['reports'],$array);

              with this:

              if (isset($reports['orders']) && is_array($reports['orders']['reports']) && is_array($array)) {
              	$reports['orders']['reports'] = array_merge($reports['orders']['reports'],$array);	
              }
                1. So I have used ChatGPT to vastly improve the functionality of this. Feel free to use if you like. I have ported my version to be a Plugin rather than a Snippet, but both options work.

                  New features include:
                  – CSV Export
                  – Automatic Calculations of Remaining Sales vs a Sales Limit (Economic Nexus)
                  – Editable Limits

                  
                  // Handle CSV Export Action
                  add_action('admin_init', 'handle_csv_export_action');
                  
                  function handle_csv_export_action() {
                      if (isset($_GET['action']) && $_GET['action'] === 'export_csv' && isset($_GET['page']) && $_GET['page'] === 'sales_tax_status') {
                          $year = get_option('state_sales_year', date('Y'));
                          $state_totals = array_fill_keys(
                              ['AL', 'AK', 'AZ', 'AR', 'CA', 'CO', 'CT', 'DE', 'DC', 'FL', 'GA', 'HI', 'ID', 'IL', 'IN', 'IA', 'KS', 'KY', 'LA', 'ME', 'MD', 'MA', 'MI', 'MN', 'MS', 'MO', 'MT', 'NE', 'NV', 'NH', 'NJ', 'NM', 'NY', 'NC', 'ND', 'OH', 'OK', 'OR', 'PA', 'RI', 'SC', 'SD', 'TN', 'TX', 'UT', 'VT', 'VA', 'WA', 'WV', 'WI', 'WY'],
                              0
                          );
                          $state_limits = get_option('state_sales_limits', []);
                  
                          // Calculate totals again for export
                          $args = [
                              'post_type' => 'shop_order',
                              'posts_per_page' => '-1',
                              'year' => $year,
                              'post_status' => ['wc-completed', 'wc-processing']
                          ];
                          $my_query = new WP_Query($args);
                          $orders = $my_query->posts;
                  
                          foreach ($orders as $value) {
                              $order_id = $value->ID;
                              $order = wc_get_order($order_id);
                              $order_data = $order->get_data();
                  
                              if ($order_data['billing']['country'] === 'US' && isset($state_totals[$order_data['billing']['state']])) {
                                  $state_totals[$order_data['billing']['state']] += $order->get_total();
                              }
                          }
                  
                          export_sales_by_state_to_csv($state_totals, $state_limits, $year);
                          exit;
                      }
                  }
                  
                  function export_sales_by_state_to_csv($state_totals, $state_limits, $year) {
                      header('Content-Type: text/csv; charset=utf-8');
                      header('Content-Disposition: attachment; filename=sales_by_state_' . $year . '.csv');
                  
                      $output = fopen('php://output', 'w');
                      fputcsv($output, ['State', 'Total Sales', 'Limit', 'Remaining']); // Header row
                  
                      foreach ($state_totals as $state => $total) {
                          $limit = isset($state_limits[$state]) ? $state_limits[$state] : 100000; // Default to 100k
                          if ($limit === -1) {
                              // No limit case
                              fputcsv($output, [wc_get_state_label($state), $total, 'No Limit', 'N/A']);
                          } else {
                              // Regular case
                              $remaining = max($limit - $total, 0);
                              fputcsv($output, [wc_get_state_label($state), $total, $limit, $remaining]);
                          }
                      }
                  
                      fclose($output);
                      exit;
                  }
                  
                  
                  // -----------------------
                  // 1. Create extra tab under Reports / Orders
                  
                  add_filter( 'woocommerce_admin_reports', 'bbloomer_admin_add_report_orders_tab' );
                  
                  function bbloomer_admin_add_report_orders_tab( $reports ) {
                  
                      $array = array(
                          'sales_by_state' => array(
                              'title' => 'Sales by State',
                              'description' => '',
                              'hide_title' => 1,
                              'callback' => 'bbloomer_yearly_sales_by_state'
                          )
                      );
                  
                      if (isset($reports['orders']) && is_array($reports['orders']['reports']) && is_array($array)) {
                          $reports['orders']['reports'] = array_merge($reports['orders']['reports'], $array);
                      }
                  
                      return $reports;
                  }
                  
                  // -----------------------
                  // 2. Calculate sales by state
                  
                  function bbloomer_yearly_sales_by_state() {
                  
                  	$year = get_option('state_sales_year', date('Y'));
                      $state_totals = array_fill_keys(
                          ['AL', 'AK', 'AZ', 'AR', 'CA', 'CO', 'CT', 'DE', 'DC', 'FL', 'GA', 'HI', 'ID', 'IL', 'IN', 'IA', 'KS', 'KY', 'LA', 'ME', 'MD', 'MA', 'MI', 'MN', 'MS', 'MO', 'MT', 'NE', 'NV', 'NH', 'NJ', 'NM', 'NY', 'NC', 'ND', 'OH', 'OK', 'OR', 'PA', 'RI', 'SC', 'SD', 'TN', 'TX', 'UT', 'VT', 'VA', 'WA', 'WV', 'WI', 'WY'],
                          0
                      );
                  
                      $state_limits = get_option('state_sales_limits', []);
                  
                      $args = [
                          'post_type' => 'shop_order',
                          'posts_per_page' => '-1',
                          'year' => $year,
                          'post_status' => ['wc-completed', 'wc-processing']
                      ];
                      $my_query = new WP_Query($args);
                      $orders = $my_query->posts;
                  
                      foreach ($orders as $value) {
                          $order_id = $value->ID;
                          $order = wc_get_order($order_id);
                          $order_data = $order->get_data();
                  
                          if ($order_data['billing']['country'] === 'US' && isset($state_totals[$order_data['billing']['state']])) {
                              $state_totals[$order_data['billing']['state']] += $order->get_total();
                          }
                      }
                  
                      echo "<h2>Sales by State for Year " . $year . "</h2>";
                      echo '<a href="' . admin_url('admin.php?page=sales_tax_status&action=export_csv') . '" class="button button-primary" style="margin-bottom: 10px;">Export to CSV</a>';
                      echo '<table class="wp-list-table widefat fixed striped">';
                      echo '<thead><tr><th>State</th><th>Total Sales</th><th>Limit</th><th>Remaining</th></tr></thead>';
                      echo '<tbody>';
                  
                      foreach ($state_totals as $state => $total) {
                          $limit = isset($state_limits[$state]) ? $state_limits[$state] : 100000; // Default to 100k
                  if ($limit === -1) {
                      echo "<tr><td>" . esc_html(wc_get_state_label($state)) . "</td><td>" . wc_price($total) . "</td><td>No Limit</td><td>N/A</td></tr>";
                  } else {
                      $remaining = max($limit - $total, 0);
                      echo "<tr><td>" . esc_html(wc_get_state_label($state)) . "</td><td>" . wc_price($total) . "</td><td>" . wc_price($limit) . "</td><td>" . wc_price($remaining) . "</td></tr>";
                  }
                      }
                  
                      echo '</tbody></table>';
                  }
                  
                  /**
                   * Utility function to get state labels for displaying names.
                   */
                  function wc_get_state_label($state_code) {
                      $states = WC()->countries->get_states('US');
                      return isset($states[$state_code]) ? $states[$state_code] : $state_code;
                  }
                  
                  // -----------------------
                  // 3. Add Sales Tax Status Admin Menu
                  
                  add_action('admin_menu', 'add_sales_tax_status_menu');
                  
                  function add_sales_tax_status_menu() {
                  add_menu_page(
                      'Sales Tax Status',             // Page title
                      'Sales Tax Status',             // Menu title
                      'manage_options',               // Capability
                      'sales_tax_status',             // Menu slug
                      'sales_tax_status_dashboard',   // Function to render dashboard
                      'dashicons-chart-area',         // Icon
                      26                              // Position
                  );
                  
                  add_submenu_page(
                      'sales_tax_status',
                      'Sales by State Report',
                      'Sales Report',
                      'manage_options',
                      'state_sales_report',
                      'sales_by_state_report_page'
                  );
                  
                  add_submenu_page(
                      'sales_tax_status',
                      'Edit Limits',
                      'Edit Limits',
                      'manage_options',
                      'state_sales_limits',
                      'state_sales_limits_page'
                  );
                  }
                  
                  // -----------------------
                  // -----------------------
                  // 4. Sales Tax Status Dashboard
                  
                  function sales_tax_status_dashboard() {
                      echo '<div class="wrap">';
                      echo '<h1>Sales Tax Status</h1>';
                      echo '<p><a href="admin.php?page=state_sales_report" class="button button-primary">View Sales Report</a></p>';
                      echo '<p><a href="admin.php?page=state_sales_limits" class="button button-secondary">Edit State Sales Limits</a></p>';
                      echo '</div>';
                  }
                  
                  // -----------------------
                  // 5. Sales Report Page
                  
                  function sales_by_state_report_page() {
                      if (!function_exists('WC')) {
                          echo '<div class="error"><p>WooCommerce is not active. Please activate WooCommerce to use this report.</p></div>';
                          return;
                      }
                  
                      try {
                          $year = get_option('state_sales_year', date('Y')); // Retrieve saved year
                          $states = WC()->countries->get_states('US') ?: [];
                          $state_totals = array_fill_keys(array_keys($states), 0); // Initialize totals
                          $state_limits = get_option('state_sales_limits', []); // Retrieve saved limits
                  
                          // Fetch WooCommerce orders
                          $orders = wc_get_orders([
                              'status' => ['wc-completed', 'wc-processing'],
                              'limit' => -1,
                              'date_created' => "$year-01-01...$year-12-31"
                          ]);
                  
                          // Aggregate totals by state
                          foreach ($orders as $order) {
                              if ($order instanceof WC_Order_Refund) {
                                  continue; // Skip refunds
                              }
                  
                              $state = $order->get_billing_state();
                              $total = $order->get_total();
                  
                              // Add totals for valid states
                              if (isset($state_totals[$state])) {
                                  $state_totals[$state] += $total;
                              }
                          }
                  
                          // Generate report table
                          echo "<h1>Sales by State for $year</h1>";
                          echo '<a href="' . admin_url('admin.php?page=sales_tax_status&action=export_csv') . '" class="button button-primary" style="margin-bottom: 10px;">Export to CSV</a>';
                          echo '<table class="wp-list-table widefat fixed striped">';
                          echo '<thead><tr><th>State</th><th>Total Sales</th><th>Limit</th><th>Remaining</th></tr></thead><tbody>';
                  
                          foreach ($state_totals as $state => $total) {
                              $limit = $state_limits[$state] ?? 100000; // Default to 100k
                              if ($limit === -1) {
                                  echo "<tr><td>" . esc_html(wc_get_state_label($state)) . "</td><td>" . wc_price($total) . "</td><td>No Limit</td><td>N/A</td></tr>";
                              } else {
                                  $remaining = max($limit - $total, 0);
                                  echo "<tr><td>" . esc_html(wc_get_state_label($state)) . "</td><td>" . wc_price($total) . "</td><td>" . wc_price($limit) . "</td><td>" . wc_price($remaining) . "</td></tr>";
                              }
                          }
                  
                          echo '</tbody></table>';
                  
                      } catch (Exception $e) {
                          // Display error message
                          echo '<div class="error"><p>There was an error generating the report: ' . esc_html($e->getMessage()) . '</p></div>';
                      }
                  }
                  
                  // -----------------------
                  // 6. State Limits Editing Page
                  
                  function state_sales_limits_page() {
                      if (!current_user_can('manage_options')) {
                          return;
                      }
                  
                      $current_year = get_option('state_sales_year', date('Y')); // Default to current year
                      if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['sales_year'])) {
                          check_admin_referer('save_state_limits');
                          $state_limits = [];
                          foreach ($_POST['state_limits'] as $state => $limit) {
                              $state_limits[$state] = isset($_POST['no_limit'][$state]) ? -1 : floatval($limit);
                          }
                          update_option('state_sales_limits', $state_limits);
                          update_option('state_sales_year', intval($_POST['sales_year']));
                          echo '<div class="updated"><p>Limits and year updated successfully!</p></div>';
                      }
                  
                      $state_limits = get_option('state_sales_limits', []);
                      $states = WC()->countries->get_states('US');
                  
                      echo '<div class="wrap">';
                      echo '<h1>Edit State Sales Limits</h1>';
                      echo '<form method="post">';
                      wp_nonce_field('save_state_limits');
                      echo '<table class="form-table">';
                      echo '<tr><th scope="row"><label for="sales_year">Calculation Year</label></th>';
                      echo '<td><input type="number" name="sales_year" id="sales_year" value="' . esc_attr($current_year) . '" step="1" min="2000" max="' . date('Y') . '" /></td></tr>';
                  
                      foreach ($states as $code => $name) {
                          $value = isset($state_limits[$code]) ? $state_limits[$code] : 100000; // Default 100k
                          echo "<tr><th scope='row'><label for='state_limit_$code'>$name ($code)</label></th>";
                          echo "<td>";
                          echo "<input type='number' name='state_limits[$code]' id='state_limit_$code' value='" . esc_attr($value === -1 ? '' : $value) . "' step='0.01'>";
                          echo "<label><input type='checkbox' name='no_limit[$code]' value='1'" . ($value === -1 ? ' checked' : '') . "> No Limit</label>";
                          echo "</td></tr>";
                      }
                  
                      echo '</table>';
                      echo '<p class="submit"><input type="submit" class="button-primary" value="Save Changes"></p>';
                      echo '</form>';
                      echo '</div>';
                  }
                  
                  
                  
    2. Agreed Dave, I would absolutely pay for a plugin that did this.

  9. This is so helpful. Thank you! I have four states that I needed to pull information for, and this did the trick!

    How difficult would it be to display by month within the year totals? For instance, 2017 is already showing for the year – then filter down by month within the state totals like so:

    WA > Jan – $xxx; Feb – $xxx; Mar – $xxx | CA > Jan – $xxx; Feb – $xxx; Mar – $xxx and so on?

    1. Karen, thanks so much for your comment! Yes, this is totally possible – but unfortunately this is custom work and I cannot provide a complementary solution here via the blog comments. Thanks a lot for your understanding! ~R

  10. Hello, I am using Woocommerce Brand Plugin.

    Plugin Link: https://woocommerce.com/products/brands/

    I want to Get Sales by Brand Report. How can I do this ?

    Regards

    1. James, thanks so much for your comment! Yes, this is possible – but unfortunately this is custom work and I cannot provide a complementary solution here via the blog comments. Thanks a lot for your understanding! ~R

  11. Cool Idea!

    What if i need to make this for Romania? Should i put RO to states?

    Because now it gives me an error.

    We put Romanian states using a plugin, but your snippet doesnt seem to work with that states https://prntscr.com/gnejer

    Can you direct me how to change? thanks

    1. Cristian, thanks for your comment! I believe I already helped you via Business Bloomer Club support. Hope you managed to fix it 🙂

  12. Works great! Thanks. How about a list of 10 states with most sales?

    1. Thank you 🙂 Sure, that can be done, you will need to do some PHP edits 🙂

  13. Every morning I wake-up I look forward to seeing your e-mail. Another awesome PHP snippet I’ve already added all the states and they work fabulously. Great work.

  14. Really nice excellent tutorial

Questions? Feedback? Customization? Leave your comment now!
_____

If you are writing code, please wrap it like so: [php]code_here[/php]. Failure to complying with this, as well as going off topic or not using the English language will result in comment disapproval. You should expect a reply in about 2 weeks - this is a popular blog but I need to get paid work done first. Please consider joining the Business Bloomer Club to get quick WooCommerce support. Thank you!

Your email address will not be published. Required fields are marked *