From 8bc85fd5dafbcbcafef547ee0aa088f500369739 Mon Sep 17 00:00:00 2001 From: arunshenoy99 Date: Fri, 19 May 2023 17:14:28 +0530 Subject: [PATCH 01/13] implement analytics --- includes/Data/Events.php | 69 ++++-- includes/RestApi/EventsController.php | 201 +++++++++++------- includes/Services/EventService.php | 83 ++++++++ src/OnboardingSPA/components/App/index.js | 48 +++++ .../Drawer/DrawerPanel/DesignColors.js | 7 +- .../Drawer/DrawerPanel/DesignHeaderMenu.js | 52 +++-- .../DrawerPanel/DesignThemeStylesPreview.js | 7 +- .../Drawer/DrawerPanel/DesignTypography.js | 8 +- .../components/ExitToWordPress/index.js | 4 + src/OnboardingSPA/components/Layouts/Base.js | 40 ++-- .../Sidebar/components/LearnMore/Menu.js | 11 +- .../Sidebar/components/LearnMore/Sidebar.js | 2 + .../components/SkipButton/index.js | 21 +- .../StateHandlers/Ecommerce/index.js | 15 +- .../pages/Steps/DesignHomepageMenu/index.js | 7 +- .../Steps/DesignThemeStyles/Menu/index.js | 10 +- .../Steps/DesignThemeStyles/Preview/index.js | 2 + .../pages/Steps/Ecommerce/StepTax/index.js | 3 + .../GetStarted/GetStartedExperience/index.js | 7 + .../SiteTypeSetup/PrimarySite/index.js | 17 +- .../SiteTypeSetup/SecondarySite/index.js | 43 +++- .../pages/Steps/TopPriority/index.js | 11 +- src/OnboardingSPA/utils/analytics/index.js | 11 + src/OnboardingSPA/utils/api/events.js | 25 --- src/constants.js | 1 + src/onboarding.js | 8 + 26 files changed, 506 insertions(+), 207 deletions(-) create mode 100644 includes/Services/EventService.php create mode 100644 src/OnboardingSPA/utils/analytics/index.js delete mode 100644 src/OnboardingSPA/utils/api/events.js diff --git a/includes/Data/Events.php b/includes/Data/Events.php index e9e92c6af..a8796031d 100644 --- a/includes/Data/Events.php +++ b/includes/Data/Events.php @@ -1,21 +1,66 @@ true, + 'sidebar-opened' => true, + 'sidebar-closed' => true, + 'wp-experience' => true, + 'primary-type' => true, + 'secondary-type' => true, + 'tax-information' => true, + 'selected-style' => true, + 'default-style' => true, + 'customize-design' => true, + 'font-selection' => true, + 'theme-header' => true, + 'homepage-layout' => true, + 'top-priority' => true, + 'top-priority-skipped' => true, + 'exit-to-wordpress' => true, + 'products-info' => true, + 'yith-wonder/company-page-layout' => true, + 'yith-wonder/contact-us-layout' => true, + 'yith-wonder/blog-page-layout' => true, + 'yith-wonder/testimonials-page-layout' => true, + 'site-features' => true, + 'color-selection' => true, + 'color-selection-reset' => true, + ); - // Contains a list of events with the key being the event slug. - protected static $events = array( - 'nfd-module-onboarding-event-pageview' => array( - 'category' => 'Admin', - 'action' => 'pageview', - ), - ); + /** + * Returns the list of valid actions that an event can perform + * + * @return array + */ + public static function get_valid_actions() { + return self::$valid_actions; + } - public static function get_event( $event_slug ) { - return self::$events[ $event_slug ] ? self::$events[ $event_slug ] : false; - } + /** + * Valid category of on event. + * + * @return string + */ + public static function get_category() { + return self::$category; + } } diff --git a/includes/RestApi/EventsController.php b/includes/RestApi/EventsController.php index f55537bbd..c5cffb52b 100644 --- a/includes/RestApi/EventsController.php +++ b/includes/RestApi/EventsController.php @@ -3,96 +3,139 @@ use NewfoldLabs\WP\Module\Onboarding\Data\Events; use NewfoldLabs\WP\Module\Onboarding\Permissions; +use NewfoldLabs\WP\Module\Onboarding\Services\EventService; /** - * [Class EventsController] + * Controller to send analytics events. */ class EventsController extends \WP_REST_Controller { - /** - * @var string - */ - protected $namespace = 'newfold-onboarding/v1'; + /** + * The namespace of the controller. + * + * @var string + */ + protected $namespace = 'newfold-onboarding/v1'; - /** - * @var string - */ - protected $rest_base = '/events'; + /** + * The REST base endpoint. + * + * @var string + */ + protected $rest_base = '/events'; - /** - * Register REST routes for EventsController class. - * - * @return void - */ - public function register_routes() { - \register_rest_route( - $this->namespace, - $this->rest_base, - array( - array( - 'methods' => \WP_REST_Server::CREATABLE, - 'callback' => array( $this, 'send_event' ), - 'permission_callback' => array( Permissions::class, 'rest_is_authorized_admin' ), - 'args' => $this->get_send_event_args(), - ), - ) - ); - } + /** + * Register routes that the controller will expose. + * + * @return void + */ + public function register_routes() { + \register_rest_route( + $this->namespace, + $this->rest_base, + array( + array( + 'methods' => \WP_REST_Server::CREATABLE, + 'callback' => array( $this, 'send' ), + 'permission_callback' => array( Permissions::class, 'rest_is_authorized_admin' ), + 'args' => $this->get_send_args(), + ), + ) + ); - /** - * Get args for the send_event endpoint. - * - * @return array - */ - public function get_send_event_args() { - return array( - 'slug' => array( - 'required' => true, - 'type' => 'string', - 'sanitize_callback' => 'sanitize_text_field', - ), - 'data' => array( - 'type' => 'object', - ), - ); - } + \register_rest_route( + $this->namespace, + $this->rest_base . '/batch', + array( + array( + 'methods' => \WP_REST_Server::CREATABLE, + 'callback' => array( $this, 'send_batch' ), + 'permission_callback' => array( Permissions::class, 'rest_is_authorized_admin' ), + ), + ) + ); + } - /** - * Send events to the data module events API. - * - * @param \WP_REST_Request $request - * - * @return \WP_REST_Response|\WP_Error - */ - public function send_event( \WP_REST_Request $request ) { - $event = Events::get_event( $request->get_param( 'slug' ) ); - if ( ! $event ) { - return new \WP_Error( - 'event-error', - 'No such event found', - array( 'status' => 404 ) - ); - } + /** + * Args for a single event. + * + * @return array + */ + public function get_send_args() { + return array( + 'action' => array( + 'required' => true, + 'description' => __( 'Event action', 'wp-module-onboarding' ), + 'type' => 'string', + 'sanitize_callback' => 'sanitize_title', + 'validate_callback' => array( EventService::class, 'validate_action' ), + ), + 'category' => array( + 'default' => Events::get_category(), + 'description' => __( 'Event category', 'wp-module-onboarding' ), + 'type' => 'string', + 'sanitize_callback' => 'sanitize_title', + 'validate_callback' => array( EventService::class, 'validate_category' ), + ), + 'data' => array( + 'description' => __( 'Event data', 'wp-module-onboarding' ), + 'type' => 'object', + ), + ); + } - $event['data'] = $request->get_param( 'data' ); + /** + * Sends a Hiive Event to the data module API. + * + * @param \WP_REST_Request $request The incoming request object. + * @return \WP_REST_Response|\WP_Error + */ + public function send( \WP_REST_Request $request ) { + return EventService::send( $request->get_params() ); + } - if ( ! empty( $event['data'] ) && ! empty( $event['data']['stepID'] ) ) { - $event['data']['page'] = \admin_url( '/index.php?page=nfd-onboarding#' . $event['data']['stepID'] ); - } + /** + * Sends an array of Hiive Events to the data module API programmatically. + * + * @param \WP_REST_Request $request The incoming request object. + * @return \WP_REST_Response|\WP_Error + */ + public function send_batch( \WP_REST_Request $request ) { + $events = $request->get_json_params(); + if ( ! rest_is_array( $events ) ) { + return new \WP_Error( + 'nfd_module_onboarding_error', + __( 'Request does not contain an array of events.', 'wp-module-onboarding' ) + ); + } - $event_data_request = new \WP_REST_Request( - \WP_REST_Server::CREATABLE, - NFD_MODULE_DATA_EVENTS_API - ); - $event_data_request->set_body_params( $event ); - $response = \rest_do_request( $event_data_request ); - if ( $response->is_error() ) { - return $response->as_error(); - } + $response_errors = array(); + foreach ( $events as $index => $event ) { + $response = EventService::send( $event ); + if ( is_wp_error( $response ) ) { + array_push( + $response_errors, + array( + 'index' => $index, + 'data' => $response, + ) + ); + } + } - return new \WP_REST_Response( - $response, - $response->status - ); - } + if ( ! empty( $response_errors ) ) { + return new \WP_Error( + 'nfd_module_onboarding_error', + __( 'Some events failed.', 'wp-module-onboarding' ), + array( + 'data' => $response_errors, + ) + ); + } + + return new \WP_REST_Response( + array(), + 202 + ); + } } diff --git a/includes/Services/EventService.php b/includes/Services/EventService.php new file mode 100644 index 000000000..a2af41dc6 --- /dev/null +++ b/includes/Services/EventService.php @@ -0,0 +1,83 @@ +set_body_params( $event ); + + $response = rest_do_request( $event_data_request ); + if ( $response->is_error() ) { + return $response->as_error(); + } + + return $response; + } + + /** + * Validates the category of an event. + * + * @param string $category The category of an event. + * @return boolean + */ + public static function validate_category( $category ) { + return Events::get_category() === $category; + } + + /** + * Validates the action performed in an event. + * + * @param string $action The action performed in an event. + * @return boolean + */ + public static function validate_action( $action ) { + $valid_actions = Events::get_valid_actions(); + if ( ! isset( $valid_actions[ $action ] ) ) { + return false; + } + + return true; + } + + /** + * Sanitizes and validates the action and category parameters of an event. + * + * @param array $event The event to sanitize and validate. + * @return array|boolean + */ + public static function validate( $event ) { + if ( ! isset( $event['action'] ) || ! self::validate_action( $event['action'] ) ) { + return false; + } + + if ( ! isset( $event['category'] ) || ! self::validate_category( $event['category'] ) ) { + $event['category'] = Events::get_category(); + } + + return $event; + } +} diff --git a/src/OnboardingSPA/components/App/index.js b/src/OnboardingSPA/components/App/index.js index 73faaa137..9e4cc586b 100644 --- a/src/OnboardingSPA/components/App/index.js +++ b/src/OnboardingSPA/components/App/index.js @@ -19,6 +19,8 @@ import { useEffect, Fragment, useState } from '@wordpress/element'; import { FullscreenMode } from '@wordpress/interface'; import { API_REQUEST } from '../../../constants'; import NewfoldInterfaceSkeleton from '../NewfoldInterfaceSkeleton'; +import { HiiveAnalytics } from '@newfold-labs/ui-analytics'; +import { trackHiiveEvent } from '../../utils/analytics'; /** * Primary app that renders the . @@ -139,6 +141,7 @@ const App = () => { setIsRequestPlaced( false ); } } + // Check if the Basic Info page was visited if ( location?.pathname.includes( 'basic-info' ) ) { setDidVisitBasicInfo( true ); @@ -223,12 +226,57 @@ const App = () => { } } + const handlePreviousStepTracking = () => { + const previousStep = window.nfdOnboarding?.previousStepID; + if ( typeof previousStep !== 'string' ) { + window.nfdOnboarding.previousStepID = location.pathname; + HiiveAnalytics.dispatchEvents(); + return; + } + + if ( previousStep.includes( 'products' ) ) { + trackHiiveEvent( 'products-info', { + productCount: + currentData.storeDetails.productInfo.product_count, + productTypes: + currentData.storeDetails.productInfo.product_types.join( + ',' + ), + } ); + } + + if ( previousStep.includes( 'site-pages' ) ) { + currentData.data.sitePages?.other?.forEach( ( sitePage ) => { + trackHiiveEvent( `${ sitePage.slug }-layout`, sitePage.slug ); + } ); + } + + if ( previousStep.includes( 'site-features' ) ) { + const siteFeatures = currentData.data?.siteFeatures; + if ( siteFeatures ) { + const siteFeaturesArray = Object.keys( siteFeatures ).filter( + ( key ) => { + return siteFeatures[ key ] !== false; + } + ); + trackHiiveEvent( + 'site-features', + siteFeaturesArray.join( ',' ) + ); + } + } + + window.nfdOnboarding.previousStepID = location.pathname; + HiiveAnalytics.dispatchEvents(); + }; + useEffect( () => { document.body.classList.add( `nfd-brand-${ newfoldBrand }` ); }, [ newfoldBrand ] ); useEffect( () => { syncStoreToDB(); + handlePreviousStepTracking(); handleColorsAndTypographyRoutes(); if ( location.pathname.includes( '/step' ) ) { setActiveFlow( onboardingFlow ); diff --git a/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignColors.js b/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignColors.js index d42e6e8ea..4b0de8bfd 100644 --- a/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignColors.js +++ b/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignColors.js @@ -6,9 +6,9 @@ import { useState, useEffect, useRef } from '@wordpress/element'; import { store as nfdOnboardingStore } from '../../../store'; import { getGlobalStyles, getThemeColors } from '../../../utils/api/themes'; import { useGlobalStylesOutput } from '../../../utils/global-styles/use-global-styles-output'; -import { GlobalStylesProvider } from '../../LivePreview'; import { THEME_STATUS_ACTIVE, THEME_STATUS_INIT } from '../../../../constants'; import Animate from '../../Animate'; +import { trackHiiveEvent } from '../../../utils/analytics'; const DesignColors = () => { const customColorsResetRef = useRef( null ); @@ -248,6 +248,7 @@ const DesignColors = () => { saveThemeColorPalette( colorStyle ); setSelectedColorsLocal( colorPalettes[ colorStyle ] ); LocalToState( colorPalettes[ colorStyle ], colorStyle ); + trackHiiveEvent( 'color-selection', colorStyle ); }; const changeCustomPickerColor = async ( color ) => { @@ -266,6 +267,9 @@ const DesignColors = () => { saveCustomColors(); LocalToState( selectedColorsLocalCopy, 'custom' ); setSelectedColorsLocal( selectedColorsLocalCopy ); + if ( ! isCustomColorActive() ) { + trackHiiveEvent( 'color-selection', 'custom' ); + } setCustomColors( selectedColorsLocalCopy ); }; @@ -299,6 +303,7 @@ const DesignColors = () => { setSelectedColors( selectedColors ); setCurrentOnboardingData( currentData ); + trackHiiveEvent( 'color-selection-reset', selectedGlobalStyle.title ); } function buildPalettes() { diff --git a/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignHeaderMenu.js b/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignHeaderMenu.js index 821655848..16372beff 100644 --- a/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignHeaderMenu.js +++ b/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignHeaderMenu.js @@ -3,13 +3,14 @@ import { useState, useEffect } from '@wordpress/element'; import { useLocation } from 'react-router-dom'; import { store as nfdOnboardingStore } from '../../../store'; import { getPatterns } from '../../../utils/api/patterns'; -import { LivePreviewSkeleton, LivePreviewSelectableCard } from '../../../components/LivePreview'; +import { + LivePreviewSkeleton, + LivePreviewSelectableCard, +} from '../../../components/LivePreview'; import { setFlow } from '../../../utils/api/flow'; -import { - THEME_STATUS_ACTIVE, - THEME_STATUS_INIT, -} from '../../../../constants'; +import { THEME_STATUS_ACTIVE, THEME_STATUS_INIT } from '../../../../constants'; +import { trackHiiveEvent } from '../../../utils/analytics'; const DesignHeaderMenu = () => { const headerMenuSlugs = [ @@ -28,19 +29,22 @@ const DesignHeaderMenu = () => { const [ selectedPattern, setSelectedPattern ] = useState( '' ); const location = useLocation(); - const { currentStep, currentData, themeStatus, storedPreviewSettings } = useSelect( ( select ) => { - return { - currentStep: select( nfdOnboardingStore ).getStepFromPath( - location.pathname - ), - currentData: - select( nfdOnboardingStore ).getCurrentOnboardingData(), - themeStatus: select( nfdOnboardingStore ).getThemeStatus(), - storedPreviewSettings: select( nfdOnboardingStore ).getStepPreviewData(), - }; - }, [] ); - - const { setCurrentOnboardingData, updateThemeStatus, setHeaderMenuData } = useDispatch( nfdOnboardingStore ); + const { currentStep, currentData, themeStatus, storedPreviewSettings } = + useSelect( ( select ) => { + return { + currentStep: select( nfdOnboardingStore ).getStepFromPath( + location.pathname + ), + currentData: + select( nfdOnboardingStore ).getCurrentOnboardingData(), + themeStatus: select( nfdOnboardingStore ).getThemeStatus(), + storedPreviewSettings: + select( nfdOnboardingStore ).getStepPreviewData(), + }; + }, [] ); + + const { setCurrentOnboardingData, updateThemeStatus, setHeaderMenuData } = + useDispatch( nfdOnboardingStore ); const getPatternsData = async () => { const headerMenuPreviewResponse = await getPatterns( @@ -89,7 +93,8 @@ const DesignHeaderMenu = () => { const handleClick = async ( idx ) => { if ( document.getElementsByClassName( 'nfd-onboard-content' ) ) { - document.getElementsByClassName( 'nfd-onboard-content' )[ 0 ] + document + .getElementsByClassName( 'nfd-onboard-content' )[ 0 ] .scrollIntoView( { behavior: 'smooth', } ); @@ -113,6 +118,7 @@ const DesignHeaderMenu = () => { if ( result?.error === null ) { setCurrentOnboardingData( currentData ); } + trackHiiveEvent( 'theme-header', chosenPattern.slug ); }; const buildPreviews = () => { @@ -120,7 +126,9 @@ const DesignHeaderMenu = () => { return ( { return ( { const [ pattern, setPattern ] = useState(); @@ -97,6 +95,7 @@ const DesignThemeStylesPreview = () => { setSelectedStyle( selectedGlobalStyle.title ); currentData.data.theme.variation = selectedGlobalStyle.title; setCurrentOnboardingData( currentData ); + trackHiiveEvent( 'selected-style', selectedGlobalStyle.title ); }; const buildPreviews = () => { diff --git a/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignTypography.js b/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignTypography.js index 8f5813473..66f5ed159 100644 --- a/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignTypography.js +++ b/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignTypography.js @@ -6,6 +6,7 @@ import { store as nfdOnboardingStore } from '../../../store'; import { getThemeFonts } from '../../../utils/api/themes'; import { useGlobalStylesOutput } from '../../../utils/global-styles/use-global-styles-output'; import { THEME_STATUS_ACTIVE, THEME_STATUS_INIT } from '../../../../constants'; +import { trackHiiveEvent } from '../../../utils/analytics'; const DesignTypography = () => { const drawerFontOptions = useRef(); @@ -57,7 +58,7 @@ const DesignTypography = () => { fontPalettes !== undefined ) { setSelectedFont( currentData?.data?.typography?.slug ); - handleClick( currentData?.data?.typography?.slug ); + handleClick( currentData?.data?.typography?.slug, 'flow' ); } }, [ fontPalettes, storedPreviewSettings ] ); @@ -66,7 +67,7 @@ const DesignTypography = () => { getFontStylesAndPatterns(); }, [ isLoaded, themeStatus ] ); - const handleClick = async ( fontStyle ) => { + const handleClick = async ( fontStyle, context = 'click' ) => { setSelectedFont( fontStyle ); // Changes the Global Styles to Recompute css properties @@ -121,6 +122,9 @@ const DesignTypography = () => { useGlobalStylesOutput( globalStylesCopy, storedPreviewSettings ) ); setCurrentOnboardingData( currentData ); + if ( 'click' === context ) { + trackHiiveEvent( 'font-selection', fontStyle ); + } }; function buildPalettes() { diff --git a/src/OnboardingSPA/components/ExitToWordPress/index.js b/src/OnboardingSPA/components/ExitToWordPress/index.js index 26525314e..e25f33d26 100644 --- a/src/OnboardingSPA/components/ExitToWordPress/index.js +++ b/src/OnboardingSPA/components/ExitToWordPress/index.js @@ -10,6 +10,8 @@ import { setFlow } from '../../utils/api/flow'; import { store as nfdOnboardingStore } from '../../store'; import { getSettings, setSettings } from '../../utils/api/settings'; import { wpAdminPage, pluginDashboardPage } from '../../../constants'; +import { HiiveAnalytics } from '@newfold-labs/ui-analytics'; +import { trackHiiveEvent } from '../../utils/analytics'; /** * Self-contained button and confirmation modal for exiting Onboarding page. @@ -91,6 +93,8 @@ const ExitToWordPress = ( { } setFlow( currentData ); } + trackHiiveEvent( 'exit-to-wordpress', window.location.href ); + await HiiveAnalytics.dispatchEvents(); //Redirect to Admin Page for normal customers // and Bluehost Dashboard for ecommerce customers const exitLink = exitToWordpressForEcommerce() diff --git a/src/OnboardingSPA/components/Layouts/Base.js b/src/OnboardingSPA/components/Layouts/Base.js index b3062c33d..75a359295 100644 --- a/src/OnboardingSPA/components/Layouts/Base.js +++ b/src/OnboardingSPA/components/Layouts/Base.js @@ -3,43 +3,29 @@ import { speak } from '@wordpress/a11y'; import { useEffect } from '@wordpress/element'; import { useLocation } from 'react-router-dom'; -import { NFD_ONBOARDING_EVENT_PREFIX } from '../../../constants'; -import Event from '../../utils/api/events'; +import { trackHiiveEvent } from '../../utils/analytics'; -/** - * The Base Layout has no prescribed styles, only shared functionality like focus-management and analytics. - * - * @param {object} props - * @returns - */ -const BaseLayout = ({ +const BaseLayout = ( { className = 'nfd-onboarding-layout__base', children, -}) => { +} ) => { const location = useLocation(); - const mainContainer = document.querySelector('.nfd-onboard-content'); + const mainContainer = document.querySelector( '.nfd-onboard-content' ); - const speakRouteTitle = ( - location, - title = 'Showing new Onboarding Page' - ) => { + const speakRouteTitle = ( title = 'Showing new Onboarding Page' ) => { // [TODO]: Determine if some routes should not speak the title - speak(title, 'assertive'); + speak( title, 'assertive' ); }; - useEffect(() => { - mainContainer?.focus({ preventScroll: true }); - speakRouteTitle(location, 'Override'); - new Event(`${NFD_ONBOARDING_EVENT_PREFIX}-pageview`, { - stepID: location.pathname, - previousStepID: window.nfdOnboarding.previousStepID - }).send(); - window.nfdOnboarding.previousStepID = location.pathname - }, [location.pathname]); + useEffect( () => { + mainContainer?.focus( { preventScroll: true } ); + speakRouteTitle( 'Override' ); + trackHiiveEvent( 'pageview', window.location.href ); + }, [ location.pathname ] ); return ( -
- {children} +
+ { children }
); }; diff --git a/src/OnboardingSPA/components/Sidebar/components/LearnMore/Menu.js b/src/OnboardingSPA/components/Sidebar/components/LearnMore/Menu.js index f95b9b86f..1cb06bf7f 100644 --- a/src/OnboardingSPA/components/Sidebar/components/LearnMore/Menu.js +++ b/src/OnboardingSPA/components/Sidebar/components/LearnMore/Menu.js @@ -8,6 +8,7 @@ import { SIDEBAR_MENU_SLOTFILL_PREFIX, } from '../../../../../constants'; import classNames from 'classnames'; +import { trackHiiveEvent } from '../../../../utils/analytics'; const LearnMoreMenu = () => { const { isSidebarOpened, sideBarView, currentStep } = useSelect( @@ -23,12 +24,16 @@ const LearnMoreMenu = () => { const { setIsSidebarOpened, setSidebarActiveView } = useDispatch( nfdOnboardingStore ); const toggleSidebar = () => { - setSidebarActiveView( SIDEBAR_LEARN_MORE ); - setIsSidebarOpened( + const isSidebarOpenedNew = sideBarView === SIDEBAR_LEARN_MORE ? ! isSidebarOpened - : isSidebarOpened + : isSidebarOpened; + trackHiiveEvent( + isSidebarOpenedNew ? 'sidebar-opened' : 'sidebar-closed', + window.location.href ); + setSidebarActiveView( SIDEBAR_LEARN_MORE ); + setIsSidebarOpened( isSidebarOpenedNew ); }; return ( diff --git a/src/OnboardingSPA/components/Sidebar/components/LearnMore/Sidebar.js b/src/OnboardingSPA/components/Sidebar/components/LearnMore/Sidebar.js index 0d3055c4f..d6bf8ecef 100644 --- a/src/OnboardingSPA/components/Sidebar/components/LearnMore/Sidebar.js +++ b/src/OnboardingSPA/components/Sidebar/components/LearnMore/Sidebar.js @@ -10,6 +10,7 @@ import { SIDEBAR_SLOTFILL_PREFIX, } from '../../../../../constants'; import SidebarSkeleton from './Skeleton/SidebarSkeleton'; +import { trackHiiveEvent } from '../../../../utils/analytics'; const LearnMoreSidebar = () => { const { currentStep } = useSelect( ( select ) => { @@ -22,6 +23,7 @@ const LearnMoreSidebar = () => { const closeSideBar = () => { setIsSidebarOpened( false ); + trackHiiveEvent( 'sidebar-closed', window.location.href ); }; return ( diff --git a/src/OnboardingSPA/components/SkipButton/index.js b/src/OnboardingSPA/components/SkipButton/index.js index 96a475971..6209a3405 100644 --- a/src/OnboardingSPA/components/SkipButton/index.js +++ b/src/OnboardingSPA/components/SkipButton/index.js @@ -8,13 +8,9 @@ import { setFlow } from '../../utils/api/flow'; import { store as nfdOnboardingStore } from '../../store'; import { getSettings, setSettings } from '../../utils/api/settings'; import { wpAdminPage, pluginDashboardPage } from '../../../constants'; +import { HiiveAnalytics } from '@newfold-labs/ui-analytics'; -/** - * Interface Text Inputs with standard design. - * - * @return {WPComponent} SkipButton Component - */ -const SkipButton = () => { +const SkipButton = ( { callback } ) => { const navigate = useNavigate(); const location = useLocation(); const { nextStep, currentData, socialData } = useSelect( ( select ) => { @@ -53,6 +49,7 @@ const SkipButton = () => { } setFlow( currentData ); } + await HiiveAnalytics.dispatchEvents(); // Redirect to Admin Page for normal customers // and Bluehost Dashboard for ecommerce customers const exitLink = exitToWordpressForEcommerce() @@ -61,6 +58,13 @@ const SkipButton = () => { window.location.replace( exitLink ); } + function skip() { + if ( typeof callback === 'function' ) { + callback(); + } + navigate( nextStep.path ); + } + function skipStep() { if ( isLastStep ) { return ( @@ -73,10 +77,7 @@ const SkipButton = () => { ); } return ( - ); diff --git a/src/OnboardingSPA/components/StateHandlers/Ecommerce/index.js b/src/OnboardingSPA/components/StateHandlers/Ecommerce/index.js index bf3d7af1a..7c1c711a5 100644 --- a/src/OnboardingSPA/components/StateHandlers/Ecommerce/index.js +++ b/src/OnboardingSPA/components/StateHandlers/Ecommerce/index.js @@ -1,6 +1,6 @@ import { useViewportMatch } from '@wordpress/compose'; import { useSelect, useDispatch } from '@wordpress/data'; -import { useEffect, useState } from '@wordpress/element'; +import { useEffect } from '@wordpress/element'; import { StepLoader } from '../../Loaders'; import { store as nfdOnboardingStore } from '../../../store'; @@ -22,10 +22,6 @@ const EcommerceStateHandler = ( { } ) => { const isLargeViewport = useViewportMatch( 'medium' ); - const [ woocommerceStatus, setWoocommerceStatus ] = useState( - PLUGIN_STATUS_INSTALLING - ); - const { storedPluginsStatus, brandName } = useSelect( ( select ) => { return { storedPluginsStatus: @@ -35,6 +31,7 @@ const EcommerceStateHandler = ( { }, [] ); const contents = getContents( brandName ); + const woocommerceStatus = storedPluginsStatus[ ECOMMERCE_STEPS_PLUGIN ]; const { updatePluginsStatus, @@ -58,7 +55,6 @@ const EcommerceStateHandler = ( { storedPluginsStatus[ ECOMMERCE_STEPS_PLUGIN ] = PLUGIN_STATUS_NOT_ACTIVE; updatePluginsStatus( storedPluginsStatus ); - return setWoocommerceStatus( PLUGIN_STATUS_NOT_ACTIVE ); } window.location.reload(); }, PLUGIN_INSTALL_WAIT_TIMEOUT ); @@ -98,7 +94,7 @@ const EcommerceStateHandler = ( { useEffect( () => { handleNavigationState( woocommerceStatus ); - }, [ woocommerceStatus ] ); + }, [ storedPluginsStatus ] ); const handlePluginsStatus = async ( pluginsStatus ) => { const pluginStatus = await checkPluginStatus(); @@ -110,15 +106,12 @@ const EcommerceStateHandler = ( { window.location.reload(); break; default: - pluginsStatus[ ECOMMERCE_STEPS_PLUGIN ] = - pluginStatus; - setWoocommerceStatus( pluginStatus ); + pluginsStatus[ ECOMMERCE_STEPS_PLUGIN ] = pluginStatus; updatePluginsStatus( pluginsStatus ); } }; useEffect( () => { - setWoocommerceStatus( storedPluginsStatus[ ECOMMERCE_STEPS_PLUGIN ] ); if ( storedPluginsStatus[ ECOMMERCE_STEPS_PLUGIN ] === PLUGIN_STATUS_INIT ) { diff --git a/src/OnboardingSPA/pages/Steps/DesignHomepageMenu/index.js b/src/OnboardingSPA/pages/Steps/DesignHomepageMenu/index.js index 847aee2a8..1ccfbc35d 100644 --- a/src/OnboardingSPA/pages/Steps/DesignHomepageMenu/index.js +++ b/src/OnboardingSPA/pages/Steps/DesignHomepageMenu/index.js @@ -18,6 +18,7 @@ import { LivePreviewSkeleton, GlobalStylesProvider, } from '../../../components/LivePreview'; +import { trackHiiveEvent } from '../../../utils/analytics'; const StepDesignHomepageMenu = () => { const homepagePatternList = [ @@ -111,7 +112,7 @@ const StepDesignHomepageMenu = () => { async function getHomepagePatternsData() { const homepagePatternDataTemp = await getPatterns( - currentStep.patternId, + currentStep.patternId ); if ( homepagePatternDataTemp?.error ) { return updateThemeStatus( THEME_STATUS_INIT ); @@ -135,11 +136,13 @@ const StepDesignHomepageMenu = () => { function saveDataForHomepage( idx ) { setSelectedHomepage( idx ); + const homepage = homepagePatternList[ idx ]; currentData.data.sitePages = { ...currentData.data.sitePages, - homepage: homepagePatternList[ idx ], + homepage, }; setCurrentOnboardingData( currentData ); + trackHiiveEvent( 'homepage-layout', homepage ); } useEffect( () => { diff --git a/src/OnboardingSPA/pages/Steps/DesignThemeStyles/Menu/index.js b/src/OnboardingSPA/pages/Steps/DesignThemeStyles/Menu/index.js index 15fb19a3a..8f93a07a3 100644 --- a/src/OnboardingSPA/pages/Steps/DesignThemeStyles/Menu/index.js +++ b/src/OnboardingSPA/pages/Steps/DesignThemeStyles/Menu/index.js @@ -22,6 +22,7 @@ import { LivePreviewSkeleton, } from '../../../../components/LivePreview'; import { addColorAndTypographyRoutes } from '../utils'; +import { trackHiiveEvent } from '../../../../utils/analytics'; const StepDesignThemeStylesMenu = () => { const content = getContents(); @@ -90,6 +91,12 @@ const StepDesignThemeStylesMenu = () => { setPattern( patternsResponse?.body ); setGlobalStyles( globalStylesResponse?.body ); setSelectedStyle( currentData.data.theme.variation ); + if ( '' === currentData.data.theme.variation ) { + trackHiiveEvent( + 'default-style', + globalStylesResponse.body[ 0 ].title + ); + } }; useEffect( () => { @@ -106,6 +113,7 @@ const StepDesignThemeStylesMenu = () => { currentData.data.theme.variation = selectedGlobalStyle.title; setCurrentOnboardingData( currentData ); navigate( nextStep.path ); + trackHiiveEvent( 'selected-style', selectedGlobalStyle.title ); }; const skiptoCustomPage = () => { @@ -121,7 +129,7 @@ const StepDesignThemeStylesMenu = () => { currentData.data.customDesign = true; setCurrentOnboardingData( currentData ); - + trackHiiveEvent( 'customize-design', true ); // Find the first Custom Conditional Step and navigate there navigate( conditionalSteps.designColors.path ); }; diff --git a/src/OnboardingSPA/pages/Steps/DesignThemeStyles/Preview/index.js b/src/OnboardingSPA/pages/Steps/DesignThemeStyles/Preview/index.js index 6a62e8179..7845134e8 100644 --- a/src/OnboardingSPA/pages/Steps/DesignThemeStyles/Preview/index.js +++ b/src/OnboardingSPA/pages/Steps/DesignThemeStyles/Preview/index.js @@ -22,6 +22,7 @@ import { import { store as nfdOnboardingStore } from '../../../../store'; import { getPatterns } from '../../../../utils/api/patterns'; import { DesignStateHandler } from '../../../../components/StateHandlers'; +import { trackHiiveEvent } from '../../../../utils/analytics'; const StepDesignThemeStylesPreview = () => { const content = getContents(); @@ -109,6 +110,7 @@ const StepDesignThemeStylesPreview = () => { } if ( selected && 'click' === context ) { + trackHiiveEvent( 'customize-design', true ); navigate( conditionalSteps.designColors.path ); } }; diff --git a/src/OnboardingSPA/pages/Steps/Ecommerce/StepTax/index.js b/src/OnboardingSPA/pages/Steps/Ecommerce/StepTax/index.js index b6148feb9..31a45da52 100644 --- a/src/OnboardingSPA/pages/Steps/Ecommerce/StepTax/index.js +++ b/src/OnboardingSPA/pages/Steps/Ecommerce/StepTax/index.js @@ -15,6 +15,7 @@ import { store as nfdOnboardingStore } from '../../../../store'; import { useWPSettings as getWPSettings } from '../useWPSettings'; import Animate from '../../../../components/Animate'; import getContents from './contents'; +import { trackHiiveEvent } from '../../../../utils/analytics'; function createReverseLookup( state ) { return ( option ) => @@ -101,6 +102,8 @@ const StepTax = () => { }, }, } ); + + trackHiiveEvent( 'tax-information', selectedOption.content ); }; return ( diff --git a/src/OnboardingSPA/pages/Steps/GetStarted/GetStartedExperience/index.js b/src/OnboardingSPA/pages/Steps/GetStarted/GetStartedExperience/index.js index a426d0031..8b4bf0a55 100644 --- a/src/OnboardingSPA/pages/Steps/GetStarted/GetStartedExperience/index.js +++ b/src/OnboardingSPA/pages/Steps/GetStarted/GetStartedExperience/index.js @@ -13,6 +13,7 @@ import { useState, useEffect } from '@wordpress/element'; import { useDispatch, useSelect } from '@wordpress/data'; import Animate from '../../../../components/Animate'; import getContents from './contents'; +import { trackHiiveEvent } from '../../../../utils/analytics'; const GetStartedExperience = () => { const [ wpComfortLevel, setWpComfortLevel ] = useState( '0' ); @@ -52,6 +53,12 @@ const GetStartedExperience = () => { const currentDataCopy = currentData; currentDataCopy.data.wpComfortLevel = value || '0'; setCurrentOnboardingData( currentDataCopy ); + trackHiiveEvent( + 'wp-experience', + content.options.filter( ( option ) => { + return option.value === value; + } )[ 0 ].label + ); }; const content = getContents(); diff --git a/src/OnboardingSPA/pages/Steps/GetStarted/SiteTypeSetup/PrimarySite/index.js b/src/OnboardingSPA/pages/Steps/GetStarted/SiteTypeSetup/PrimarySite/index.js index 32d07ab69..e968550b1 100644 --- a/src/OnboardingSPA/pages/Steps/GetStarted/SiteTypeSetup/PrimarySite/index.js +++ b/src/OnboardingSPA/pages/Steps/GetStarted/SiteTypeSetup/PrimarySite/index.js @@ -13,6 +13,7 @@ import NavCardButton from '../../../../../components/Button/NavCardButton'; import NeedHelpTag from '../../../../../components/NeedHelpTag'; import Animate from '../../../../../components/Animate'; import { getSiteClassification } from '../../../../../utils/api/siteClassification'; +import { trackHiiveEvent } from '../../../../../utils/analytics'; const StepPrimarySetup = () => { const { @@ -41,6 +42,8 @@ const StepPrimarySetup = () => { const [ custom, setCustom ] = useState( false ); const [ siteClassification, setSiteClassification ] = useState(); const [ primaryCategory, setPrimaryCategory ] = useState( '' ); + // Timeout after which a custom input analytics event will be sent. + const [ typingTimeout, setTypingTimeout ] = useState(); const content = getContents(); @@ -87,6 +90,7 @@ const StepPrimarySetup = () => { currentData.data.siteType.primary.refers = 'slug'; currentData.data.siteType.primary.value = primType; setCurrentOnboardingData( currentData ); + trackHiiveEvent( 'primary-type', currentData.data.siteType.primary ); }; /** @@ -96,10 +100,21 @@ const StepPrimarySetup = () => { */ const categoryInput = ( value ) => { setCustom( true ); - setPrimaryCategory( value ); currentData.data.siteType.primary.refers = 'custom'; currentData.data.siteType.primary.value = value; setCurrentOnboardingData( currentData ); + if ( '' !== primaryCategory && primaryCategory !== value ) { + clearTimeout( typingTimeout ); + setTypingTimeout( + setTimeout( () => { + trackHiiveEvent( + 'primary-type', + currentData.data.siteType.primary + ); + }, 1000 ) + ); + } + setPrimaryCategory( value ); }; const primarySiteTypeChips = () => { diff --git a/src/OnboardingSPA/pages/Steps/GetStarted/SiteTypeSetup/SecondarySite/index.js b/src/OnboardingSPA/pages/Steps/GetStarted/SiteTypeSetup/SecondarySite/index.js index d3a1ca259..e020ebac6 100644 --- a/src/OnboardingSPA/pages/Steps/GetStarted/SiteTypeSetup/SecondarySite/index.js +++ b/src/OnboardingSPA/pages/Steps/GetStarted/SiteTypeSetup/SecondarySite/index.js @@ -13,6 +13,7 @@ import NavCardButton from '../../../../../components/Button/NavCardButton'; import NeedHelpTag from '../../../../../components/NeedHelpTag'; import Animate from '../../../../../components/Animate'; import { getSiteClassification } from '../../../../../utils/api/siteClassification'; +import { trackHiiveEvent } from '../../../../../utils/analytics'; const StepPrimarySetup = () => { const { @@ -37,6 +38,8 @@ const StepPrimarySetup = () => { const [ primaryTypesList, setPrimaryTypeList ] = useState(); const [ primaryCategory, setPrimaryCategory ] = useState(); const [ secondaryCategory, setSecondaryCategory ] = useState( '' ); + // Timeout after which a custom input analytics event will be sent. + const [ typingTimeout, setTypingTimeout ] = useState(); const { currentData } = useSelect( ( select ) => { return { @@ -125,10 +128,21 @@ const StepPrimarySetup = () => { */ const categoryInput = ( value ) => { setCustom( true ); - setSecondaryCategory( value ); currentData.data.siteType.secondary.refers = 'custom'; currentData.data.siteType.secondary.value = value; setCurrentOnboardingData( currentData ); + if ( '' !== secondaryCategory && secondaryCategory !== value ) { + clearTimeout( typingTimeout ); + setTypingTimeout( + setTimeout( () => { + trackHiiveEvent( + 'secondary-type', + currentData.data.siteType.secondary + ); + }, 1000 ) + ); + } + setSecondaryCategory( value ); }; /** @@ -137,6 +151,12 @@ const StepPrimarySetup = () => { * @param {string} secType */ const handleCategoryClick = ( secType ) => { + if ( + secondaryCategory === secType && + currentData.data.siteType.primary.value === primaryCategory + ) { + return true; + } setCustom( false ); setSecondaryCategory( secType ); currentData.data.siteType.primary.refers = 'slug'; @@ -144,29 +164,38 @@ const StepPrimarySetup = () => { currentData.data.siteType.primary.value = primaryCategory; currentData.data.siteType.secondary.value = secType; setCurrentOnboardingData( currentData ); + trackHiiveEvent( + 'secondary-type', + currentData.data.siteType.secondary + ); }; const changePrimaryType = ( direction ) => { const idx = primaryTypesList.findIndex( ( val ) => primaryCategory === val ); + let primaryType; switch ( direction ) { case 'back': // idx = ( (idx - 1 + N) % N ) - setPrimaryCategory( + primaryType = primaryTypesList[ ( idx - 1 + primaryTypesList.length ) % primaryTypesList.length - ] - ); + ]; + setPrimaryCategory( primaryType ); break; case 'next': // idx = ( (idx + 1 ) % N ) - setPrimaryCategory( - primaryTypesList[ ( idx + 1 ) % primaryTypesList.length ] - ); + primaryType = + primaryTypesList[ ( idx + 1 ) % primaryTypesList.length ]; + setPrimaryCategory( primaryType ); break; } + trackHiiveEvent( 'primary-type', { + refers: 'slug', + value: primaryType, + } ); }; const secondarySiteTypeChips = () => { diff --git a/src/OnboardingSPA/pages/Steps/TopPriority/index.js b/src/OnboardingSPA/pages/Steps/TopPriority/index.js index 186f01b1b..fd8cd9d5e 100644 --- a/src/OnboardingSPA/pages/Steps/TopPriority/index.js +++ b/src/OnboardingSPA/pages/Steps/TopPriority/index.js @@ -10,6 +10,7 @@ import CommonLayout from '../../../components/Layouts/Common'; import HeadingWithSubHeading from '../../../components/HeadingWithSubHeading'; import SelectableCardList from '../../../components/SelectableCardList/selectable-card-list'; import getContents from './contents'; +import { trackHiiveEvent } from '../../../utils/analytics'; const StepTopPriority = () => { const priorityTypes = { @@ -74,6 +75,7 @@ const StepTopPriority = () => { if ( isLoaded ) { currentData.data.topPriority.priority1 = priorityTypes[ selected ]; setCurrentOnboardingData( currentData ); + trackHiiveEvent( 'top-priority', priorityTypes[ selected ] ); } }, [ selected ] ); @@ -101,7 +103,14 @@ const StepTopPriority = () => { 'wp-module-onboarding' ) }

- + + trackHiiveEvent( + 'top-priority-skipped', + priorityTypes[ selected ] + ) + } + />
); diff --git a/src/OnboardingSPA/utils/analytics/index.js b/src/OnboardingSPA/utils/analytics/index.js new file mode 100644 index 000000000..0ca528504 --- /dev/null +++ b/src/OnboardingSPA/utils/analytics/index.js @@ -0,0 +1,11 @@ +import { HiiveAnalytics, HiiveEvent } from '@newfold-labs/ui-analytics'; +import { HIIVE_ANALYTICS_CATEGORY } from '../../../constants'; + +export const trackHiiveEvent = ( action, value ) => { + const hiiveEvent = new HiiveEvent( HIIVE_ANALYTICS_CATEGORY, action, { + value, + timestamp: Date.now(), + } ); + + HiiveAnalytics.track( hiiveEvent ); +}; diff --git a/src/OnboardingSPA/utils/api/events.js b/src/OnboardingSPA/utils/api/events.js deleted file mode 100644 index b4b40cec2..000000000 --- a/src/OnboardingSPA/utils/api/events.js +++ /dev/null @@ -1,25 +0,0 @@ -import apiFetch from '@wordpress/api-fetch'; - -import { onboardingRestURL } from './common'; - -class Event { - constructor( eventSlug, eventData = {} ) { - this.eventSlug = eventSlug; - this.eventData = eventData; - } - - send() { - apiFetch( { - url: onboardingRestURL( 'events' ), - method: 'POST', - data: { - slug: this.eventSlug, - data: this.eventData, - }, - } ).catch( ( error ) => { - console.error( error ); - } ); - } -} - -export default Event; diff --git a/src/constants.js b/src/constants.js index 0d74c016b..78d4e3f25 100644 --- a/src/constants.js +++ b/src/constants.js @@ -50,6 +50,7 @@ export const PLUGIN_STATUS_NOT_ACTIVE = 'inactive'; export const PLUGIN_STATUS_INSTALLING = 'installing'; export const PLUGIN_STATUS_ACTIVE = 'activated'; export const PLUGIN_INSTALL_WAIT_TIMEOUT = 30000; +export const HIIVE_ANALYTICS_CATEGORY = 'wp-onboarding'; /** * All views for the component. diff --git a/src/onboarding.js b/src/onboarding.js index 8a78591fe..56c002548 100644 --- a/src/onboarding.js +++ b/src/onboarding.js @@ -5,9 +5,17 @@ import { NFD_ONBOARDING_ELEMENT_ID, runtimeDataExists } from './constants'; import domReady from '@wordpress/dom-ready'; import { registerCoreBlocks } from '@wordpress/block-library'; import initializeNFDOnboarding from './OnboardingSPA'; +import { HiiveAnalytics } from '@newfold-labs/ui-analytics'; +import { onboardingRestURL } from './OnboardingSPA/utils/api/common'; if ( runtimeDataExists ) { domReady( () => { + HiiveAnalytics.initialize( { + defaultUrl: onboardingRestURL( 'events' ), + batchUrl: onboardingRestURL( 'events/batch' ), + debounceTime: 3000, + } ); + initializeNFDOnboarding( NFD_ONBOARDING_ELEMENT_ID, window.nfdOnboarding From 1410b35b7c7ec4216c8825946dc145c205d3e686 Mon Sep 17 00:00:00 2001 From: arunshenoy99 Date: Fri, 19 May 2023 17:21:57 +0530 Subject: [PATCH 02/13] prevent redundant color selections --- .../components/Drawer/DrawerPanel/DesignColors.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignColors.js b/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignColors.js index 0a303fc58..a3356e9f7 100644 --- a/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignColors.js +++ b/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignColors.js @@ -85,9 +85,6 @@ const DesignColors = () => { selectedColorsLocalTemp = selectedColors, globalStylesTemp = storedPreviewSettings ) { - if ( selectedColors?.slug === colorStyle ) { - return true; - } const isCustomStyle = colorStyle === 'custom'; const selectedGlobalStyle = globalStylesTemp; const selectedThemeColorPalette = @@ -240,6 +237,9 @@ const DesignColors = () => { }, [ isLoaded, themeStatus ] ); const handleClick = ( colorStyle ) => { + if ( selectedColors?.slug === colorStyle ) { + return true; + } const customColorsTemp = customColors; for ( const custom in customColorsTemp ) customColorsTemp[ custom ] = ''; From e35d416bcb62ebf4aa6b1283d41de3318f44435a Mon Sep 17 00:00:00 2001 From: arunshenoy99 Date: Fri, 19 May 2023 17:41:00 +0530 Subject: [PATCH 03/13] update package.json --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index e2d5cde36..90016ebd2 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "test:unit": "npx wp-env run phpunit 'phpunit -c /var/www/html/wp-content/plugins//phpunit.xml --verbose'" }, "dependencies": { + "@newfold-labs/js-utility-ui-analytics": "https://github.com/newfold-labs/js-utility-ui-analytics.git", "@wordpress/interface": "^5.10.0", "@wordpress/style-engine": "^0.11.0", "classnames": "^2.3.1", From 3a71a8b166bbed7f4aa633f0b707db84084562f9 Mon Sep 17 00:00:00 2001 From: arunshenoy99 Date: Fri, 19 May 2023 17:43:27 +0530 Subject: [PATCH 04/13] use new repo naming convention --- src/OnboardingSPA/components/App/index.js | 2 +- src/OnboardingSPA/components/ExitToWordPress/index.js | 2 +- src/OnboardingSPA/components/SkipButton/index.js | 2 +- src/OnboardingSPA/utils/analytics/index.js | 2 +- src/onboarding.js | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/OnboardingSPA/components/App/index.js b/src/OnboardingSPA/components/App/index.js index 9e4cc586b..79aef8539 100644 --- a/src/OnboardingSPA/components/App/index.js +++ b/src/OnboardingSPA/components/App/index.js @@ -19,7 +19,7 @@ import { useEffect, Fragment, useState } from '@wordpress/element'; import { FullscreenMode } from '@wordpress/interface'; import { API_REQUEST } from '../../../constants'; import NewfoldInterfaceSkeleton from '../NewfoldInterfaceSkeleton'; -import { HiiveAnalytics } from '@newfold-labs/ui-analytics'; +import { HiiveAnalytics } from '@newfold-labs/js-utility-ui-analytics'; import { trackHiiveEvent } from '../../utils/analytics'; /** diff --git a/src/OnboardingSPA/components/ExitToWordPress/index.js b/src/OnboardingSPA/components/ExitToWordPress/index.js index e25f33d26..002fe25e2 100644 --- a/src/OnboardingSPA/components/ExitToWordPress/index.js +++ b/src/OnboardingSPA/components/ExitToWordPress/index.js @@ -10,7 +10,7 @@ import { setFlow } from '../../utils/api/flow'; import { store as nfdOnboardingStore } from '../../store'; import { getSettings, setSettings } from '../../utils/api/settings'; import { wpAdminPage, pluginDashboardPage } from '../../../constants'; -import { HiiveAnalytics } from '@newfold-labs/ui-analytics'; +import { HiiveAnalytics } from '@newfold-labs/js-utility-ui-analytics'; import { trackHiiveEvent } from '../../utils/analytics'; /** diff --git a/src/OnboardingSPA/components/SkipButton/index.js b/src/OnboardingSPA/components/SkipButton/index.js index 6209a3405..02c2617e3 100644 --- a/src/OnboardingSPA/components/SkipButton/index.js +++ b/src/OnboardingSPA/components/SkipButton/index.js @@ -8,7 +8,7 @@ import { setFlow } from '../../utils/api/flow'; import { store as nfdOnboardingStore } from '../../store'; import { getSettings, setSettings } from '../../utils/api/settings'; import { wpAdminPage, pluginDashboardPage } from '../../../constants'; -import { HiiveAnalytics } from '@newfold-labs/ui-analytics'; +import { HiiveAnalytics } from '@newfold-labs/js-utility-ui-analytics'; const SkipButton = ( { callback } ) => { const navigate = useNavigate(); diff --git a/src/OnboardingSPA/utils/analytics/index.js b/src/OnboardingSPA/utils/analytics/index.js index 0ca528504..58fd001d8 100644 --- a/src/OnboardingSPA/utils/analytics/index.js +++ b/src/OnboardingSPA/utils/analytics/index.js @@ -1,4 +1,4 @@ -import { HiiveAnalytics, HiiveEvent } from '@newfold-labs/ui-analytics'; +import { HiiveAnalytics, HiiveEvent } from '@newfold-labs/js-utility-ui-analytics'; import { HIIVE_ANALYTICS_CATEGORY } from '../../../constants'; export const trackHiiveEvent = ( action, value ) => { diff --git a/src/onboarding.js b/src/onboarding.js index 56c002548..aa2b018ca 100644 --- a/src/onboarding.js +++ b/src/onboarding.js @@ -5,7 +5,7 @@ import { NFD_ONBOARDING_ELEMENT_ID, runtimeDataExists } from './constants'; import domReady from '@wordpress/dom-ready'; import { registerCoreBlocks } from '@wordpress/block-library'; import initializeNFDOnboarding from './OnboardingSPA'; -import { HiiveAnalytics } from '@newfold-labs/ui-analytics'; +import { HiiveAnalytics } from '@newfold-labs/js-utility-ui-analytics'; import { onboardingRestURL } from './OnboardingSPA/utils/api/common'; if ( runtimeDataExists ) { From cf27547ea045bd09d6f2f42fbcd69dc6edb70a36 Mon Sep 17 00:00:00 2001 From: arunshenoy99 Date: Fri, 19 May 2023 18:23:40 +0530 Subject: [PATCH 05/13] lint fixes --- .../Drawer/DrawerPanel/DesignColors.js | 37 ++++---- .../Drawer/DrawerPanel/DesignTypography.js | 7 +- .../Steps/DesignThemeStyles/Menu/index.js | 4 +- .../Steps/DesignThemeStyles/Preview/index.js | 4 +- .../SiteTypeSetup/SecondarySite/index.js | 84 +++++++++---------- .../pages/Steps/TopPriority/index.js | 9 +- 6 files changed, 82 insertions(+), 63 deletions(-) diff --git a/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignColors.js b/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignColors.js index a3356e9f7..dc337af6e 100644 --- a/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignColors.js +++ b/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignColors.js @@ -96,13 +96,11 @@ const DesignColors = () => { isCustomStyle && selectedColorsLocalTemp?.[ slug ] !== '' && selectedColorsLocalTemp?.[ slug ] !== undefined - ) + ) { selectedThemeColorPalette[ idx ].color = selectedColorsLocalTemp[ slug ]; - /** - * Add Exception for Background. - * (perhaps scope to yith-wonder in future) - */ else if ( + } else if ( + // Add Exception for Background. (perhaps scope to yith-wonder in future) colorPalettesTemp?.[ colorStyle ]?.[ slug ] && 'base' === slug ) { @@ -135,10 +133,11 @@ const DesignColors = () => { const res = selectedThemeColorPalette.findIndex( ( { slug } ) => slug === slugName ); - if ( res === -1 ) + if ( res === -1 ) { return selectedThemeColorPalette.findIndex( ( { slug } ) => slug === colorPickerCalledBy ); + } return res; } @@ -154,9 +153,10 @@ const DesignColors = () => { colorPickerCalledBy === slug && customColors && customColors[ slug ] !== undefined - ) + ) { selectedThemeColorPalette[ idx ].color = customColors[ slug ]; + } } if ( customColorsMap ) { const colorVariant = customColorsMap[ colorPickerCalledBy ]; @@ -225,8 +225,9 @@ const DesignColors = () => { }; useEffect( () => { - if ( ! isLoaded && THEME_STATUS_ACTIVE === themeStatus ) + if ( ! isLoaded && THEME_STATUS_ACTIVE === themeStatus ) { getColorStylesAndPatterns(); + } if ( isCustomColorActive() ) { setIsAccordionClosed( false ); customColorsResetRef.current.scrollIntoView( { @@ -241,8 +242,9 @@ const DesignColors = () => { return true; } const customColorsTemp = customColors; - for ( const custom in customColorsTemp ) + for ( const custom in customColorsTemp ) { customColorsTemp[ custom ] = ''; + } setCustomColors( customColorsTemp ); saveThemeColorPalette( colorStyle ); @@ -276,8 +278,11 @@ const DesignColors = () => { const selectCustomColor = ( colorType ) => { setShowColorPicker( ! showColorPicker ); - if ( ! showColorPicker ) setColorPickerCalledBy( colorType ); - else setColorPickerCalledBy( '' ); + if ( ! showColorPicker ) { + setColorPickerCalledBy( colorType ); + } else { + setColorPickerCalledBy( '' ); + } }; async function resetColors() { @@ -297,8 +302,9 @@ const DesignColors = () => { ); selectedColors.slug = ''; selectedColors.name = ''; - for ( const colorVal in selectedColors?.color ) + for ( const colorVal in selectedColors?.color ) { selectedColors.color[ colorVal ].color = ''; + } setCustomColors( stateToLocal( selectedColors ) ); currentData.data.palette = selectedColors; @@ -352,8 +358,11 @@ const DesignColors = () => { } function isCustomColorActive() { - for ( const custom in customColors ) - if ( customColors[ custom ] !== '' ) return true; + for ( const custom in customColors ) { + if ( customColors[ custom ] !== '' ) { + return true; + } + } return false; } diff --git a/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignTypography.js b/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignTypography.js index 7e4fac92e..7b049e778 100644 --- a/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignTypography.js +++ b/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignTypography.js @@ -63,8 +63,9 @@ const DesignTypography = () => { }, [ fontPalettes, storedPreviewSettings ] ); useEffect( () => { - if ( ! isLoaded && THEME_STATUS_ACTIVE === themeStatus ) + if ( ! isLoaded && THEME_STATUS_ACTIVE === themeStatus ) { getFontStylesAndPatterns(); + } }, [ isLoaded, themeStatus ] ); const handleClick = async ( fontStyle, context = 'click' ) => { @@ -133,7 +134,9 @@ const DesignTypography = () => { function buildPalettes() { return Object.keys( fontPalettes ).map( ( fontStyle, idx ) => { const splitLabel = fontPalettes[ fontStyle ]?.label.split( '&', 2 ); - if ( splitLabel.length === 0 ) return null; + if ( splitLabel.length === 0 ) { + return null; + } return (
{ }; useEffect( () => { - if ( themeStatus === THEME_STATUS_ACTIVE ) getStylesAndPatterns(); + if ( themeStatus === THEME_STATUS_ACTIVE ) { + getStylesAndPatterns(); + } }, [ themeStatus ] ); const handleClick = ( idx ) => { diff --git a/src/OnboardingSPA/pages/Steps/DesignThemeStyles/Preview/index.js b/src/OnboardingSPA/pages/Steps/DesignThemeStyles/Preview/index.js index 12d7b5445..adc991a3b 100644 --- a/src/OnboardingSPA/pages/Steps/DesignThemeStyles/Preview/index.js +++ b/src/OnboardingSPA/pages/Steps/DesignThemeStyles/Preview/index.js @@ -116,7 +116,9 @@ const StepDesignThemeStylesPreview = () => { }; useEffect( () => { - if ( themeStatus === THEME_STATUS_ACTIVE ) getStylesAndPatterns(); + if ( themeStatus === THEME_STATUS_ACTIVE ) { + getStylesAndPatterns(); + } }, [ themeStatus ] ); return ( diff --git a/src/OnboardingSPA/pages/Steps/GetStarted/SiteTypeSetup/SecondarySite/index.js b/src/OnboardingSPA/pages/Steps/GetStarted/SiteTypeSetup/SecondarySite/index.js index e020ebac6..dd5b11835 100644 --- a/src/OnboardingSPA/pages/Steps/GetStarted/SiteTypeSetup/SecondarySite/index.js +++ b/src/OnboardingSPA/pages/Steps/GetStarted/SiteTypeSetup/SecondarySite/index.js @@ -240,28 +240,28 @@ const StepPrimarySetup = () => {
{ primaryTypesList && primaryTypesList.length > 1 && ( -
- - changePrimaryType( - 'back' - ) - } - onKeyUp={ () => - changePrimaryType( - 'back' - ) - } - role="button" - tabIndex={ 0 } - style={ { - backgroundImage: +
+ + changePrimaryType( + 'back' + ) + } + onKeyUp={ () => + changePrimaryType( + 'back' + ) + } + role="button" + tabIndex={ 0 } + style={ { + backgroundImage: 'var(--chevron-left-icon)', - } } - /> -
- ) } + } } + /> +
+ ) }
{
{ primaryTypesList && primaryTypesList.length > 1 && ( -
- - changePrimaryType( - 'next' - ) - } - onKeyUp={ () => - changePrimaryType( - 'next' - ) - } - role="button" - tabIndex={ 0 } - style={ { - backgroundImage: +
+ + changePrimaryType( + 'next' + ) + } + onKeyUp={ () => + changePrimaryType( + 'next' + ) + } + role="button" + tabIndex={ 0 } + style={ { + backgroundImage: 'var(--chevron-right-icon)', - } } - /> -
- ) } + } } + /> +
+ ) }
) }
diff --git a/src/OnboardingSPA/pages/Steps/TopPriority/index.js b/src/OnboardingSPA/pages/Steps/TopPriority/index.js index fd8cd9d5e..3231fd299 100644 --- a/src/OnboardingSPA/pages/Steps/TopPriority/index.js +++ b/src/OnboardingSPA/pages/Steps/TopPriority/index.js @@ -59,8 +59,9 @@ const StepTopPriority = () => { async function setInitialData() { if ( currentData ) { const val = await currentData?.data.topPriority.priority1; - if ( val !== '' ) setSelected( parseInt( getKey( val ) ) ); - else { + if ( val !== '' ) { + setSelected( parseInt( getKey( val ) ) ); + } else { currentData.data.topPriority.priority1 = priorityTypes[ selected ]; setCurrentOnboardingData( currentData ); @@ -68,7 +69,9 @@ const StepTopPriority = () => { } setisLoaded( true ); } - if ( ! isLoaded ) setInitialData(); + if ( ! isLoaded ) { + setInitialData(); + } }, [ isLoaded ] ); useEffect( () => { From 16d6b07cf479871bcc42d5556f2bd57c39442fef Mon Sep 17 00:00:00 2001 From: arunshenoy99 Date: Fri, 19 May 2023 18:27:12 +0530 Subject: [PATCH 06/13] fix no console error --- src/onboarding.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/onboarding.js b/src/onboarding.js index aa2b018ca..feb7060bd 100644 --- a/src/onboarding.js +++ b/src/onboarding.js @@ -23,6 +23,7 @@ if ( runtimeDataExists ) { registerCoreBlocks(); } ); } else { + /* eslint-disable no-console */ console.log( 'Cannot find Newfold Onboarding runtime data to set __webpack_public_path__.' ); From a3c44b26cedfb66939b2de475b01784101c4e129 Mon Sep 17 00:00:00 2001 From: arunshenoy99 Date: Tue, 23 May 2023 12:24:54 +0530 Subject: [PATCH 07/13] Lint fix: add semicolon --- src/OnboardingSPA/pages/Steps/TopPriority/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OnboardingSPA/pages/Steps/TopPriority/index.js b/src/OnboardingSPA/pages/Steps/TopPriority/index.js index 20193d21e..06fdb23ea 100644 --- a/src/OnboardingSPA/pages/Steps/TopPriority/index.js +++ b/src/OnboardingSPA/pages/Steps/TopPriority/index.js @@ -99,7 +99,7 @@ const StepTopPriority = () => { trackHiiveEvent( 'top-priority-skipped', priorityTypes[ 0 ] - ) + ); }; const content = getContents(); From 9f084d48395d3d3e5f5a318446566b5f730c4647 Mon Sep 17 00:00:00 2001 From: arunshenoy99 Date: Tue, 23 May 2023 14:49:52 +0530 Subject: [PATCH 08/13] switch to ssh to install --- .github/workflows/lint-check-spa.yml | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/lint-check-spa.yml b/.github/workflows/lint-check-spa.yml index c4e31c619..ea8cbbb91 100644 --- a/.github/workflows/lint-check-spa.yml +++ b/.github/workflows/lint-check-spa.yml @@ -41,7 +41,7 @@ jobs: # Installs @wordpress/scripts for lint checks if it does not exist in the cache. - name: Install dependencies - run: npm i @wordpress/scripts + run: npm i @wordpress/scripts @newfold-labs/js-utility-ui-analytics if: steps.cache.outputs.cache-hit != 'true' # Gets the files changed wrt to trunk and filters out the js files. diff --git a/package.json b/package.json index f38bf0bf0..a2c74e707 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "test:unit": "npx wp-env run phpunit 'phpunit -c /var/www/html/wp-content/plugins//phpunit.xml --verbose'" }, "dependencies": { - "@newfold-labs/js-utility-ui-analytics": "https://github.com/newfold-labs/js-utility-ui-analytics.git", + "@newfold-labs/js-utility-ui-analytics": "git+ssh://git@github.com/newfold-labs/js-utility-ui-analytics.git#add/hiive-analytics", "@wordpress/interface": "^5.10.0", "@wordpress/style-engine": "^0.11.0", "classnames": "^2.3.1", From d6755e1ac91ae6844f8d165c489c065a3a4ee063 Mon Sep 17 00:00:00 2001 From: arunshenoy99 Date: Tue, 23 May 2023 18:05:03 +0530 Subject: [PATCH 09/13] setup registry context --- .github/workflows/lint-check-spa.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/lint-check-spa.yml b/.github/workflows/lint-check-spa.yml index ea8cbbb91..f1bd347b2 100644 --- a/.github/workflows/lint-check-spa.yml +++ b/.github/workflows/lint-check-spa.yml @@ -38,6 +38,10 @@ jobs: path: node_modules key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} restore-keys: ${{ runner.os }}-node- + + - name: Setup Registry + run: echo "@newfold-labs:registry=https://npm.pkg.github.com/\\n//npm.pkg.github.com/:_authToken=${{ secrets.NPM_TOKEN }}" > .npmrc + if: steps.cache.outputs.cache-hit != 'true' # Installs @wordpress/scripts for lint checks if it does not exist in the cache. - name: Install dependencies From 316fb68008777a72255bbc7d432fec631189f463 Mon Sep 17 00:00:00 2001 From: arunshenoy99 Date: Tue, 23 May 2023 18:06:56 +0530 Subject: [PATCH 10/13] update dependency --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a2c74e707..e72aac706 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "test:unit": "npx wp-env run phpunit 'phpunit -c /var/www/html/wp-content/plugins//phpunit.xml --verbose'" }, "dependencies": { - "@newfold-labs/js-utility-ui-analytics": "git+ssh://git@github.com/newfold-labs/js-utility-ui-analytics.git#add/hiive-analytics", + "@newfold-labs/js-utility-ui-analytics": "1.0.0", "@wordpress/interface": "^5.10.0", "@wordpress/style-engine": "^0.11.0", "classnames": "^2.3.1", From 8231b331967ce5f81f2cf6db58cdf3cc960dd769 Mon Sep 17 00:00:00 2001 From: arunshenoy99 Date: Tue, 23 May 2023 18:10:06 +0530 Subject: [PATCH 11/13] use printf to handle \n --- .github/workflows/lint-check-spa.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint-check-spa.yml b/.github/workflows/lint-check-spa.yml index f1bd347b2..ef486b73e 100644 --- a/.github/workflows/lint-check-spa.yml +++ b/.github/workflows/lint-check-spa.yml @@ -40,7 +40,7 @@ jobs: restore-keys: ${{ runner.os }}-node- - name: Setup Registry - run: echo "@newfold-labs:registry=https://npm.pkg.github.com/\\n//npm.pkg.github.com/:_authToken=${{ secrets.NPM_TOKEN }}" > .npmrc + run: printf "@newfold-labs:registry=https://npm.pkg.github.com/\n//npm.pkg.github.com/:_authToken=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" > .npmrc if: steps.cache.outputs.cache-hit != 'true' # Installs @wordpress/scripts for lint checks if it does not exist in the cache. From 0d9b79c8377aa473d207d097e49f90a45218e69b Mon Sep 17 00:00:00 2001 From: arunshenoy99 Date: Tue, 23 May 2023 18:17:46 +0530 Subject: [PATCH 12/13] update token --- .github/workflows/lint-check-spa.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint-check-spa.yml b/.github/workflows/lint-check-spa.yml index ef486b73e..8c8470e4f 100644 --- a/.github/workflows/lint-check-spa.yml +++ b/.github/workflows/lint-check-spa.yml @@ -40,7 +40,7 @@ jobs: restore-keys: ${{ runner.os }}-node- - name: Setup Registry - run: printf "@newfold-labs:registry=https://npm.pkg.github.com/\n//npm.pkg.github.com/:_authToken=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" > .npmrc + run: printf "@newfold-labs:registry=https://npm.pkg.github.com/\n//npm.pkg.github.com/:_authToken=${{ secrets.NPM_TOKEN }}" > .npmrc if: steps.cache.outputs.cache-hit != 'true' # Installs @wordpress/scripts for lint checks if it does not exist in the cache. From d32de0382eb08dad54bbde57e3dbc5197574ebb1 Mon Sep 17 00:00:00 2001 From: arunshenoy99 Date: Fri, 26 May 2023 14:21:53 +0530 Subject: [PATCH 13/13] update to use the new initialize structure, return false when not a valid category, move skip check to a better place in code --- includes/Services/EventService.php | 2 +- src/OnboardingSPA/components/SkipButton/index.js | 2 +- src/onboarding.js | 12 +++++++++--- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/includes/Services/EventService.php b/includes/Services/EventService.php index a2af41dc6..d8b215677 100644 --- a/includes/Services/EventService.php +++ b/includes/Services/EventService.php @@ -75,7 +75,7 @@ public static function validate( $event ) { } if ( ! isset( $event['category'] ) || ! self::validate_category( $event['category'] ) ) { - $event['category'] = Events::get_category(); + return false; } return $event; diff --git a/src/OnboardingSPA/components/SkipButton/index.js b/src/OnboardingSPA/components/SkipButton/index.js index d389f8232..a68159a2a 100644 --- a/src/OnboardingSPA/components/SkipButton/index.js +++ b/src/OnboardingSPA/components/SkipButton/index.js @@ -46,10 +46,10 @@ const SkipButton = ( { callback = false } ) => { if ( socialDataResp ) { setOnboardingSocialData( socialDataResp ); } + await HiiveAnalytics.dispatchEvents(); } setFlow( currentData ); } - await HiiveAnalytics.dispatchEvents(); // Redirect to Admin Page for normal customers // and Bluehost Dashboard for ecommerce customers const exitLink = exitToWordpressForEcommerce() diff --git a/src/onboarding.js b/src/onboarding.js index feb7060bd..0f54397e6 100644 --- a/src/onboarding.js +++ b/src/onboarding.js @@ -11,9 +11,15 @@ import { onboardingRestURL } from './OnboardingSPA/utils/api/common'; if ( runtimeDataExists ) { domReady( () => { HiiveAnalytics.initialize( { - defaultUrl: onboardingRestURL( 'events' ), - batchUrl: onboardingRestURL( 'events/batch' ), - debounceTime: 3000, + urls: { + single: onboardingRestURL( 'events' ), + batch: onboardingRestURL( 'events/batch' ), + }, + settings: { + debounce: { + time: 3000, + }, + }, } ); initializeNFDOnboarding(