Commit 061221e10ab for woocommerce
commit 061221e10ab2cc1d839dcadab03698144fcff19b
Author: Ján Mikláš <neosinner@gmail.com>
Date: Sun Sep 13 23:28:55 2026 +0200
Document Analytics customer hook timing (#68679)
* Document Analytics customer hook timing
* Add changelog entry for customer hook timing
* Remove trailing changelog whitespace
diff --git a/plugins/woocommerce/changelog/docs-analytics-customer-hook-timing b/plugins/woocommerce/changelog/docs-analytics-customer-hook-timing
new file mode 100644
index 00000000000..b7a0a1b28b3
--- /dev/null
+++ b/plugins/woocommerce/changelog/docs-analytics-customer-hook-timing
@@ -0,0 +1,3 @@
+Significance: patch
+Type: dev
+Comment: Document Analytics customer creation hook timing and cover repeated customer-history views and imports.
diff --git a/plugins/woocommerce/src/Admin/API/Reports/Customers/DataStore.php b/plugins/woocommerce/src/Admin/API/Reports/Customers/DataStore.php
index 9002e69b9af..1b6a47104e9 100644
--- a/plugins/woocommerce/src/Admin/API/Reports/Customers/DataStore.php
+++ b/plugins/woocommerce/src/Admin/API/Reports/Customers/DataStore.php
@@ -727,6 +727,9 @@ class DataStore extends ReportsDataStore implements DataStoreInterface {
/**
* Fires when a new report customer is created.
*
+ * This includes customers created during Analytics import. Rendering the order-edit
+ * customer history panel uses a read-only lookup and does not fire this action.
+ *
* @param int $customer_id Customer ID.
* @since 4.0.0
*/
diff --git a/plugins/woocommerce/tests/php/src/Internal/Admin/Orders/MetaBoxes/CustomerHistoryTest.php b/plugins/woocommerce/tests/php/src/Internal/Admin/Orders/MetaBoxes/CustomerHistoryTest.php
index 05955ee0262..4c7e61ac7a3 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Admin/Orders/MetaBoxes/CustomerHistoryTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Admin/Orders/MetaBoxes/CustomerHistoryTest.php
@@ -769,14 +769,17 @@ class CustomerHistoryTest extends WC_Unit_Test_Case {
\WC_Helper_Reports::reset_stats_dbs();
$new_customer_fired = 0;
- $callback = static function () use ( &$new_customer_fired ) {
+ $new_customer_id = null;
+ $callback = static function ( $customer_id ) use ( &$new_customer_fired, &$new_customer_id ) {
++$new_customer_fired;
+ $new_customer_id = $customer_id;
};
add_action( 'woocommerce_analytics_new_customer', $callback );
try {
ob_start();
try {
+ $this->sut->output( $order );
$this->sut->output( $order );
$output = (string) ob_get_contents();
} finally {
@@ -788,6 +791,17 @@ class CustomerHistoryTest extends WC_Unit_Test_Case {
$customers_after_render = (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$customer_lookup_table}" );
$new_customers_after_render = $new_customer_fired;
+ OrdersStatsDataStore::update( new AdminOrder( $order->get_id() ) );
+ $this->assertSame( 1, $new_customer_fired, 'The first import should fire the new-customer action once.' );
+ $this->assertSame( (int) CustomersDataStore::get_existing_customer_id_from_order( $order ), $new_customer_id, 'The action should receive the analytics customer ID linked to the order.' );
+
+ ob_start();
+ try {
+ $this->sut->output( $order );
+ $this->sut->output( $order );
+ } finally {
+ ob_end_clean();
+ }
OrdersStatsDataStore::update( new AdminOrder( $order->get_id() ) );
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table name is provided by the data store.
@@ -799,8 +813,8 @@ class CustomerHistoryTest extends WC_Unit_Test_Case {
$this->assertStringContainsString( 'order-attribution-total-orders', $output, 'Should render the metabox template.' );
$this->assertSame( 0, $customers_after_render, 'Rendering customer history should not create an analytics customer.' );
$this->assertSame( 0, $new_customers_after_render, 'Rendering customer history should not fire the new-customer action.' );
- $this->assertSame( 1, $customers_after_import, 'Importing the order should create one analytics customer.' );
- $this->assertSame( 1, $new_customer_fired, 'Importing the order should fire the new-customer action once.' );
+ $this->assertSame( 1, $customers_after_import, 'Repeated views and imports should reuse the analytics customer.' );
+ $this->assertSame( 1, $new_customer_fired, 'Repeated views and imports should not fire the new-customer action again.' );
}
/**