diff --git a/assets/js/modules/analytics/components/common/EnableUniversalAnalytics.js b/assets/js/modules/analytics/components/common/EnableUniversalAnalytics.js new file mode 100644 index 00000000000..363fa5f16b7 --- /dev/null +++ b/assets/js/modules/analytics/components/common/EnableUniversalAnalytics.js @@ -0,0 +1,103 @@ +/** + * Enable Universal Analytics component. + * + * Site Kit by Google, Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * External dependencies + */ +import PropTypes from 'prop-types'; + +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { Fragment, useCallback } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import Data from 'googlesitekit-data'; +import { Switch } from 'googlesitekit-components'; +import { CORE_FORMS } from '../../../../googlesitekit/datastore/forms/constants'; +import { MODULES_ANALYTICS, FORM_SETUP } from '../../datastore/constants'; +import ProfileSelect from './ProfileSelect'; +import PropertySelect from './PropertySelect'; +const { useSelect, useDispatch } = Data; + +export default function EnableUniversalAnalytics( { children } ) { + const accountID = useSelect( ( select ) => + select( MODULES_ANALYTICS ).getAccountID() + ); + const properties = useSelect( ( select ) => { + if ( ! accountID ) { + return []; + } + + return select( MODULES_ANALYTICS ).getProperties( accountID ) || []; + } ); + + const { setValues } = useDispatch( CORE_FORMS ); + + const isUAEnabled = useSelect( ( select ) => + select( CORE_FORMS ).getValue( FORM_SETUP, 'enableUA' ) + ); + + const onChange = useCallback( () => { + setValues( FORM_SETUP, { enableUA: ! isUAEnabled } ); + }, [ setValues, isUAEnabled ] ); + + if ( properties.length === 0 ) { + return null; + } + + return ( + +
+ +

+ { __( + 'The old version of Analytics, which stops recording data after July 1, 2023', + 'google-site-kit' + ) } +

+
+ { isUAEnabled && ( + +
+ + +
+ + { /* Renders the SetupUseSnippetSwitch or SettingsUseSnippetSwitch */ } + { children } +
+ ) } +
+ ); +} + +EnableUniversalAnalytics.propTypes = { + children: PropTypes.node.isRequired, +}; diff --git a/assets/js/modules/analytics/components/common/index.js b/assets/js/modules/analytics/components/common/index.js index fc95fe7fb01..4cc68b07b7f 100644 --- a/assets/js/modules/analytics/components/common/index.js +++ b/assets/js/modules/analytics/components/common/index.js @@ -23,6 +23,7 @@ export { default as AdsConversionIDTextField } from './AdsConversionIDTextField' export { default as AdSenseLinkCTA } from './AdSenseLinkCTA'; export { default as AnonymizeIPSwitch } from './AnonymizeIPSwitch'; export { default as ExistingGTMPropertyNotice } from './ExistingGTMPropertyNotice'; +export { default as EnableUniversalAnalytics } from './EnableUniversalAnalytics'; export { default as ProfileNameTextField } from './ProfileNameTextField'; export { default as GA4Notice } from './GA4Notice'; export { default as ProfileSelect } from './ProfileSelect'; diff --git a/assets/js/modules/analytics/components/setup/SetupForm.js b/assets/js/modules/analytics/components/setup/SetupForm.js index 47a5c89704c..caf0e72566e 100644 --- a/assets/js/modules/analytics/components/setup/SetupForm.js +++ b/assets/js/modules/analytics/components/setup/SetupForm.js @@ -39,23 +39,31 @@ import { MODULES_ANALYTICS, FORM_SETUP, EDIT_SCOPE, + SETUP_FLOW_MODE_GA4_LEGACY, } from '../../datastore/constants'; import { CORE_USER } from '../../../../googlesitekit/datastore/user/constants'; import { CORE_FORMS } from '../../../../googlesitekit/datastore/forms/constants'; import { isPermissionScopeError } from '../../../../util/errors'; import SetupFormUA from './SetupFormUA'; import SetupFormGA4 from './SetupFormGA4'; +import SetupFormGA4Legacy from './SetupFormGA4Legacy'; import SetupFormGA4Transitional from './SetupFormGA4Transitional'; import StoreErrorNotices from '../../../../components/StoreErrorNotices'; import { ExistingGTMPropertyNotice } from '../common'; import { CORE_MODULES } from '../../../../googlesitekit/modules/datastore/constants'; import { MODULES_TAGMANAGER } from '../../../tagmanager/datastore/constants'; +import { MODULES_ANALYTICS_4 } from '../../../analytics-4/datastore/constants'; +import { useFeature } from '../../../../hooks/useFeature'; const { useSelect, useDispatch } = Data; export default function SetupForm( { finishSetup } ) { + const ga4ReportingEnabled = useFeature( 'ga4Reporting' ); const canSubmitChanges = useSelect( ( select ) => select( MODULES_ANALYTICS ).canSubmitChanges() ); + const canSubmitChangesGA4 = useSelect( ( select ) => + select( MODULES_ANALYTICS_4 ).canSubmitChanges() + ); const hasEditScope = useSelect( ( select ) => select( CORE_USER ).hasScope( EDIT_SCOPE ) ); @@ -121,11 +129,20 @@ export default function SetupForm( { finishSetup } ) { /> { setupFlowMode === SETUP_FLOW_MODE_UA && } { setupFlowMode === SETUP_FLOW_MODE_GA4 && } + { setupFlowMode === SETUP_FLOW_MODE_GA4_LEGACY && ( + + ) } { setupFlowMode === SETUP_FLOW_MODE_GA4_TRANSITIONAL && ( ) }
-
diff --git a/assets/js/modules/analytics/components/setup/SetupFormGA4.js b/assets/js/modules/analytics/components/setup/SetupFormGA4.js index 49236fcdc36..5aa4e9796ed 100644 --- a/assets/js/modules/analytics/components/setup/SetupFormGA4.js +++ b/assets/js/modules/analytics/components/setup/SetupFormGA4.js @@ -16,87 +16,31 @@ * limitations under the License. */ -/** - * External dependencies - */ -import { useMount } from 'react-use'; - /** * WordPress dependencies */ -import { __, _x } from '@wordpress/i18n'; -import { Fragment, useEffect } from '@wordpress/element'; +import { __ } from '@wordpress/i18n'; +import { Fragment } from '@wordpress/element'; /** * Internal dependencies */ import Data from 'googlesitekit-data'; -import { CORE_FORMS } from '../../../../googlesitekit/datastore/forms/constants'; -import { - MODULES_ANALYTICS, - PROPERTY_CREATE, - FORM_SETUP, - ACCOUNT_CREATE, -} from '../../datastore/constants'; -import { MODULES_ANALYTICS_4 } from '../../../analytics-4/datastore/constants'; +import { MODULES_ANALYTICS } from '../../datastore/constants'; import { PropertySelect as GA4PropertySelect, WebDataStreamSelect as GA4WebDataStreamSelect, } from '../../../analytics-4/components/common'; -import { AccountSelect, GA4PropertyNotice } from '../common'; +import { AccountSelect } from '../common'; import SetupUseSnippetSwitchUA from './SetupUseSnippetSwitch'; -import { SetupUseSnippetSwitch as SetupUseSnippetSwitchGA4 } from '../../../analytics-4/components/setup'; -const { useSelect, useDispatch } = Data; +import EnableUniversalAnalytics from '../common/EnableUniversalAnalytics'; +const { useSelect } = Data; export default function SetupFormGA4() { const accounts = useSelect( ( select ) => select( MODULES_ANALYTICS ).getAccounts() ) || []; - const ga4HasExistingTag = useSelect( ( select ) => - select( MODULES_ANALYTICS_4 ).hasExistingTag() - ); - const ga4ExistingTag = useSelect( ( select ) => - select( MODULES_ANALYTICS_4 ).getExistingTag() - ); - const ga4MeasurementID = useSelect( ( select ) => - select( MODULES_ANALYTICS_4 ).getMeasurementID() - ); - const ga4PropertyID = useSelect( ( select ) => - select( MODULES_ANALYTICS_4 ).getPropertyID() - ); - - const accountID = useSelect( ( select ) => - select( MODULES_ANALYTICS ).getAccountID() - ); - const { selectProperty } = useDispatch( MODULES_ANALYTICS ); - const { setValues } = useDispatch( CORE_FORMS ); - const { setUseSnippet } = useDispatch( MODULES_ANALYTICS_4 ); - - const shouldShowAssociatedPropertyNotice = - accountID && accountID !== ACCOUNT_CREATE && ga4PropertyID; - - const hasExistingGA4Tag = useSelect( ( select ) => - select( MODULES_ANALYTICS_4 ).hasExistingTag() - ); - - useMount( () => { - selectProperty( PROPERTY_CREATE ); - setValues( FORM_SETUP, { - profileName: _x( - 'All Web Site Data', - 'default Analytics view name', - 'google-site-kit' - ), - } ); - } ); - - useEffect( () => { - if ( ga4HasExistingTag ) { - setUseSnippet( ga4ExistingTag !== ga4MeasurementID ); - } - }, [ setUseSnippet, ga4HasExistingTag, ga4ExistingTag, ga4MeasurementID ] ); - return ( { !! accounts.length && ( @@ -114,18 +58,9 @@ export default function SetupFormGA4() { - { hasExistingGA4Tag && } - - { shouldShowAssociatedPropertyNotice && ( - - - - ) } + + + ); } diff --git a/assets/js/modules/analytics/components/setup/SetupFormGA4.stories.js b/assets/js/modules/analytics/components/setup/SetupFormGA4.stories.js index 088ce135bd5..1b2e2ef66f9 100644 --- a/assets/js/modules/analytics/components/setup/SetupFormGA4.stories.js +++ b/assets/js/modules/analytics/components/setup/SetupFormGA4.stories.js @@ -19,7 +19,7 @@ /** * Internal dependencies */ -import { MODULES_ANALYTICS } from '../../datastore/constants'; +import { FORM_SETUP, MODULES_ANALYTICS } from '../../datastore/constants'; import { MODULES_ANALYTICS_4 } from '../../../analytics-4/datastore/constants'; import { provideModules, @@ -30,31 +30,33 @@ import ModuleSetup from '../../../../components/setup/ModuleSetup'; import WithRegistrySetup from '../../../../../../tests/js/WithRegistrySetup'; import * as fixtures from '../../datastore/__fixtures__'; import * as ga4Fixtures from '../../../analytics-4/datastore/__fixtures__'; +import { CORE_FORMS } from '../../../../googlesitekit/datastore/forms/constants'; function Template() { return ; } -export const WithoutExistingTag = Template.bind( null ); -WithoutExistingTag.storyName = 'Without Existing Tag'; -WithoutExistingTag.scenario = { - label: 'Modules/Analytics/Setup/SetupFormGA4/WithoutExistingTag', +const { accounts, properties, profiles } = fixtures.accountsPropertiesProfiles; +const accountID = accounts[ 0 ].id; +const propertyID = properties[ 0 ].id; + +export const WithoutEnableUAToggle = Template.bind( null ); +WithoutEnableUAToggle.storyName = 'Without Enable UA Toggle'; +WithoutEnableUAToggle.scenario = { + label: 'Modules/Analytics/Setup/SetupFormGA4/WithoutEnableUAToggle', delay: 250, }; -export const WithGA4Tag = Template.bind( null ); -WithGA4Tag.storyName = 'With GA4 Tag, non-matching property selected'; -WithGA4Tag.decorators = [ +export const WithEnableUAToggle = Template.bind( null ); +WithEnableUAToggle.storyName = 'With Enable UA Toggle'; +WithEnableUAToggle.decorators = [ ( Story ) => { const setupRegistry = ( registry ) => { registry - .dispatch( MODULES_ANALYTICS_4 ) - .selectProperty( ga4Fixtures.properties[ 1 ]._id ); - - registry.dispatch( MODULES_ANALYTICS_4 ).receiveGetExistingTag( - // eslint-disable-next-line sitekit/acronym-case - ga4Fixtures.webDataStreams[ 0 ].webStreamData.measurementId - ); + .dispatch( MODULES_ANALYTICS ) + .receiveGetProperties( fixtures.propertiesProfiles.properties, { + accountID, + } ); }; return ( @@ -64,25 +66,42 @@ WithGA4Tag.decorators = [ ); }, ]; +WithEnableUAToggle.scenario = { + label: 'Modules/Analytics/Setup/SetupFormGA4/WithEnableUAToggle', + delay: 250, +}; -export const WithBothTags = Template.bind( null ); -WithBothTags.storyName = 'With Both Tags, matching GA4 property selected'; -WithBothTags.decorators = [ +export const WithUAMatchingTag = Template.bind( null ); +WithUAMatchingTag.storyName = 'With UA Enabled, matching UA property selected'; +WithUAMatchingTag.decorators = [ ( Story ) => { const setupRegistry = ( registry ) => { - registry.dispatch( MODULES_ANALYTICS_4 ).receiveGetExistingTag( - // eslint-disable-next-line sitekit/acronym-case - ga4Fixtures.webDataStreams[ 0 ].webStreamData.measurementId - ); - registry .dispatch( MODULES_ANALYTICS ) - .receiveGetExistingTag( - fixtures.accountsPropertiesProfiles.properties[ 0 ].id - ); + .receiveGetProperties( properties, { + accountID, + } ); + registry + .dispatch( MODULES_ANALYTICS ) + .receiveGetExistingTag( propertyID ); + registry + .dispatch( MODULES_ANALYTICS ) + .receiveGetProfiles( profiles, { + accountID, + propertyID, + } ); + registry + .dispatch( MODULES_ANALYTICS ) + .selectProperty( properties[ 0 ].id ); + const profileName = fixtures.createProfile.name; + registry.dispatch( CORE_FORMS ).setValues( FORM_SETUP, { + profileName, + } ); + registry.dispatch( CORE_FORMS ).setValues( FORM_SETUP, { + enableUA: true, + } ); registry.dispatch( MODULES_ANALYTICS ).setUseSnippet( true ); - registry.dispatch( MODULES_ANALYTICS_4 ).setUseSnippet( false ); }; return ( @@ -92,8 +111,8 @@ WithBothTags.decorators = [ ); }, ]; -WithBothTags.scenario = { - label: 'Modules/Analytics/Setup/SetupFormGA4/WithBothTags', +WithUAMatchingTag.scenario = { + label: 'Modules/Analytics/Setup/SetupFormGA4/WithUAMatchingTag', delay: 250, }; @@ -102,10 +121,6 @@ export default { decorators: [ ( Story ) => { const setupRegistry = ( registry ) => { - const accounts = - fixtures.accountsPropertiesProfiles.accounts.slice( 0, 1 ); - const accountID = accounts[ 0 ].id; - provideModules( registry, [ { slug: 'analytics', @@ -170,5 +185,5 @@ export default { ); }, ], - parameters: { padding: 0 }, + parameters: { padding: 0, features: [ 'ga4Reporting' ] }, }; diff --git a/assets/js/modules/analytics/components/setup/SetupFormGA4Legacy.js b/assets/js/modules/analytics/components/setup/SetupFormGA4Legacy.js new file mode 100644 index 00000000000..4809beb8077 --- /dev/null +++ b/assets/js/modules/analytics/components/setup/SetupFormGA4Legacy.js @@ -0,0 +1,131 @@ +/** + * Analytics GA4 Setup form (legacy version, supports UA setup). + * + * Site Kit by Google, Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * External dependencies + */ +import { useMount } from 'react-use'; + +/** + * WordPress dependencies + */ +import { __, _x } from '@wordpress/i18n'; +import { Fragment, useEffect } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import Data from 'googlesitekit-data'; +import { CORE_FORMS } from '../../../../googlesitekit/datastore/forms/constants'; +import { + MODULES_ANALYTICS, + PROPERTY_CREATE, + FORM_SETUP, + ACCOUNT_CREATE, +} from '../../datastore/constants'; +import { MODULES_ANALYTICS_4 } from '../../../analytics-4/datastore/constants'; +import { + PropertySelect as GA4PropertySelect, + WebDataStreamSelect as GA4WebDataStreamSelect, +} from '../../../analytics-4/components/common'; +import { AccountSelect, GA4PropertyNotice } from '../common'; +import SetupUseSnippetSwitchUA from './SetupUseSnippetSwitch'; +import { SetupUseSnippetSwitch as SetupUseSnippetSwitchGA4 } from '../../../analytics-4/components/setup'; +const { useSelect, useDispatch } = Data; + +export default function SetupFormGA4Legacy() { + const accounts = + useSelect( ( select ) => select( MODULES_ANALYTICS ).getAccounts() ) || + []; + + const ga4HasExistingTag = useSelect( ( select ) => + select( MODULES_ANALYTICS_4 ).hasExistingTag() + ); + const ga4ExistingTag = useSelect( ( select ) => + select( MODULES_ANALYTICS_4 ).getExistingTag() + ); + const ga4MeasurementID = useSelect( ( select ) => + select( MODULES_ANALYTICS_4 ).getMeasurementID() + ); + const ga4PropertyID = useSelect( ( select ) => + select( MODULES_ANALYTICS_4 ).getPropertyID() + ); + + const accountID = useSelect( ( select ) => + select( MODULES_ANALYTICS ).getAccountID() + ); + const { selectProperty } = useDispatch( MODULES_ANALYTICS ); + const { setValues } = useDispatch( CORE_FORMS ); + const { setUseSnippet } = useDispatch( MODULES_ANALYTICS_4 ); + + const shouldShowAssociatedPropertyNotice = + accountID && accountID !== ACCOUNT_CREATE && ga4PropertyID; + + const hasExistingGA4Tag = useSelect( ( select ) => + select( MODULES_ANALYTICS_4 ).hasExistingTag() + ); + + useMount( () => { + selectProperty( PROPERTY_CREATE ); + setValues( FORM_SETUP, { + profileName: _x( + 'All Web Site Data', + 'default Analytics view name', + 'google-site-kit' + ), + } ); + } ); + + useEffect( () => { + if ( ga4HasExistingTag ) { + setUseSnippet( ga4ExistingTag !== ga4MeasurementID ); + } + }, [ setUseSnippet, ga4HasExistingTag, ga4ExistingTag, ga4MeasurementID ] ); + + return ( + + { !! accounts.length && ( +

+ { __( + 'Please select the account information below. You can change this later in your settings.', + 'google-site-kit' + ) } +

+ ) } + +
+ + + +
+ + { hasExistingGA4Tag && } + + { shouldShowAssociatedPropertyNotice && ( + + + + ) } +
+ ); +} diff --git a/assets/js/modules/analytics/components/setup/SetupFormGA4Legacy.stories.js b/assets/js/modules/analytics/components/setup/SetupFormGA4Legacy.stories.js new file mode 100644 index 00000000000..b2b8c925e29 --- /dev/null +++ b/assets/js/modules/analytics/components/setup/SetupFormGA4Legacy.stories.js @@ -0,0 +1,174 @@ +/** + * SetupFormGA4Legacy component stories. + * + * Site Kit by Google, Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Internal dependencies + */ +import { MODULES_ANALYTICS } from '../../datastore/constants'; +import { MODULES_ANALYTICS_4 } from '../../../analytics-4/datastore/constants'; +import { + provideModules, + provideModuleRegistrations, + provideSiteInfo, +} from '../../../../../../tests/js/utils'; +import ModuleSetup from '../../../../components/setup/ModuleSetup'; +import WithRegistrySetup from '../../../../../../tests/js/WithRegistrySetup'; +import * as fixtures from '../../datastore/__fixtures__'; +import * as ga4Fixtures from '../../../analytics-4/datastore/__fixtures__'; + +function Template() { + return ; +} + +export const WithoutExistingTag = Template.bind( null ); +WithoutExistingTag.storyName = 'Without Existing Tag'; +WithoutExistingTag.scenario = { + label: 'Modules/Analytics/Setup/SetupFormGA4Legacy/WithoutExistingTag', + delay: 250, +}; + +export const WithGA4Tag = Template.bind( null ); +WithGA4Tag.storyName = 'With GA4 Tag, non-matching property selected'; +WithGA4Tag.decorators = [ + ( Story ) => { + const setupRegistry = ( registry ) => { + registry + .dispatch( MODULES_ANALYTICS_4 ) + .selectProperty( ga4Fixtures.properties[ 1 ]._id ); + + registry.dispatch( MODULES_ANALYTICS_4 ).receiveGetExistingTag( + // eslint-disable-next-line sitekit/acronym-case + ga4Fixtures.webDataStreams[ 0 ].webStreamData.measurementId + ); + }; + + return ( + + + + ); + }, +]; + +export const WithBothTags = Template.bind( null ); +WithBothTags.storyName = 'With Both Tags, matching GA4 property selected'; +WithBothTags.decorators = [ + ( Story ) => { + const setupRegistry = ( registry ) => { + registry.dispatch( MODULES_ANALYTICS_4 ).receiveGetExistingTag( + // eslint-disable-next-line sitekit/acronym-case + ga4Fixtures.webDataStreams[ 0 ].webStreamData.measurementId + ); + + registry + .dispatch( MODULES_ANALYTICS ) + .receiveGetExistingTag( + fixtures.accountsPropertiesProfiles.properties[ 0 ].id + ); + + registry.dispatch( MODULES_ANALYTICS ).setUseSnippet( true ); + registry.dispatch( MODULES_ANALYTICS_4 ).setUseSnippet( false ); + }; + + return ( + + + + ); + }, +]; +WithBothTags.scenario = { + label: 'Modules/Analytics/Setup/SetupFormGA4Legacy/WithBothTags', + delay: 250, +}; + +export default { + title: 'Modules/Analytics/Setup/SetupFormGA4Legacy', + decorators: [ + ( Story ) => { + const setupRegistry = ( registry ) => { + const accounts = + fixtures.accountsPropertiesProfiles.accounts.slice( 0, 1 ); + const accountID = accounts[ 0 ].id; + + provideModules( registry, [ + { + slug: 'analytics', + active: true, + connected: true, + }, + { + slug: 'analytics-4', + active: true, + connected: true, + }, + ] ); + + provideSiteInfo( registry ); + provideModuleRegistrations( registry ); + + registry + .dispatch( MODULES_ANALYTICS_4 ) + .receiveGetSettings( {} ); + registry + .dispatch( MODULES_ANALYTICS_4 ) + .receiveGetExistingTag( null ); + registry + .dispatch( MODULES_ANALYTICS_4 ) + .receiveGetProperties( ga4Fixtures.properties, { + accountID, + } ); + registry + .dispatch( MODULES_ANALYTICS_4 ) + .receiveGetWebDataStreamsBatch( + ga4Fixtures.webDataStreamsBatchSetup, + { + propertyIDs: Object.keys( + ga4Fixtures.webDataStreamsBatchSetup + ), + } + ); + + registry.dispatch( MODULES_ANALYTICS ).receiveGetSettings( { + adsConversionID: '', + canUseSnippet: true, + } ); + registry + .dispatch( MODULES_ANALYTICS ) + .receiveGetExistingTag( null ); + registry + .dispatch( MODULES_ANALYTICS ) + .receiveGetAccounts( accounts ); + registry + .dispatch( MODULES_ANALYTICS ) + .receiveGetProperties( [], { accountID } ); + + registry + .dispatch( MODULES_ANALYTICS ) + .selectAccount( accountID ); + }; + + return ( + + + + ); + }, + ], + parameters: { padding: 0 }, +}; diff --git a/assets/js/modules/analytics/components/setup/index.js b/assets/js/modules/analytics/components/setup/index.js index dd87128bf6a..01cf1ea900f 100644 --- a/assets/js/modules/analytics/components/setup/index.js +++ b/assets/js/modules/analytics/components/setup/index.js @@ -20,5 +20,6 @@ export { default as SetupForm } from './SetupForm'; export { default as SetupMain } from './SetupMain'; export { default as SetupFormUA } from './SetupFormUA'; export { default as SetupFormGA4 } from './SetupFormGA4'; +export { default as SetupFormGA4Legacy } from './SetupFormGA4Legacy'; export { default as SetupFormGA4Transitional } from './SetupFormGA4Transitional'; export { default as SetupUseSnippetSwitch } from './SetupUseSnippetSwitch'; diff --git a/assets/js/modules/analytics/datastore/accounts.js b/assets/js/modules/analytics/datastore/accounts.js index bf8609055d0..b836b6fa729 100644 --- a/assets/js/modules/analytics/datastore/accounts.js +++ b/assets/js/modules/analytics/datastore/accounts.js @@ -99,6 +99,7 @@ const RECEIVE_ACCOUNTS_PROPERTIES_PROFILES_COMPLETION = const RESET_ACCOUNTS = 'RESET_ACCOUNTS'; const START_SELECTING_ACCOUNT = 'START_SELECTING_ACCOUNT'; const FINISH_SELECTING_ACCOUNT = 'FINISH_SELECTING_ACCOUNT'; +const RESET_PROPERTY_AND_PROFILE_IDS = 'RESET_PROPERTY_AND_PROFILE_IDS'; const baseInitialState = { accounts: undefined, @@ -137,6 +138,13 @@ const baseActions = { ).invalidateResolutionForStoreSelector( 'getAccounts' ); }, + resetPropertyAndProfileIDs() { + return { + payload: {}, + type: RESET_PROPERTY_AND_PROFILE_IDS, + }; + }, + selectAccount: createValidatedAction( ( accountID ) => { invariant( @@ -298,6 +306,18 @@ const baseReducer = ( state, { type, payload } ) => { }; } + case RESET_PROPERTY_AND_PROFILE_IDS: { + return { + ...state, + settings: { + ...state.settings, + propertyID: '', + internalWebPropertyID: '', + profileID: '', + }, + }; + } + default: { return state; } diff --git a/assets/js/modules/analytics/datastore/constants.js b/assets/js/modules/analytics/datastore/constants.js index 10d99db7704..8215eea1ad6 100644 --- a/assets/js/modules/analytics/datastore/constants.js +++ b/assets/js/modules/analytics/datastore/constants.js @@ -46,6 +46,7 @@ export const UI_ALL_TRAFFIC_LOADED = 'dashboardAllTrafficWidgetLoaded'; // Setup modes for Analytics based on UA/GA4 properties. export const SETUP_FLOW_MODE_UA = 'ua'; export const SETUP_FLOW_MODE_GA4 = 'ga4'; +export const SETUP_FLOW_MODE_GA4_LEGACY = 'ga4-legacy'; export const SETUP_FLOW_MODE_GA4_TRANSITIONAL = 'ga4-transitional'; export const PROPERTY_TYPE_UA = 'ua'; diff --git a/assets/js/modules/analytics/datastore/settings.js b/assets/js/modules/analytics/datastore/settings.js index fd6f4e332c5..15ac8483929 100644 --- a/assets/js/modules/analytics/datastore/settings.js +++ b/assets/js/modules/analytics/datastore/settings.js @@ -51,6 +51,7 @@ import { PROFILE_CREATE, FORM_SETUP, DASHBOARD_VIEW_GA4, + DASHBOARD_VIEW_UA, } from './constants'; import { createStrictSelect } from '../../../googlesitekit/data/utils'; import { isPermissionScopeError } from '../../../util/errors'; @@ -92,8 +93,12 @@ export async function submitChanges( registry ) { const ga4ReportingEnabled = isFeatureEnabled( 'ga4Reporting' ); + const isUAEnabled = select( CORE_FORMS ).getValue( FORM_SETUP, 'enableUA' ); let propertyID = select( MODULES_ANALYTICS ).getPropertyID(); - if ( ! ga4ReportingEnabled && propertyID === PROPERTY_CREATE ) { + if ( + ( ! ga4ReportingEnabled || isUAEnabled ) && + propertyID === PROPERTY_CREATE + ) { const accountID = select( MODULES_ANALYTICS ).getAccountID(); const { response: property, error } = await dispatch( MODULES_ANALYTICS @@ -112,7 +117,10 @@ export async function submitChanges( registry ) { } const profileID = select( MODULES_ANALYTICS ).getProfileID(); - if ( ! ga4ReportingEnabled && profileID === PROFILE_CREATE ) { + if ( + ( ! ga4ReportingEnabled || isUAEnabled ) && + profileID === PROFILE_CREATE + ) { const profileName = select( CORE_FORMS ).getValue( FORM_SETUP, 'profileName' @@ -129,6 +137,19 @@ export async function submitChanges( registry ) { dispatch( MODULES_ANALYTICS ).setProfileID( profile.id ); } + // If `ga4Reporting` is enabled AND `enableUA` toggle is disabled, we need to reset the + // property and profile IDs to ensure that the UA settings are not saved. + if ( ga4ReportingEnabled && ! isUAEnabled ) { + dispatch( MODULES_ANALYTICS ).resetPropertyAndProfileIDs(); + } + + // If `ga4Reporting` is enabled and the dashboard view is set to UA, we need + // to set the dashboard view to GA4. + const dashboardView = select( MODULES_ANALYTICS ).getDashboardView(); + if ( ga4ReportingEnabled && dashboardView === DASHBOARD_VIEW_UA ) { + dispatch( MODULES_ANALYTICS ).setDashboardView( DASHBOARD_VIEW_GA4 ); + } + const ga4PropertyID = select( MODULES_ANALYTICS_4 ).getPropertyID(); const ga4StreamID = select( MODULES_ANALYTICS_4 ).getWebDataStreamID(); @@ -198,9 +219,10 @@ export function validateCanSubmitChanges( select ) { INVARIANT_INVALID_ACCOUNT_ID ); + const isUAEnabled = select( CORE_FORMS ).getValue( FORM_SETUP, 'enableUA' ); // Do not require selecting a property or profile if `ga4Reporting` is enabled. - // Therefore, only validate these if `ga4Reporting` is not enabled. - if ( ! isFeatureEnabled( 'ga4Reporting' ) ) { + // Only validate UA settings if `ga4Reporting` is not enabled OR `enableUA` is enabled. + if ( ! isFeatureEnabled( 'ga4Reporting' ) || isUAEnabled ) { invariant( isValidPropertySelection( getPropertyID() ), INVARIANT_INVALID_PROPERTY_SELECTION diff --git a/assets/js/modules/analytics/datastore/setup-flow.js b/assets/js/modules/analytics/datastore/setup-flow.js index 99dc442a81e..e55392eacfa 100644 --- a/assets/js/modules/analytics/datastore/setup-flow.js +++ b/assets/js/modules/analytics/datastore/setup-flow.js @@ -27,11 +27,13 @@ import { SETUP_FLOW_MODE_GA4_TRANSITIONAL, ACCOUNT_CREATE, FORM_SETUP, + SETUP_FLOW_MODE_GA4_LEGACY, } from './constants'; import { MODULES_ANALYTICS_4 } from '../../analytics-4/datastore/constants'; import { CORE_MODULES } from '../../../googlesitekit/modules/datastore/constants'; import { CORE_FORMS } from '../../../googlesitekit/datastore/forms/constants'; import { MODULES_TAGMANAGER } from '../../tagmanager/datastore/constants'; +import { isFeatureEnabled } from '../../../features'; const { createRegistrySelector } = Data; @@ -54,6 +56,10 @@ const baseSelectors = { return undefined; } + if ( isFeatureEnabled( 'ga4Reporting' ) ) { + return SETUP_FLOW_MODE_GA4; + } + const accountID = select( MODULES_ANALYTICS ).getAccountID(); // If no accountID exists then no account is selected. This means we should @@ -84,7 +90,7 @@ const baseSelectors = { // If no UA properties exist and there are GA4 properties, use GA4-only. if ( uaProperties.length === 0 ) { - return SETUP_FLOW_MODE_GA4; + return SETUP_FLOW_MODE_GA4_LEGACY; } // There are UA and GA4 properties, so use the transitional mode. diff --git a/assets/js/modules/analytics/datastore/setup-flow.test.js b/assets/js/modules/analytics/datastore/setup-flow.test.js index 1dc0c08801c..d89087b20ba 100644 --- a/assets/js/modules/analytics/datastore/setup-flow.test.js +++ b/assets/js/modules/analytics/datastore/setup-flow.test.js @@ -28,6 +28,7 @@ import { SETUP_FLOW_MODE_GA4, SETUP_FLOW_MODE_GA4_TRANSITIONAL, FORM_SETUP, + SETUP_FLOW_MODE_GA4_LEGACY, } from './constants'; import { createTestRegistry, @@ -40,6 +41,7 @@ import { CORE_MODULES } from '../../../googlesitekit/modules/datastore/constants import { MODULES_TAGMANAGER } from '../../tagmanager/datastore/constants'; import { parseLiveContainerVersionIDs } from '../../tagmanager/datastore/__factories__/utils'; import * as gtmFixtures from '../../tagmanager/datastore/__fixtures__'; +import { enabledFeatures } from '../../../features'; const accountID = 'pub-12345678'; @@ -250,7 +252,20 @@ describe( 'modules/analytics setup-flow', () => { ).toBeUndefined(); } ); - it( 'should return "ga4" if selected account returns an empty array from UA getProperties selector', () => { + it( 'should return "ga4" if the `ga4Reporting` feature flag is enabled', () => { + registry + .dispatch( MODULES_ANALYTICS ) + .setAccountID( accountID ); + populateAnalytics4Datastore( registry ); + + enabledFeatures.add( 'ga4Reporting' ); + + expect( + registry.select( MODULES_ANALYTICS ).getSetupFlowMode() + ).toBe( SETUP_FLOW_MODE_GA4 ); + } ); + + it( 'should return "ga4-legacy" if selected account returns an empty array from UA getProperties selector', () => { registry .dispatch( MODULES_ANALYTICS ) .setAccountID( accountID ); @@ -262,7 +277,7 @@ describe( 'modules/analytics setup-flow', () => { expect( registry.select( MODULES_ANALYTICS ).getSetupFlowMode() - ).toBe( SETUP_FLOW_MODE_GA4 ); + ).toBe( SETUP_FLOW_MODE_GA4_LEGACY ); } ); it( 'should return "ga4-transitional" if both GA4 and UA properties are found for an account', () => { diff --git a/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4Legacy_WithBothTags_0_document_0_small.png b/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4Legacy_WithBothTags_0_document_0_small.png new file mode 100644 index 00000000000..fb90ecf358d Binary files /dev/null and b/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4Legacy_WithBothTags_0_document_0_small.png differ diff --git a/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4Legacy_WithBothTags_0_document_1_medium.png b/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4Legacy_WithBothTags_0_document_1_medium.png new file mode 100644 index 00000000000..3e6cfb4f5a9 Binary files /dev/null and b/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4Legacy_WithBothTags_0_document_1_medium.png differ diff --git a/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4Legacy_WithBothTags_0_document_2_large.png b/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4Legacy_WithBothTags_0_document_2_large.png new file mode 100644 index 00000000000..21f1cc085d3 Binary files /dev/null and b/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4Legacy_WithBothTags_0_document_2_large.png differ diff --git a/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4Legacy_WithoutExistingTag_0_document_0_small.png b/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4Legacy_WithoutExistingTag_0_document_0_small.png new file mode 100644 index 00000000000..2e707b08e10 Binary files /dev/null and b/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4Legacy_WithoutExistingTag_0_document_0_small.png differ diff --git a/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4Legacy_WithoutExistingTag_0_document_1_medium.png b/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4Legacy_WithoutExistingTag_0_document_1_medium.png new file mode 100644 index 00000000000..da8bd22e699 Binary files /dev/null and b/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4Legacy_WithoutExistingTag_0_document_1_medium.png differ diff --git a/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4Legacy_WithoutExistingTag_0_document_2_large.png b/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4Legacy_WithoutExistingTag_0_document_2_large.png new file mode 100644 index 00000000000..d11421da523 Binary files /dev/null and b/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4Legacy_WithoutExistingTag_0_document_2_large.png differ diff --git a/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4_WithEnableUAToggle_0_document_0_small.png b/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4_WithEnableUAToggle_0_document_0_small.png new file mode 100644 index 00000000000..922cf041aa1 Binary files /dev/null and b/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4_WithEnableUAToggle_0_document_0_small.png differ diff --git a/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4_WithEnableUAToggle_0_document_1_medium.png b/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4_WithEnableUAToggle_0_document_1_medium.png new file mode 100644 index 00000000000..310aec6000c Binary files /dev/null and b/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4_WithEnableUAToggle_0_document_1_medium.png differ diff --git a/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4_WithEnableUAToggle_0_document_2_large.png b/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4_WithEnableUAToggle_0_document_2_large.png new file mode 100644 index 00000000000..34ea81171d0 Binary files /dev/null and b/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4_WithEnableUAToggle_0_document_2_large.png differ diff --git a/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4_WithUAMatchingTag_0_document_0_small.png b/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4_WithUAMatchingTag_0_document_0_small.png new file mode 100644 index 00000000000..928ad888642 Binary files /dev/null and b/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4_WithUAMatchingTag_0_document_0_small.png differ diff --git a/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4_WithUAMatchingTag_0_document_1_medium.png b/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4_WithUAMatchingTag_0_document_1_medium.png new file mode 100644 index 00000000000..00efcf77fea Binary files /dev/null and b/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4_WithUAMatchingTag_0_document_1_medium.png differ diff --git a/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4_WithUAMatchingTag_0_document_2_large.png b/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4_WithUAMatchingTag_0_document_2_large.png new file mode 100644 index 00000000000..b35060de9c4 Binary files /dev/null and b/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4_WithUAMatchingTag_0_document_2_large.png differ diff --git a/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4_WithoutEnableUAToggle_0_document_0_small.png b/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4_WithoutEnableUAToggle_0_document_0_small.png new file mode 100644 index 00000000000..572579eb62e Binary files /dev/null and b/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4_WithoutEnableUAToggle_0_document_0_small.png differ diff --git a/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4_WithoutEnableUAToggle_0_document_1_medium.png b/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4_WithoutEnableUAToggle_0_document_1_medium.png new file mode 100644 index 00000000000..2ce401948ce Binary files /dev/null and b/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4_WithoutEnableUAToggle_0_document_1_medium.png differ diff --git a/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4_WithoutEnableUAToggle_0_document_2_large.png b/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4_WithoutEnableUAToggle_0_document_2_large.png new file mode 100644 index 00000000000..c640704b42b Binary files /dev/null and b/tests/backstop/reference/google-site-kit_Modules_Analytics_Setup_SetupFormGA4_WithoutEnableUAToggle_0_document_2_large.png differ