Commit 72c56a65c1 for woocommerce
commit 72c56a65c1a8f6d27541984b7520abb1fd779bd4
Author: Vladimir Reznichenko <kalessil@gmail.com>
Date: Mon Jan 26 08:57:55 2026 +0100
[Performance] Tracks: defer `product_add_publish` event when importing products. (#62888)
When `Allow usage of WooCommerce to be tracked` is enabled in settings, deferred event tracking improves products import performance.
diff --git a/plugins/woocommerce/changelog/performance-61316-defer-product-published-tracks-when-importing b/plugins/woocommerce/changelog/performance-61316-defer-product-published-tracks-when-importing
new file mode 100644
index 0000000000..15214cd359
--- /dev/null
+++ b/plugins/woocommerce/changelog/performance-61316-defer-product-published-tracks-when-importing
@@ -0,0 +1,4 @@
+Significance: patch
+Type: performance
+
+Products: defer publishing the 'product_add_publish' Tracks-event when importing products.
diff --git a/plugins/woocommerce/includes/tracks/class-wc-site-tracking.php b/plugins/woocommerce/includes/tracks/class-wc-site-tracking.php
index ace7306b2a..69462ae3f0 100644
--- a/plugins/woocommerce/includes/tracks/class-wc-site-tracking.php
+++ b/plugins/woocommerce/includes/tracks/class-wc-site-tracking.php
@@ -234,6 +234,24 @@ class WC_Site_Tracking {
call_user_func( $tracker_init_method );
}
}
+
+ add_filter( 'pre_update_option_woocommerce_allow_tracking', array( __CLASS__, 'maybe_unschedule_deferred_tracks' ) );
+ }
+
+ /**
+ * When the tracking is getting disabled, unschedules all deferred tracks.
+ *
+ * @internal
+ * @since 10.6.0
+ *
+ * @param string $new_option_value The new, unserialized option value.
+ * @return string
+ */
+ public static function maybe_unschedule_deferred_tracks( $new_option_value ) {
+ if ( 'yes' !== $new_option_value ) {
+ as_unschedule_all_actions( '', array(), 'woocommerce-tracks' );
+ }
+ return $new_option_value;
}
/**
diff --git a/plugins/woocommerce/includes/tracks/events/class-wc-products-tracking.php b/plugins/woocommerce/includes/tracks/events/class-wc-products-tracking.php
index 026e611bb4..971a77c14a 100644
--- a/plugins/woocommerce/includes/tracks/events/class-wc-products-tracking.php
+++ b/plugins/woocommerce/includes/tracks/events/class-wc-products-tracking.php
@@ -20,7 +20,15 @@ class WC_Products_Tracking {
/**
* Tracks source.
*/
- const TRACKS_SOURCE = 'product-legacy-editor';
+ public const TRACKS_SOURCE = 'product-legacy-editor';
+
+ /**
+ * Deferred Tracks callback.
+ *
+ * @internal
+ * @since 10.6.0
+ */
+ public const TRACK_PRODUCT_PUBLISHED_CALLBACK = 'track_product_published';
/**
* Init tracking.
@@ -37,6 +45,7 @@ class WC_Products_Tracking {
add_action( 'admin_enqueue_scripts', array( $this, 'possibly_add_product_import_scripts' ) );
add_action( 'admin_enqueue_scripts', array( $this, 'possibly_add_attribute_tracking_scripts' ) );
add_action( 'admin_enqueue_scripts', array( $this, 'possibly_add_tag_tracking_scripts' ) );
+ add_action( self::TRACK_PRODUCT_PUBLISHED_CALLBACK, array( $this, 'track_product_published_maybe_defer' ), 10, 3 );
}
/**
@@ -331,7 +340,8 @@ class WC_Products_Tracking {
$product_type_options = self::get_product_type_options( $post_id );
$product_type_options_string = self::get_product_type_options_string( $product_type_options );
- $properties = array(
+ $is_importing = self::is_importing();
+ $properties = array(
'attributes' => count( $product->get_attributes() ),
'categories' => count( $product->get_category_ids() ),
'cross_sells' => ! empty( $product->get_cross_sell_ids() ) ? 'yes' : 'no',
@@ -349,7 +359,7 @@ class WC_Products_Tracking {
'product_type_options' => $product_type_options_string,
'purchase_note' => $product->get_purchase_note() ? 'yes' : 'no',
'sale_price' => $product->get_sale_price() ? 'yes' : 'no',
- 'source' => apply_filters( 'woocommerce_product_source', self::is_importing() ? 'import' : self::TRACKS_SOURCE ),
+ 'source' => apply_filters( 'woocommerce_product_source', $is_importing ? 'import' : self::TRACKS_SOURCE ),
'short_description' => $product->get_short_description() ? 'yes' : 'no',
'tags' => count( $product->get_tag_ids() ),
'upsells' => ! empty( $product->get_upsell_ids() ) ? 'yes' : 'no',
@@ -357,7 +367,31 @@ class WC_Products_Tracking {
'global_unique_id' => $product->get_global_unique_id() ? 'yes' : 'no',
);
- WC_Tracks::record_event( 'product_add_publish', $properties );
+ $this->track_product_published_maybe_defer( 'product_add_publish', $properties, $is_importing );
+ }
+
+ /**
+ * Tracks the event, allowing deferred/asynchronous event recording.
+ *
+ * @internal
+ * @since 10.6.0
+ *
+ * @param string $event_name The name of the event.
+ * @param array $event_properties Custom properties to send with the event.
+ * @param bool $defer Whether to defer the event publishing.
+ * @return void
+ */
+ public function track_product_published_maybe_defer( string $event_name, array $event_properties, bool $defer = false ): void {
+ if ( $defer ) {
+ as_schedule_single_action(
+ time(),
+ self::TRACK_PRODUCT_PUBLISHED_CALLBACK,
+ array( $event_name, $event_properties ),
+ 'woocommerce-tracks'
+ );
+ } else {
+ WC_Tracks::record_event( $event_name, $event_properties );
+ }
}
/**
diff --git a/plugins/woocommerce/tests/php/includes/class-wc-products-tracking-test.php b/plugins/woocommerce/tests/php/includes/class-wc-products-tracking-test.php
index c7ef03bc55..2574b60fb1 100644
--- a/plugins/woocommerce/tests/php/includes/class-wc-products-tracking-test.php
+++ b/plugins/woocommerce/tests/php/includes/class-wc-products-tracking-test.php
@@ -118,4 +118,20 @@ class WC_Products_Tracking_Test extends \WC_Unit_Test_Case {
do_action( 'load-edit.php' );
$this->assertRecordedTracksEvent( 'wcadmin_products_search' );
}
+
+ /**
+ * Test if track_product_published is deferring the even publishing for imports.
+ */
+ public function test_track_product_published_deferred_when_importing(): void {
+ $_POST['action'] = 'woocommerce_do_ajax_product_import';
+ $this->assertFalse( as_has_scheduled_action( WC_Products_Tracking::TRACK_PRODUCT_PUBLISHED_CALLBACK, null, 'woocommerce-tracks' ) );
+
+ $product = new WC_Product_Simple();
+ $product->set_name( 'New name' );
+ $product->set_status( ProductStatus::PUBLISH );
+ $product->save();
+
+ $this->assertTrue( as_has_scheduled_action( WC_Products_Tracking::TRACK_PRODUCT_PUBLISHED_CALLBACK, null, 'woocommerce-tracks' ) );
+ as_unschedule_all_actions( WC_Products_Tracking::TRACK_PRODUCT_PUBLISHED_CALLBACK, null, 'woocommerce-tracks' );
+ }
}