Skip to content

Commit

Permalink
Add missing tracks events to product editor (#38728)
Browse files Browse the repository at this point in the history
* Only record product update on already published products

* Add source into published product tracks event

* Add missing tracks options to product update event

* Track tab clicks in the editor

* Add source to tab clicks

* Record tracks on preview click

* Add events for media gallery, description, and attributes

* Add tracks events to more menu

* Replace new_product_page with source

* Add changelog entry

* Fix lint errors

* Add tracks for About the Editor menu item

* Add onClick event to AboutTheEditor menu item

* Use dropdown option event for classic editor menu click
  • Loading branch information
joshuatf authored and WooCommerce Bot committed Jun 21, 2023
1 parent db31bff commit ba6b850
Show file tree
Hide file tree
Showing 30 changed files with 311 additions and 74 deletions.
4 changes: 4 additions & 0 deletions packages/js/components/changelog/fix-38637
@@ -0,0 +1,4 @@
Significance: minor
Type: add

Add callback for the media uploader component when gallery is opened
10 changes: 9 additions & 1 deletion packages/js/components/src/media-uploader/media-uploader.tsx
Expand Up @@ -34,6 +34,7 @@ type MediaUploaderProps = {
message: string;
file: File;
} ) => void;
onMediaGalleryOpen?: () => void;
onUpload?: ( files: MediaItem[] ) => void;
onFileUploadChange?: ( files: MediaItem[] ) => void;
uploadMedia?: ( options: UploadMediaOptions ) => Promise< void >;
Expand All @@ -49,6 +50,7 @@ export const MediaUploader = ( {
multipleSelect = false,
onError = () => null,
onFileUploadChange = () => null,
onMediaGalleryOpen = () => null,
onUpload = () => null,
onSelect = () => null,
uploadMedia = wpUploadMedia,
Expand Down Expand Up @@ -96,7 +98,13 @@ export const MediaUploader = ( {
allowedTypes={ allowedMediaTypes }
multiple={ multipleSelect }
render={ ( { open } ) => (
<Button variant="secondary" onClick={ open }>
<Button
variant="secondary"
onClick={ () => {
onMediaGalleryOpen();
open();
} }
>
{ buttonText }
</Button>
) }
Expand Down
4 changes: 4 additions & 0 deletions packages/js/product-editor/changelog/fix-38637
@@ -0,0 +1,4 @@
Significance: minor
Type: add

Add missing track events to product editing experience
6 changes: 5 additions & 1 deletion packages/js/product-editor/src/blocks/description/edit.tsx
Expand Up @@ -5,6 +5,7 @@ import { __ } from '@wordpress/i18n';
import { createElement, useState } from '@wordpress/element';
import { parse, serialize } from '@wordpress/blocks';
import { Button } from '@wordpress/components';
import { recordEvent } from '@woocommerce/tracks';
import { useBlockProps } from '@wordpress/block-editor';
import { useEntityProp } from '@wordpress/core-data';

Expand All @@ -31,7 +32,10 @@ export function Edit() {
<div { ...blockProps }>
<Button
variant="secondary"
onClick={ () => setIsModalOpen( true ) }
onClick={ () => {
setIsModalOpen( true );
recordEvent( 'product_add_description_click' );
} }
>
{ description.length
? __( 'Edit description', 'woocommerce' )
Expand Down
3 changes: 3 additions & 0 deletions packages/js/product-editor/src/blocks/images/edit.tsx
Expand Up @@ -87,6 +87,9 @@ export function Edit() {
multipleSelect={ true }
onError={ () => null }
onFileUploadChange={ onFileUpload }
onMediaGalleryOpen={ () => {
recordEvent( 'product_images_media_gallery_open' );
} }
onSelect={ ( files ) => {
const newImages = files.filter(
( img: Image ) =>
Expand Down
Expand Up @@ -16,6 +16,7 @@ import {
Link,
} from '@woocommerce/components';
import { getAdminLink } from '@woocommerce/settings';
import { recordEvent } from '@woocommerce/tracks';

/**
* Internal dependencies
Expand Down Expand Up @@ -182,7 +183,10 @@ export const AttributeControl: React.FC< AttributeControlProps > = ( {
<Button
variant="secondary"
className="woocommerce-add-attribute-list-item__add-button"
onClick={ openNewModal }
onClick={ () => {
openNewModal();
recordEvent( 'product_add_attributes_click' );
} }
>
{ uiStrings.newAttributeListItemLabel }
</Button>
Expand Down
Expand Up @@ -23,6 +23,7 @@ import {
* Internal dependencies
*/
import { EnhancedProductAttribute } from '../../hooks/use-product-attributes';
import { TRACKS_SOURCE } from '../../constants';

type NarrowedQueryAttribute = Pick< QueryProductAttribute, 'id' | 'name' >;

Expand Down Expand Up @@ -112,7 +113,7 @@ export const AttributeInputField: React.FC< AttributeInputFieldProps > = ( {
onSelect={ ( attribute ) => {
if ( isNewAttributeListItem( attribute ) ) {
recordEvent( 'product_attribute_add_custom_attribute', {
new_product_page: true,
source: TRACKS_SOURCE,
} );
}
onChange(
Expand Down
Expand Up @@ -19,6 +19,11 @@ import {
QueryProductAttribute,
} from '@woocommerce/data';

/**
* Internal dependencies
*/
import { TRACKS_SOURCE } from '../../constants';

type CreateAttributeTermModalProps = {
initialAttributeTermName: string;
attributeId: number;
Expand All @@ -41,7 +46,7 @@ export const CreateAttributeTermModal: React.FC<

const onAdd = async ( attribute: Partial< ProductAttributeTerm > ) => {
recordEvent( 'product_attribute_term_add', {
new_product_page: true,
source: TRACKS_SOURCE,
} );
setIsCreating( true );
try {
Expand All @@ -51,14 +56,14 @@ export const CreateAttributeTermModal: React.FC<
attribute_id: attributeId,
} );
recordEvent( 'product_attribute_term_add_success', {
new_product_page: true,
source: TRACKS_SOURCE,
} );
invalidateResolutionForStoreSelector( 'getProductAttributes' );
setIsCreating( false );
onCreated( newAttribute );
} catch ( e ) {
recordEvent( 'product_attribute_term_add_failed', {
new_product_page: true,
source: TRACKS_SOURCE,
} );
createNotice(
'error',
Expand Down
Expand Up @@ -28,6 +28,7 @@ import {
mapFromCategoriesToTreeItems,
mapFromCategoryToTreeItem,
} from './category-field';
import { TRACKS_SOURCE } from '../../constants';

type CreateCategoryModalProps = {
initialCategoryName?: string;
Expand Down Expand Up @@ -61,7 +62,7 @@ export const CreateCategoryModal: React.FC< CreateCategoryModalProps > = ( {

const onSave = async () => {
recordEvent( 'product_category_add', {
new_product_page: true,
source: TRACKS_SOURCE,
} );
setIsCreating( true );
try {
Expand Down
Expand Up @@ -13,6 +13,11 @@ import { cleanForSlug } from '@wordpress/url';
import { Product } from '@woocommerce/data';
import { recordEvent } from '@woocommerce/tracks';

/**
* Internal dependencies
*/
import { TRACKS_SOURCE } from '../../constants';

type EditProductLinkModalProps = {
product: Product;
permalinkPrefix: string;
Expand Down Expand Up @@ -40,7 +45,7 @@ export const EditProductLinkModal: React.FC< EditProductLinkModalProps > = ( {

const onSave = async () => {
recordEvent( 'product_update_slug', {
new_product_page: true,
source: TRACKS_SOURCE,
product_id: product.id,
product_type: product.type,
} );
Expand Down
Expand Up @@ -2,11 +2,11 @@
* External dependencies
*/
import { createElement, Fragment } from '@wordpress/element';
import { recordEvent } from '@woocommerce/tracks';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore No types for this exist yet.
// eslint-disable-next-line @woocommerce/dependency-group
import { MoreMenuDropdown } from '@wordpress/interface';
//import { displayShortcut } from '@wordpress/keycodes';

/**
* Internal dependencies
Expand All @@ -17,6 +17,9 @@ export const MoreMenu = () => {
return (
<>
<MoreMenuDropdown
toggleProps={ {
onClick: () => recordEvent( 'product_dropdown_click' ),
} }
popoverProps={ {
className: 'woocommerce-product-header__more-menu',
} }
Expand Down
@@ -1,18 +1,20 @@
/**
* External dependencies
*/
import { Product } from '@woocommerce/data';
import { getNewPath, navigateTo } from '@woocommerce/navigation';
import { Button } from '@wordpress/components';
import { useDispatch } from '@wordpress/data';
import { createElement } from '@wordpress/element';
import { getNewPath, navigateTo } from '@woocommerce/navigation';
import { Product } from '@woocommerce/data';
import { recordEvent } from '@woocommerce/tracks';
import { useDispatch } from '@wordpress/data';

/**
* Internal dependencies
*/
import { getProductErrorMessage } from '../../../utils/get-product-error-message';
import { usePreview } from '../hooks/use-preview';
import { PreviewButtonProps } from './types';
import { TRACKS_SOURCE } from '../../../constants';

export function PreviewButton( {
productStatus,
Expand All @@ -23,6 +25,9 @@ export function PreviewButton( {
const previewButtonProps = usePreview( {
productStatus,
...props,
onClick() {
recordEvent( 'product_preview_changes', { source: TRACKS_SOURCE } );
},
onSaveSuccess( savedProduct: Product ) {
if ( productStatus === 'auto-draft' ) {
const url = getNewPath( {}, `/product/${ savedProduct.id }` );
Expand Down
Expand Up @@ -31,10 +31,12 @@ export function PublishButton( {
productStatus,
...props,
onPublishSuccess( savedProduct: Product ) {
recordProductEvent( 'product_update', savedProduct );

const isPublished = productStatus === 'publish';

if ( isPublished ) {
recordProductEvent( 'product_update', savedProduct );
}

const noticeContent = isPublished
? __( 'Product updated.', 'woocommerce' )
: __( 'Product added.', 'woocommerce' );
Expand Down
26 changes: 24 additions & 2 deletions packages/js/product-editor/src/components/tabs/tabs.tsx
Expand Up @@ -4,6 +4,10 @@
import { createElement, useEffect, useState } from '@wordpress/element';
import { ReactElement } from 'react';
import { NavigableMenu, Slot } from '@wordpress/components';
import { Product } from '@woocommerce/data';
import { recordEvent } from '@woocommerce/tracks';
import { useSelect } from '@wordpress/data';
import { useEntityProp } from '@wordpress/core-data';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore No types for this exist yet.
// eslint-disable-next-line @woocommerce/dependency-group
Expand All @@ -12,6 +16,7 @@ import { navigateTo, getNewPath, getQuery } from '@woocommerce/navigation';
/**
* Internal dependencies
*/
import { getTabTracksData } from './utils/get-tab-tracks-data';
import { sortFillsByOrder } from '../../utils';
import { TABS_SLOT_NAME } from './constants';

Expand All @@ -26,6 +31,18 @@ export type TabsFillProps = {
export function Tabs( { onChange = () => {} }: TabsProps ) {
const [ selected, setSelected ] = useState< string | null >( null );
const query = getQuery() as Record< string, string >;
const [ productId ] = useEntityProp< number >(
'postType',
'product',
'id'
);
const product: Product = useSelect( ( select ) =>
select( 'core' ).getEditedEntityRecord(
'postType',
'product',
productId
)
);

useEffect( () => {
onChange( selected );
Expand Down Expand Up @@ -69,10 +86,15 @@ export function Tabs( { onChange = () => {} }: TabsProps ) {
<Slot
fillProps={
{
onClick: ( tabId ) =>
onClick: ( tabId ) => {
navigateTo( {
url: getNewPath( { tab: tabId } ),
} ),
} );
recordEvent(
'product_tab_click',
getTabTracksData( tabId, product )
);
},
} as TabsFillProps
}
name={ TABS_SLOT_NAME }
Expand Down
@@ -0,0 +1,33 @@
/**
* External dependencies
*/
import { Product } from '@woocommerce/data';

/**
* Internal dependencies
*/
import { TRACKS_SOURCE } from '../../../constants';

/**
* Get the data for a tab click.
*
* @param {string} tabId Clicked tab.
* @param {Product} product Current product.
* @return {Object} The data for the event.
*/
export function getTabTracksData( tabId: string, product: Product ) {
const data = {
product_tab: tabId,
product_type: product.type,
source: TRACKS_SOURCE,
};

if ( tabId === 'inventory' ) {
return {
...data,
is_store_stock_management_enabled: product.manage_stock,
};
}

return data;
}
2 changes: 2 additions & 0 deletions packages/js/product-editor/src/constants.ts
Expand Up @@ -50,3 +50,5 @@ export const VARIANT_SHIPPING_SECTION_DIMENSIONS_ID = `variant/${ SHIPPING_SECTI
export const PRODUCT_DETAILS_SLUG = 'product-details';

export const PRODUCT_SCHEDULED_SALE_SLUG = 'product-scheduled-sale';

export const TRACKS_SOURCE = 'product-block-editor-v1';
3 changes: 2 additions & 1 deletion packages/js/product-editor/src/hooks/use-product-helper.ts
Expand Up @@ -25,6 +25,7 @@ import { AUTO_DRAFT_NAME, getDerivedProductType } from '../index';
import {
NUMBERS_AND_DECIMAL_SEPARATOR,
ONLY_ONE_DECIMAL_SEPARATOR,
TRACKS_SOURCE,
} from '../constants';
import { ProductVariationsOrder } from './use-variations-order';

Expand All @@ -44,7 +45,7 @@ function getNoticePreviewActions( status: ProductStatus, permalink: string ) {
label: __( 'View in store', 'woocommerce' ),
onClick: () => {
recordEvent( 'product_preview_changes', {
new_product_page: true,
source: TRACKS_SOURCE,
} );
window.open( permalink, '_blank' );
},
Expand Down
1 change: 1 addition & 0 deletions packages/js/product-editor/src/index.ts
Expand Up @@ -3,6 +3,7 @@ export {
DETAILS_SECTION_ID,
NEW_PRODUCT_MANAGEMENT_ENABLED_OPTION_NAME,
TAB_GENERAL_ID,
TRACKS_SOURCE,
} from './constants';

/**
Expand Down

0 comments on commit ba6b850

Please sign in to comment.