From 61d9d0043fe4fe9c0355194e7856619b3d6cb76c Mon Sep 17 00:00:00 2001 From: louwie17 Date: Mon, 30 May 2022 13:14:25 -0300 Subject: [PATCH] Add initial tracking for categories, tags, and attribute product pages (#33118) * Add initial tracking for categories, tracks, and attribute product pages * Update list action tracks that add new items without page refresh * Add changelog * Add extra category tracks * Rename constant for add a new tag button * Remove unneeded props from track --- .../add-term-tracking/index.js | 43 ++++++ .../attributes-tracking/index.js | 56 ++++++++ .../category-tracking/index.js | 41 ++++++ .../wp-admin-scripts/tags-tracking/index.js | 43 ++++++ plugins/woocommerce-admin/webpack.config.js | 4 + .../add-32676_category_and_tag_tracks | 4 + .../events/class-wc-products-tracking.php | 123 +++++++++++++++++- .../legacy/js/admin/term-ordering.js | 11 ++ 8 files changed, 322 insertions(+), 3 deletions(-) create mode 100644 plugins/woocommerce-admin/client/wp-admin-scripts/add-term-tracking/index.js create mode 100644 plugins/woocommerce-admin/client/wp-admin-scripts/attributes-tracking/index.js create mode 100644 plugins/woocommerce-admin/client/wp-admin-scripts/category-tracking/index.js create mode 100644 plugins/woocommerce-admin/client/wp-admin-scripts/tags-tracking/index.js create mode 100644 plugins/woocommerce/changelog/add-32676_category_and_tag_tracks diff --git a/plugins/woocommerce-admin/client/wp-admin-scripts/add-term-tracking/index.js b/plugins/woocommerce-admin/client/wp-admin-scripts/add-term-tracking/index.js new file mode 100644 index 00000000000..2eaaf41fdd4 --- /dev/null +++ b/plugins/woocommerce-admin/client/wp-admin-scripts/add-term-tracking/index.js @@ -0,0 +1,43 @@ +/** + * External dependencies + */ +import { recordEvent } from '@woocommerce/tracks'; + +const addNewTag = document.querySelector( '#addtag #submit' ); + +function actionButtonEventHandler( event ) { + const actionClass = event.target.parentElement.classList[ 0 ]; + + const actions = { + edit: 'edit', + inline: 'quick_edit', + delete: 'delete', + view: 'preview', + }; + + if ( ! actions[ actionClass ] ) { + return; + } + + recordEvent( 'product_attributes_term_list_action_click', { + selected_action: actions[ actionClass ], + } ); +} + +function addActionButtonListeners() { + const actionButtons = document.querySelectorAll( '.row-actions span' ); + actionButtons.forEach( ( button ) => { + button.removeEventListener( 'click', actionButtonEventHandler ); + button.addEventListener( 'click', actionButtonEventHandler ); + } ); +} +addActionButtonListeners(); + +addNewTag?.addEventListener( 'click', function () { + recordEvent( 'product_attributes_add_term', { + page: 'tags', + } ); + setTimeout( () => { + addActionButtonListeners(); + }, 1000 ); +} ); diff --git a/plugins/woocommerce-admin/client/wp-admin-scripts/attributes-tracking/index.js b/plugins/woocommerce-admin/client/wp-admin-scripts/attributes-tracking/index.js new file mode 100644 index 00000000000..d1d7cac0104 --- /dev/null +++ b/plugins/woocommerce-admin/client/wp-admin-scripts/attributes-tracking/index.js @@ -0,0 +1,56 @@ +/** + * External dependencies + */ +import { recordEvent } from '@woocommerce/tracks'; + +const addNewAttribute = document.querySelector( '[name="add_new_attribute"]' ); +const saveAttribute = document.querySelector( '[name="save_attribute"]' ); +const actionButtons = document.querySelectorAll( '.row-actions span a' ); +const configureTerms = document.querySelectorAll( '.configure-terms' ); + +addNewAttribute?.addEventListener( 'click', function () { + const archiveInput = document.querySelector( '#attribute_public' ); + const sortOrder = document.querySelector( '#attribute_orderby' ); + recordEvent( 'product_attributes_add', { + enable_archive: archiveInput?.checked ? 'yes' : 'no', + default_sort_order: sortOrder?.value, + page: 'attributes', + } ); +} ); + +saveAttribute?.addEventListener( 'click', function () { + const archiveInput = document.querySelector( '#attribute_public' ); + const sortOrder = document.querySelector( '#attribute_orderby' ); + recordEvent( 'product_attributes_update', { + enable_archive: archiveInput?.checked ? 'yes' : 'no', + default_sort_order: sortOrder?.value, + page: 'attributes', + } ); +} ); + +actionButtons.forEach( ( button ) => { + button.addEventListener( 'click', function ( event ) { + const actionClass = event.target.parentElement.classList[ 0 ]; + + const actions = { + edit: 'edit', + delete: 'delete', + }; + + if ( ! actions[ actionClass ] ) { + return; + } + + recordEvent( 'product_attributes_' + actions[ actionClass ], { + page: 'attributes', + } ); + } ); +} ); + +configureTerms.forEach( ( button ) => { + button.addEventListener( 'click', function () { + recordEvent( 'product_attributes_configure_terms', { + page: 'attributes', + } ); + } ); +} ); diff --git a/plugins/woocommerce-admin/client/wp-admin-scripts/category-tracking/index.js b/plugins/woocommerce-admin/client/wp-admin-scripts/category-tracking/index.js new file mode 100644 index 00000000000..5377b3e9271 --- /dev/null +++ b/plugins/woocommerce-admin/client/wp-admin-scripts/category-tracking/index.js @@ -0,0 +1,41 @@ +/** + * External dependencies + */ +import { recordEvent } from '@woocommerce/tracks'; + +const addNewCategory = document.querySelector( '#addtag #submit' ); + +function actionButtonEventHandler( event ) { + const actionClass = event.target.parentElement.classList[ 0 ]; + + const actions = { + edit: 'edit', + inline: 'quick_edit', + delete: 'delete', + view: 'preview', + make_default: 'make_default', + }; + + if ( ! actions[ actionClass ] ) { + return; + } + + recordEvent( 'product_category_manage', { + option_selected: actions[ actionClass ], + } ); +} + +function addActionButtonListeners() { + const actionButtons = document.querySelectorAll( '.row-actions span' ); + actionButtons.forEach( ( button ) => { + button.removeEventListener( 'click', actionButtonEventHandler ); + button.addEventListener( 'click', actionButtonEventHandler ); + } ); +} +addActionButtonListeners(); + +addNewCategory?.addEventListener( 'click', function () { + setTimeout( () => { + addActionButtonListeners(); + }, 1000 ); +} ); diff --git a/plugins/woocommerce-admin/client/wp-admin-scripts/tags-tracking/index.js b/plugins/woocommerce-admin/client/wp-admin-scripts/tags-tracking/index.js new file mode 100644 index 00000000000..258e6f2c9ac --- /dev/null +++ b/plugins/woocommerce-admin/client/wp-admin-scripts/tags-tracking/index.js @@ -0,0 +1,43 @@ +/** + * External dependencies + */ +import { recordEvent } from '@woocommerce/tracks'; + +const addNewTag = document.querySelector( '#addtag #submit' ); + +function actionButtonEventHandler( event ) { + const actionClass = event.target.parentElement.classList[ 0 ]; + + const actions = { + edit: 'edit', + inline: 'quick_edit', + delete: 'delete', + view: 'preview', + }; + + if ( ! actions[ actionClass ] ) { + return; + } + + recordEvent( 'product_tags_list_action_click', { + selected_action: actions[ actionClass ], + } ); +} + +function addActionButtonListeners() { + const actionButtons = document.querySelectorAll( '.row-actions span' ); + actionButtons.forEach( ( button ) => { + button.removeEventListener( 'click', actionButtonEventHandler ); + button.addEventListener( 'click', actionButtonEventHandler ); + } ); +} +addActionButtonListeners(); + +addNewTag?.addEventListener( 'click', function () { + recordEvent( 'product_tags_add', { + page: 'attributes', + } ); + setTimeout( () => { + addActionButtonListeners(); + }, 1000 ); +} ); diff --git a/plugins/woocommerce-admin/webpack.config.js b/plugins/woocommerce-admin/webpack.config.js index df48d892a65..15c27e3141b 100644 --- a/plugins/woocommerce-admin/webpack.config.js +++ b/plugins/woocommerce-admin/webpack.config.js @@ -50,6 +50,10 @@ const wpAdminScripts = [ 'payment-method-promotions', 'onboarding-load-sample-products-notice', 'product-tracking', + 'add-term-tracking', + 'attributes-tracking', + 'category-tracking', + 'tags-tracking', ]; const getEntryPoints = () => { const entryPoints = { diff --git a/plugins/woocommerce/changelog/add-32676_category_and_tag_tracks b/plugins/woocommerce/changelog/add-32676_category_and_tag_tracks new file mode 100644 index 00000000000..800debfd962 --- /dev/null +++ b/plugins/woocommerce/changelog/add-32676_category_and_tag_tracks @@ -0,0 +1,4 @@ +Significance: minor +Type: add + +Add wpAdmin scripts for tracking actions in the category, tags, and attribute pages. #33118 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 9c19dcfebac..4f7d398d96c 100644 --- a/plugins/woocommerce/includes/tracks/events/class-wc-products-tracking.php +++ b/plugins/woocommerce/includes/tracks/events/class-wc-products-tracking.php @@ -23,8 +23,11 @@ class WC_Products_Tracking { add_action( 'edit_post', array( $this, 'track_product_updated' ), 10, 2 ); add_action( 'wp_after_insert_post', array( $this, 'track_product_published' ), 10, 4 ); add_action( 'created_product_cat', array( $this, 'track_product_category_created' ) ); + add_action( 'edited_product_cat', array( $this, 'track_product_category_updated' ) ); add_action( 'add_meta_boxes_product', array( $this, 'track_product_updated_client_side' ), 10 ); - add_action( 'admin_enqueue_scripts', array( $this, 'possibly_add_tracking_scripts' ) ); + add_action( 'admin_enqueue_scripts', array( $this, 'possibly_add_product_tracking_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' ) ); } /** @@ -230,7 +233,27 @@ class WC_Products_Tracking { } /** - * Get the product screen name if current hook and page is a products type page. + * Send a Tracks event when a product category is updated. + * + * @param int $category_id Category ID. + */ + public function track_product_category_updated( $category_id ) { + // phpcs:disable WordPress.Security.NonceVerification.Missing + // Only track category creation from the edit product screen or the + // category management screen (which both occur via AJAX). + if ( + empty( $_POST['action'] ) || + ( 'editedtag' !== $_POST['action'] && 'inline-save-tax' !== $_POST['action'] ) + ) { + return; + } + // phpcs:enable + + WC_Tracks::record_event( 'product_category_update' ); + } + + /** + * Adds the tracking scripts for product filtering actions. * * @param string $hook Hook of the current page. * @return string|boolean @@ -269,7 +292,7 @@ class WC_Products_Tracking { * * @param string $hook Page hook. */ - public function possibly_add_tracking_scripts( $hook ) { + public function possibly_add_product_tracking_scripts( $hook ) { $product_screen = $this->get_product_screen( $hook ); if ( ! $product_screen ) { return; @@ -294,4 +317,98 @@ class WC_Products_Tracking { ) ); } + + /** + * Adds the tracking scripts for product attributes filtering actions. + * + * @param string $hook Page hook. + */ + public function possibly_add_attribute_tracking_scripts( $hook ) { + // phpcs:disable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification + if ( + 'product_page_product_attributes' !== $hook || + ! isset( $_GET['page'] ) || + 'product_attributes' !== wp_unslash( $_GET['page'] ) + ) { + return; + } + // phpcs:enable + + $script_assets_filename = WCAdminAssets::get_script_asset_filename( 'wp-admin-scripts', 'attributes-tracking' ); + $script_assets = require WC_ADMIN_ABSPATH . WC_ADMIN_DIST_JS_FOLDER . 'wp-admin-scripts/' . $script_assets_filename; + + wp_enqueue_script( + 'wc-admin-attributes-tracking', + WCAdminAssets::get_url( 'wp-admin-scripts/attributes-tracking', 'js' ), + array_merge( array( WC_ADMIN_APP ), $script_assets ['dependencies'] ), + WCAdminAssets::get_file_version( 'js' ), + true + ); + } + + /** + * Adds the tracking scripts for tags and categories filtering actions. + * + * @param string $hook Page hook. + */ + public function possibly_add_tag_tracking_scripts( $hook ) { + // phpcs:disable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification + if ( + 'edit-tags.php' !== $hook || + ! isset( $_GET['post_type'] ) || + 'product' !== wp_unslash( $_GET['post_type'] ) + ) { + return; + } + // phpcs:enable + + // phpcs:disable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized + if ( + isset( $_GET['taxonomy'] ) && + 'product_tag' === wp_unslash( $_GET['taxonomy'] ) + ) { + // phpcs:enable + $tags_script_assets_filename = WCAdminAssets::get_script_asset_filename( 'wp-admin-scripts', 'tags-tracking' ); + $tags_script_assets = require WC_ADMIN_ABSPATH . WC_ADMIN_DIST_JS_FOLDER . 'wp-admin-scripts/' . $tags_script_assets_filename; + + wp_enqueue_script( + 'wc-admin-tags-tracking', + WCAdminAssets::get_url( 'wp-admin-scripts/tags-tracking', 'js' ), + array_merge( array( WC_ADMIN_APP ), $tags_script_assets ['dependencies'] ), + WCAdminAssets::get_file_version( 'js' ), + true + ); + return; + } + + // phpcs:disable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized + if ( + isset( $_GET['taxonomy'] ) && + 'product_cat' === wp_unslash( $_GET['taxonomy'] ) + ) { + // phpcs:enable + $category_script_assets_filename = WCAdminAssets::get_script_asset_filename( 'wp-admin-scripts', 'category-tracking' ); + $category_script_assets = require WC_ADMIN_ABSPATH . WC_ADMIN_DIST_JS_FOLDER . 'wp-admin-scripts/' . $category_script_assets_filename; + + wp_enqueue_script( + 'wc-admin-category-tracking', + WCAdminAssets::get_url( 'wp-admin-scripts/category-tracking', 'js' ), + array_merge( array( WC_ADMIN_APP ), $category_script_assets ['dependencies'] ), + WCAdminAssets::get_file_version( 'js' ), + true + ); + return; + } + + $script_assets_filename = WCAdminAssets::get_script_asset_filename( 'wp-admin-scripts', 'add-term-tracking' ); + $script_assets = require WC_ADMIN_ABSPATH . WC_ADMIN_DIST_JS_FOLDER . 'wp-admin-scripts/' . $script_assets_filename; + + wp_enqueue_script( + 'wc-admin-add-term-tracking', + WCAdminAssets::get_url( 'wp-admin-scripts/add-term-tracking', 'js' ), + array_merge( array( WC_ADMIN_APP ), $script_assets ['dependencies'] ), + WCAdminAssets::get_file_version( 'js' ), + true + ); + } } diff --git a/plugins/woocommerce/legacy/js/admin/term-ordering.js b/plugins/woocommerce/legacy/js/admin/term-ordering.js index 1a1a99d8d97..50d9459427b 100644 --- a/plugins/woocommerce/legacy/js/admin/term-ordering.js +++ b/plugins/woocommerce/legacy/js/admin/term-ordering.js @@ -14,6 +14,10 @@ jQuery( function( $ ) { term_id_selector = '.check-column input'; } + // Stand-in wcTracks.recordEvent in case tracks is not available (for any reason). + window.wcTracks = window.wcTracks || {}; + window.wcTracks.recordEvent = window.wcTracks.recordEvent || function() { }; + $( table_selector ).find( '.column-handle' ).show(); $.wc_add_missing_sort_handles = function() { @@ -97,6 +101,13 @@ jQuery( function( $ ) { return; } + window.wcTracks.recordEvent( 'product_attributes_ordering_term', { + is_category: + woocommerce_term_ordering_params.taxonomy === 'product_cat' + ? 'yes' + : 'no', + } ); + // Show Spinner ui.item.find( '.check-column input' ).hide(); ui.item