Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ACR Dashboard Subtle Notification #9612

Open
wants to merge 23 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import {
import { useSelect, useDispatch } from 'googlesitekit-data';
import { CORE_USER } from '../../googlesitekit/datastore/user/constants';
import { KEY_METRICS_WIDGETS } from './key-metrics-widgets';
import { useConversionReportingEventsForTailoredMetrics } from './hooks/useConversionReportingEventsForTailoredMetrics';

function ConfirmSitePurposeChangeModal( {
dialogActive = false,
Expand All @@ -57,9 +58,14 @@ function ConfirmSitePurposeChangeModal( {
} );

const purpose = userInputSettings?.purpose?.values?.[ 0 ];
const haveConversionReportingEventsForTailoredMetrics =
useConversionReportingEventsForTailoredMetrics( purpose );

const newMetrics = useSelect( ( select ) => {
return select( CORE_USER ).getAnswerBasedMetrics( purpose );
return select( CORE_USER ).getAnswerBasedMetrics(
purpose,
haveConversionReportingEventsForTailoredMetrics
);
} );

const { saveUserInputSettings } = useDispatch( CORE_USER );
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/**
* ConversionReportingDashboardSubtleNotification component.
*
* Site Kit by Google, Copyright 2024 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 { createInterpolateElement } from '@wordpress/element';

/**
* Internal dependencies
*/
import { useSelect } from 'googlesitekit-data';
import { Button, SpinnerButton } from 'googlesitekit-components';
import StarFill from '../../../svg/icons/star-fill.svg';
import SubtleNotification from '../../googlesitekit/notifications/components/layout/SubtleNotification';
import { CORE_SITE } from '../../googlesitekit/datastore/site/constants';
import Link from '../Link';

export default function ConversionReportingDashboardSubtleNotification( {
ctaLabel,
handleCTAClick,
isSaving,
onDismiss,
dismissCTALabel = __( 'Maybe later', 'google-site-kit' ),
} ) {
const documentationURL = useSelect( ( select ) =>
select( CORE_SITE ).getDocumentationLinkURL( 'key-metrics' )
);

return (
<SubtleNotification
className="googlesitekit-acr-subtle-notification"
title={ __( 'New key metrics were added!', 'google-site-kit' ) }
description={ createInterpolateElement(
__(
'We’ve extended your metrics selection with metrics that aren’t available by default in Analytics. Add them to your dashboard to get a better understanding of how users interact with your site. <a>Learn more</a>',
'google-site-kit'
),
{
a: (
<Link
href={ documentationURL }
external
aria-label={ __(
'Learn more about advanced conversion reporting',
'google-site-kit'
) }
/>
),
}
) }
dismissCTA={
<Button tertiary onClick={ onDismiss }>
{ dismissCTALabel }
</Button>
}
additionalCTA={
<SpinnerButton onClick={ handleCTAClick } isSaving={ isSaving }>
{ ctaLabel }
</SpinnerButton>
}
icon={ <StarFill width={ 24 } height={ 24 } /> }
/>
);
}

ConversionReportingDashboardSubtleNotification.propTypes = {
ctaLabel: PropTypes.string.isRequired,
handleCTAClick: PropTypes.func.isRequired,
isSaving: PropTypes.bool,
onDismiss: PropTypes.func.isRequired,
dismissCTALabel: PropTypes.string,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/**
* ConversionReportingNotificationCTAWidget component.
*
* Site Kit by Google, Copyright 2024 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.
*/

/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { useCallback, useState } from '@wordpress/element';

/**
* External dependencies
*/
import PropTypes from 'prop-types';

/**
* Internal dependencies
*/
import { useSelect, useDispatch } from 'googlesitekit-data';
import { CORE_USER } from '../../googlesitekit/datastore/user/constants';
import whenActive from '../../util/when-active';
import ConversionReportingDashboardSubtleNotification from './ConversionReportingDashboardSubtleNotification';
import { useConversionReportingEventsForTailoredMetrics } from './hooks/useConversionReportingEventsForTailoredMetrics';
import { MODULES_ANALYTICS_4 } from '../../modules/analytics-4/datastore/constants';

function ConversionReportingNotificationCTAWidget( { Widget, WidgetNull } ) {
const [ isSaving, setIsSaving ] = useState( false );
const isUserInputCompleted = useSelect( ( select ) =>
select( CORE_USER ).isUserInputCompleted()
);

const userInputSettings = useSelect( ( select ) =>
select( CORE_USER ).getUserInputSettings()
);
const keyMetricSettings = useSelect( ( select ) =>
select( CORE_USER ).getKeyMetricsSettings()
);

const { setKeyMetricsSetting, saveKeyMetricsSettings } =
useDispatch( CORE_USER );
const { dismissNewConversionReportingEvents } =
useDispatch( MODULES_ANALYTICS_4 );

const handleCTAClick = useCallback( async () => {
setIsSaving( true );
await setKeyMetricsSetting( 'includeConversionTailoredMetrics', true );
await saveKeyMetricsSettings( {
widgetSlugs: undefined,
} );
dismissNewConversionReportingEvents();
setIsSaving( false );
}, [
setKeyMetricsSetting,
saveKeyMetricsSettings,
dismissNewConversionReportingEvents,
] );

const onDismiss = useCallback( () => {
dismissNewConversionReportingEvents();
}, [ dismissNewConversionReportingEvents ] );

const purpose = userInputSettings?.purpose?.values?.[ 0 ];
const haveConversionReportingEventsForTailoredMetrics =
useConversionReportingEventsForTailoredMetrics( purpose );

// Initial callout is surfaced to the users with tailored metrics, if detectedEvents setting
// has a conversion event associated with the ACR key metrics matching the current site purpose answer.
// If new ACR key metrics that can be added are found using haveConversionReportingEventsForTailoredMetrics,
// and have not been already included, which is determined by includeConversionTailoredMetrics setting, callout banner should be displayed.
const shouldShowInitialCalloutForTailoredMetrics =
isUserInputCompleted &&
haveConversionReportingEventsForTailoredMetrics &&
! keyMetricSettings?.includeConversionTailoredMetrics;

if ( ! shouldShowInitialCalloutForTailoredMetrics ) {
return <WidgetNull />;
}

return (
<Widget noPadding fullWidth>
<ConversionReportingDashboardSubtleNotification
ctaLabel={ __( 'Add metrics', 'google-site-kit' ) }
handleCTAClick={ handleCTAClick }
isSaving={ isSaving }
onDismiss={ onDismiss }
/>
</Widget>
);
}

ConversionReportingNotificationCTAWidget.propTypes = {
Widget: PropTypes.elementType.isRequired,
WidgetNull: PropTypes.elementType,
};

export default whenActive( { moduleName: 'analytics-4' } )(
ConversionReportingNotificationCTAWidget
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/**
* ConversionReportingNotificationCTAWidget Component Stories.
*
* Site Kit by Google, Copyright 2024 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 {
provideModules,
provideUserAuthentication,
} from '../../../../tests/js/test-utils';
import WithRegistrySetup from '../../../../tests/js/WithRegistrySetup';
import { CORE_USER } from '../../googlesitekit/datastore/user/constants';
import { withWidgetComponentProps } from '../../googlesitekit/widgets/util';
import { MODULES_ANALYTICS_4 } from '../../modules/analytics-4/datastore/constants';
import ConversionReportingNotificationCTAWidget from './ConversionReportingNotificationCTAWidget';

const WidgetWithComponentProps = withWidgetComponentProps(
'keyMetricsSetupCTA'
)( ConversionReportingNotificationCTAWidget );

function Template() {
return (
<div className="googlesitekit-widget-area--mainDashboardKeyMetricsPrimary">
<div className="googlesitekit-widget-area-widgets">
<div className="googlesitekit-widget--keyMetricsEventDetectionCalloutNotification">
<WidgetWithComponentProps />
</div>
</div>
</div>
);
}

export const Default = Template.bind( {} );
Default.storyName = 'ConversionReportingNotificationCTAWidget';
Default.parameters = {
features: [ 'conversionReporting' ],
};
Default.scenario = {
label: 'KeyMetrics/ConversionReportingNotificationCTAWidget',
};

export default {
title: 'Key Metrics/ConversionReportingNotificationCTAWidget',
decorators: [
( Story, { parameters } ) => {
const setupRegistry = async ( registry ) => {
provideModules( registry, [
{
slug: 'analytics-4',
active: true,
connected: true,
},
] );

provideUserAuthentication( registry );

const data = {
newEvents: [ 'contact' ],
lostEvents: [],
};

await registry
.dispatch( MODULES_ANALYTICS_4 )
.receiveConversionReportingInlineData( data );
registry
.dispatch( CORE_USER )
.receiveIsUserInputCompleted( true );

registry.dispatch( CORE_USER ).receiveGetKeyMetricsSettings( {
widgetSlugs: [],
includeConversionTailoredMetrics: false,
isWidgetHidden: false,
} );

registry
.dispatch( MODULES_ANALYTICS_4 )
.setDetectedEvents( [ 'contact' ] );

registry.dispatch( CORE_USER ).receiveGetUserInputSettings( {
purpose: {
values: [ 'publish_blog' ],
scope: 'site',
},
} );
};

return (
<WithRegistrySetup
func={ setupRegistry }
features={ parameters.features || [] }
>
<Story />
</WithRegistrySetup>
);
},
],
};
Loading