WooCommerce HPOS Analytics Showing Zero Revenue After Migration

WooCommerce Analytics shows zero revenue after HPOS migration but orders look fine on the orders screen? Here is the lookup table the importer skips and the rebuild that fixes it.
WooCommerceHPOSAnalytics
May 26, 20266 min read1050 words

The Problem

A client pinged me yesterday in a panic. Their store had run the High-Performance Order Storage migration two nights earlier on a sleepy maintenance window, the orders screen looked perfect, and orders were still flowing in. Then they opened WooCommerce → Analytics → Revenue and the entire chart was flat. Net sales: $0. Gross sales: $0. Refunds: $0. Orders: 0. Every range, every preset, every comparison period.

The catch is that WooCommerce → Orders showed thousands of completed orders with real totals. The order edit screens worked. The REST API returned correct data. Customers were getting receipts. Only Analytics was lying. I ran into this on a client project two days ago and saw three more variants of it in r/Woocommerce this morning, so it is worth writing down.

The store was on WooCommerce 10.7, WordPress 6.9, and the HPOS migration tool from the official WooCommerce → Status → Tools page had reported "Migration completed successfully" with no warnings.

Why It Happens

WooCommerce Analytics does not read from wp_wc_orders directly. It reads from a separate set of lookup tables that the analytics importer builds in the background: wp_wc_order_stats, wp_wc_order_product_lookup, wp_wc_order_tax_lookup, and wp_wc_order_coupon_lookup. Those tables are populated by Action Scheduler jobs that fire when an order is created, updated, or refunded.

Under the legacy storage model the importer subscribed to the woocommerce_new_order and woocommerce_update_order actions on wp_posts. After HPOS migration those actions still fire, but only if the order is created or touched through WC_Order methods. The migration tool copies rows from wp_posts straight into wp_wc_orders with a bulk INSERT and never triggers the per-order hooks. Result: the source of truth moved, but the lookup tables never heard about it. Analytics keeps querying empty tables.

The HPOS migration docs mention rebuilding the lookup tables only in passing, near the bottom of the troubleshooting section. Most teams miss it because the migration report does not warn that analytics needs a separate rebuild.

The Fix

The fix has three steps: confirm the lookup tables are empty, queue the rebuild through WP-CLI, and then verify the data actually lands. Doing this through the admin UI rebuild button works on small stores but silently times out on anything over 50k orders.

Step 1: Confirm the lookup tables are empty.

SELECT COUNT(*) AS lookup_rows FROM wp_wc_order_stats;
SELECT COUNT(*) AS hpos_rows FROM wp_wc_orders WHERE status IN ('wc-completed','wc-processing','wc-refunded');

If lookup_rows is dramatically lower than hpos_rows (or zero), the importer never ran on the migrated rows and this is your issue. If both numbers match roughly, the problem is something else (often a date range bug from a stuck woocommerce_analytics_report_cache transient — clear it from the options table and stop reading here).

Step 2: Queue the analytics rebuild through WP-CLI.

The admin button calls WC_Admin_Reports_Sync::regenerate_report_data() and queues one Action Scheduler job per batch of 25 orders. On a 200k-order store that is 8,000 jobs, and the request that schedules them will time out long before it finishes queueing. WP-CLI bypasses the HTTP timeout entirely:

wp wc analytics reset --user=1
wp action-scheduler run --group=wc-admin-data --batch-size=50

wc analytics reset truncates the four lookup tables and schedules the regeneration jobs. The second command processes the queue in the foreground until it is empty. Keep an eye on it: a 200k-order store takes 15–25 minutes on decent hosting. If the runner stops because of a stuck job, list the failed actions:

wp action-scheduler list --status=failed --group=wc-admin-data --per-page=20

The most common failure is a single order with a malformed _order_total meta from a legacy import. Fix the meta value or skip the order with wp action-scheduler cancel <id> and re-run.

Step 3: Verify the data lands.

Once the queue is empty, count the lookup rows again:

SELECT COUNT(*) FROM wp_wc_order_stats WHERE status IN ('wc-completed','wc-processing');
SELECT SUM(net_total) FROM wp_wc_order_stats WHERE date_created >= '2026-05-01';

The first count should match the HPOS row count for those statuses within a few rows. The second query gives you a sanity-checkable revenue number for May. Compare it against the order export from WooCommerce → Orders filtered to the same date range. If it matches, refresh the Analytics dashboard and the chart will be back.

One extra step for stores still ingesting orders during the rebuild: the importer queues new orders to the back of the same Action Scheduler queue. If checkout is busy, new orders can land in the lookup tables before older historical ones, and Analytics will show partial data while the queue drains. That is normal. The rebuild is correct when the queue is empty, not when the first new orders show up.

If you have a custom plugin that listens for analytics events (anything subscribing to woocommerce_analytics_update_order_stats), check that it returns the original args. A common silent break is a filter callback that mutates the row array and forgets to return it, which writes null to wp_wc_order_stats and makes that row invisible to the dashboard without throwing an error.

The Lesson

The HPOS migration tool moves the orders. It does not rebuild analytics. Plan a separate maintenance window for wp wc analytics reset plus a foreground action-scheduler run, and never trust the admin UI rebuild button on stores over 50k orders. The lookup tables are a denormalised copy of the order data and they have to be regenerated explicitly when the source of truth changes.

If your analytics dashboard has been flat since you migrated to HPOS and nobody on the team knows where the revenue went, that is the exact kind of post-migration audit I run for clients. See my services. For a related HPOS gotcha on bulk order status changes, read WooCommerce HPOS bulk order status update failing silently.

Analytics flat after an HPOS migration? Let me fix it.

Back to blogStart a project