diff --git a/assets/js/components/ChangeBadge.js b/assets/js/components/ChangeBadge.js index ed823a1f025..874df068907 100644 --- a/assets/js/components/ChangeBadge.js +++ b/assets/js/components/ChangeBadge.js @@ -27,11 +27,20 @@ import classnames from 'classnames'; */ import { calculateChange, numFmt } from '../util'; -export default function ChangeBadge( { previousValue, currentValue } ) { - const change = calculateChange( previousValue, currentValue ); +export default function ChangeBadge( props ) { + const { previousValue, currentValue, isAbsolute } = props; + + const change = isAbsolute + ? currentValue - previousValue + : calculateChange( previousValue, currentValue ); const isNegative = change < 0; const isZero = change === 0; + // Do not display the change badge if the change value can't be calculated. + if ( change === null ) { + return null; + } + return (
; export const Default = Template.bind( {} ); -Default.storyName = 'KeyMetricsSetupCTAWidget'; +Default.storyName = 'SetupCTAWidget'; Default.scenario = { - label: 'Global/KeyMetricsSetupCTAWidget', + label: 'KeyMetrics/SetupCTAWidget', delay: 250, }; Default.parameters = { @@ -41,7 +41,7 @@ Default.parameters = { }; export default { - title: 'Components/KeyMetrics', + title: 'Key Metrics', decorators: [ ( Story ) => { const setupRegistry = ( registry ) => { diff --git a/assets/js/components/KeyMetrics/MetricTileNumeric.js b/assets/js/components/KeyMetrics/MetricTileNumeric.js index 3b08c79e92b..78c33de9583 100644 --- a/assets/js/components/KeyMetrics/MetricTileNumeric.js +++ b/assets/js/components/KeyMetrics/MetricTileNumeric.js @@ -24,26 +24,32 @@ import PropTypes from 'prop-types'; /** * Internal dependencies */ +import { numFmt, expandNumFmtOptions } from '../../util'; import ChangeBadge from '../ChangeBadge'; import PreviewBlock from '../PreviewBlock'; -export default function MetricTileNumeric( { - Widget, - loading, - title, - metricValue, - subText, - previousValue, - currentValue, -} ) { +export default function MetricTileNumeric( props ) { + const { + Widget, + loading, + title, + metricValue, + metricValueFormat, + subText, + previousValue, + currentValue, + } = props; + if ( loading ) { return ( - + ); } + const formatOptions = expandNumFmtOptions( metricValueFormat ); + return (
@@ -53,11 +59,12 @@ export default function MetricTileNumeric( {
- { metricValue } + { numFmt( metricValue, formatOptions ) }

@@ -74,6 +81,10 @@ MetricTileNumeric.propTypes = { loading: PropTypes.bool, title: PropTypes.string, metricValue: PropTypes.oneOfType( [ PropTypes.string, PropTypes.number ] ), + metricValueFormat: PropTypes.oneOfType( [ + PropTypes.string, + PropTypes.object, + ] ), subtext: PropTypes.string, previousValue: PropTypes.number, currentValue: PropTypes.number, diff --git a/assets/js/components/KeyMetrics/MetricTileNumeric.stories.js b/assets/js/components/KeyMetrics/MetricTileNumeric.stories.js index bc0b541bbed..9c1ef9cf271 100644 --- a/assets/js/components/KeyMetrics/MetricTileNumeric.stories.js +++ b/assets/js/components/KeyMetrics/MetricTileNumeric.stories.js @@ -22,9 +22,8 @@ import MetricTileNumeric from './MetricTileNumeric'; import { withWidgetComponentProps } from '../../googlesitekit/widgets/util'; -const WidgetWithComponentProps = withWidgetComponentProps( - 'kmAnalyticsNewVisitors' -)( MetricTileNumeric ); +const WidgetWithComponentProps = + withWidgetComponentProps( 'test' )( MetricTileNumeric ); const Template = ( { ...args } ) => ; @@ -38,7 +37,7 @@ Positive.args = { previousValue: 91, }; Positive.scenario = { - label: 'Components/KeyMetrics/Widgets/MetricTileNumeric/Positive', + label: 'KeyMetrics/MetricTileNumeric/Positive', delay: 250, }; @@ -52,7 +51,7 @@ Negative.args = { previousValue: 103, }; Negative.scenario = { - label: 'Components/KeyMetrics/Widgets/MetricTileNumeric/Negative', + label: 'KeyMetrics/MetricTileNumeric/Negative', delay: 250, }; @@ -66,7 +65,7 @@ ZeroChange.args = { previousValue: 100, }; ZeroChange.scenario = { - label: 'Components/KeyMetrics/Widgets/MetricTileNumeric/ZeroChange', + label: 'KeyMetrics/MetricTileNumeric/ZeroChange', delay: 250, }; @@ -77,6 +76,6 @@ Loading.args = { }; export default { - title: 'Components/KeyMetrics/WidgetTiles/MetricTileNumeric', + title: 'Key Metrics/WidgetTiles/MetricTileNumeric', component: MetricTileNumeric, }; diff --git a/assets/js/components/KeyMetrics/index.js b/assets/js/components/KeyMetrics/index.js new file mode 100644 index 00000000000..1e0c0537ef9 --- /dev/null +++ b/assets/js/components/KeyMetrics/index.js @@ -0,0 +1,19 @@ +/** + * 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. + */ + +export { default as KeyMetricsSetupCTAWidget } from './KeyMetricsSetupCTAWidget'; +export { default as MetricTileNumeric } from './MetricTileNumeric'; +export * from './utils'; diff --git a/assets/js/components/KeyMetrics/utils.js b/assets/js/components/KeyMetrics/utils.js new file mode 100644 index 00000000000..ff1de7ba1d4 --- /dev/null +++ b/assets/js/components/KeyMetrics/utils.js @@ -0,0 +1,60 @@ +/** + * 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 Data from 'googlesitekit-data'; +import { CORE_USER } from '../../googlesitekit/datastore/user/constants'; +const { useSelect } = Data; + +/** + * Returns a Higher-Order Component to render wrapped components when the Key Metrics widget is visible. + * + * @since n.e.x.t + * + * @return {Function} Enhancing function. + */ +export function whenKeyMetricsWidgetVisible() { + return ( WrappedComponent ) => { + const WrapperComponent = ( props ) => { + const { WidgetNull } = props; + + const isHidden = useSelect( ( select ) => + select( CORE_USER ).isKeyMetricsWidgetHidden() + ); + + if ( isHidden !== false ) { + if ( WidgetNull ) { + return ; + } + + return null; + } + + // Return the wrapped component. + return ; + }; + + WrapperComponent.displayName = `WhenKeyMetricsWidgetVisible(${ + WrappedComponent.displayName || + WrappedComponent.name || + 'Annonymous' + })`; + + return WrapperComponent; + }; +} diff --git a/assets/js/modules/analytics-4/components/widgets/LoyalVisitorsWidget.js b/assets/js/modules/analytics-4/components/widgets/LoyalVisitorsWidget.js index 5d0902e35d0..15b243a6be5 100644 --- a/assets/js/modules/analytics-4/components/widgets/LoyalVisitorsWidget.js +++ b/assets/js/modules/analytics-4/components/widgets/LoyalVisitorsWidget.js @@ -21,31 +21,96 @@ */ import PropTypes from 'prop-types'; +/** + * WordPress dependencies + */ +import { __, sprintf } from '@wordpress/i18n'; + /** * Internal dependencies */ import Data from 'googlesitekit-data'; import { CORE_USER } from '../../../../googlesitekit/datastore/user/constants'; +import { + DATE_RANGE_OFFSET, + MODULES_ANALYTICS_4, +} from '../../datastore/constants'; +import { + MetricTileNumeric, + whenKeyMetricsWidgetVisible, +} from '../../../../components/KeyMetrics'; + +const { useSelect, useInViewSelect } = Data; + +function LoyalVisitorsWidget( { Widget } ) { + const dates = useSelect( ( select ) => + select( CORE_USER ).getDateRangeDates( { + offsetDays: DATE_RANGE_OFFSET, + compare: true, + } ) + ); -const { useSelect } = Data; + const reportOptions = { + ...dates, + dimensions: [ 'newVsReturning' ], + metrics: [ { name: 'activeUsers' } ], + }; -export default function LoyalVisitorsWidget( { Widget, WidgetNull } ) { - const keyMetricsWidgetHidden = useSelect( ( select ) => - select( CORE_USER ).isKeyMetricsWidgetHidden() + const report = useInViewSelect( ( select ) => + select( MODULES_ANALYTICS_4 ).getReport( reportOptions ) ); - if ( keyMetricsWidgetHidden !== false ) { - return ; - } + const loading = useInViewSelect( + ( select ) => + ! select( MODULES_ANALYTICS_4 ).hasFinishedResolution( + 'getReport', + [ reportOptions ] + ) + ); + + const newVisitors = + parseInt( report?.rows?.[ 1 ]?.metricValues[ 0 ]?.value, 10 ) || 0; + const returningVisitors = + parseInt( report?.rows?.[ 3 ]?.metricValues[ 0 ]?.value, 10 ) || 0; + const totalVisitors = newVisitors + returningVisitors; + + const prevNewVisitors = + parseInt( report?.rows?.[ 0 ]?.metricValues[ 0 ]?.value, 10 ) || 0; + const prevReturningVisitors = + parseInt( report?.rows?.[ 2 ]?.metricValues[ 0 ]?.value, 10 ) || 0; + const prevTotalVisitors = prevNewVisitors + prevReturningVisitors; + + const currentPercentage = + totalVisitors > 0 ? returningVisitors / totalVisitors : 0; + const prevPercentage = + prevTotalVisitors > 0 ? prevReturningVisitors / prevTotalVisitors : 0; + + const format = { + style: 'percent', + signDisplay: 'exceptZero', + maximumFractionDigits: 1, + }; return ( - -

TODO: UI for LoyalVisitorsWidget
- + ); } LoyalVisitorsWidget.propTypes = { Widget: PropTypes.elementType.isRequired, - WidgetNull: PropTypes.elementType.isRequired, }; + +export default whenKeyMetricsWidgetVisible()( LoyalVisitorsWidget ); diff --git a/assets/js/modules/analytics-4/components/widgets/LoyalVisitorsWidget.stories.js b/assets/js/modules/analytics-4/components/widgets/LoyalVisitorsWidget.stories.js new file mode 100644 index 00000000000..ff61759dc56 --- /dev/null +++ b/assets/js/modules/analytics-4/components/widgets/LoyalVisitorsWidget.stories.js @@ -0,0 +1,127 @@ +/** + * 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 { CORE_USER } from '../../../../googlesitekit/datastore/user/constants'; +import { MODULES_ANALYTICS_4 } from '../../datastore/constants'; +import { + provideKeyMetrics, + provideModules, +} from '../../../../../../tests/js/utils'; +import { withWidgetComponentProps } from '../../../../googlesitekit/widgets/util'; +import WithRegistrySetup from '../../../../../../tests/js/WithRegistrySetup'; +import LoyalVisitorsWidget from './LoyalVisitorsWidget'; +import { + getAnalytics4MockResponse, + provideAnalytics4MockReport, +} from '../../utils/data-mock'; +import { replaceValuesInAnalytics4ReportWithZeroData } from '../../../../../../.storybook/utils/zeroReports'; + +const reportOptions = { + compareStartDate: '2020-07-14', + compareEndDate: '2020-08-10', + startDate: '2020-08-11', + endDate: '2020-09-07', + dimensions: [ 'newVsReturning' ], + metrics: [ + { + name: 'activeUsers', + }, + ], +}; + +const WidgetWithComponentProps = withWidgetComponentProps( + 'kmAnalyticsLoyalVisitors' +)( LoyalVisitorsWidget ); + +const Template = ( { setupRegistry, ...args } ) => ( + + + +); + +export const Ready = Template.bind( {} ); +Ready.storyName = 'Ready'; +Ready.args = { + setupRegistry: ( registry ) => { + provideAnalytics4MockReport( registry, reportOptions ); + }, +}; +Ready.scenario = { + label: 'KeyMetrics/LoyalVisitors/Ready', + delay: 250, +}; + +export const Loading = Template.bind( {} ); +Loading.storyName = 'Loading'; +Loading.args = { + setupRegistry: ( { dispatch } ) => { + dispatch( MODULES_ANALYTICS_4 ).startResolution( 'getReport', [ + reportOptions, + ] ); + }, +}; + +export const ZeroData = Template.bind( {} ); +ZeroData.storyName = 'Zero Data'; +ZeroData.args = { + setupRegistry: ( { dispatch } ) => { + const report = getAnalytics4MockResponse( reportOptions ); + const zeroReport = + replaceValuesInAnalytics4ReportWithZeroData( report ); + + dispatch( MODULES_ANALYTICS_4 ).receiveGetReport( zeroReport, { + options: reportOptions, + } ); + }, +}; +ZeroData.scenario = { + label: 'KeyMetrics/LoyalVisitors/ZeroData', + delay: 250, +}; + +export default { + title: 'Key Metrics/LoyalVisitors', + decorators: [ + ( Story, { args } ) => { + const setupRegistry = ( registry ) => { + global._googlesitekitUserData.isUserInputCompleted = false; + provideModules( registry, [ + { + slug: 'analytics-4', + active: true, + connected: true, + }, + ] ); + + registry.dispatch( CORE_USER ).setReferenceDate( '2020-09-08' ); + + provideKeyMetrics( registry ); + + // Call story-specific setup. + args.setupRegistry( registry ); + }; + + return ( + + + + ); + }, + ], +}; diff --git a/assets/js/modules/analytics-4/components/widgets/NewVisitorsWidget.js b/assets/js/modules/analytics-4/components/widgets/NewVisitorsWidget.js index 05c9ac44d38..a6c95cef45f 100644 --- a/assets/js/modules/analytics-4/components/widgets/NewVisitorsWidget.js +++ b/assets/js/modules/analytics-4/components/widgets/NewVisitorsWidget.js @@ -30,20 +30,19 @@ import { __, sprintf } from '@wordpress/i18n'; * Internal dependencies */ import Data from 'googlesitekit-data'; -import MetricTileNumeric from '../../../../components/KeyMetrics/MetricTileNumeric'; import { CORE_USER } from '../../../../googlesitekit/datastore/user/constants'; import { DATE_RANGE_OFFSET, MODULES_ANALYTICS_4, } from '../../datastore/constants'; +import { + MetricTileNumeric, + whenKeyMetricsWidgetVisible, +} from '../../../../components/KeyMetrics'; const { useSelect, useInViewSelect } = Data; -export default function NewVisitorsWidget( { Widget, WidgetNull } ) { - const keyMetricsWidgetHidden = useSelect( ( select ) => - select( CORE_USER ).isKeyMetricsWidgetHidden() - ); - +function NewVisitorsWidget( { Widget } ) { const dates = useSelect( ( select ) => select( CORE_USER ).getDateRangeDates( { offsetDays: DATE_RANGE_OFFSET, @@ -54,18 +53,14 @@ export default function NewVisitorsWidget( { Widget, WidgetNull } ) { const reportOptions = { ...dates, dimensions: [ 'newVsReturning' ], - metrics: [ - { - name: 'activeUsers', - }, - ], + metrics: [ { name: 'activeUsers' } ], }; const report = useInViewSelect( ( select ) => select( MODULES_ANALYTICS_4 ).getReport( reportOptions ) ); - const loading = useSelect( + const loading = useInViewSelect( ( select ) => ! select( MODULES_ANALYTICS_4 ).hasFinishedResolution( 'getReport', @@ -85,14 +80,10 @@ export default function NewVisitorsWidget( { Widget, WidgetNull } ) { parseInt( report?.rows?.[ 2 ]?.metricValues[ 0 ]?.value, 10 ) || 0; const compareTotalVisitors = compareNewVisitors + compareReturningVisitors; - if ( keyMetricsWidgetHidden !== false ) { - return ; - } - return ( { const setupRegistry = ( registry ) => { diff --git a/assets/js/util/i18n.js b/assets/js/util/i18n.js index c887048082e..a7b806f201c 100644 --- a/assets/js/util/i18n.js +++ b/assets/js/util/i18n.js @@ -245,6 +245,40 @@ export const readableLargeNumber = ( number ) => { } ); }; +/** + * Parses formatting options and returns an object with options for selected formatting. + * + * @since n.e.x.t + * + * @param {(Intl.NumberFormatOptions|string)} options Formatting options or unit shorthand. Possible shorthand values are '%', 's', or a currency code. + * @return {Object} Formatting options. + */ +export function expandNumFmtOptions( options ) { + let formatOptions = {}; + + // Expand shorthand values for units. + if ( '%' === options ) { + formatOptions = { + style: 'percent', + maximumFractionDigits: 2, + }; + } else if ( 's' === options ) { + formatOptions = { + style: 'duration', + unitDisplay: 'narrow', + }; + } else if ( !! options && typeof options === 'string' ) { + formatOptions = { + style: 'currency', + currency: options, + }; + } else if ( isPlainObject( options ) ) { + formatOptions = { ...options }; + } + + return formatOptions; +} + /** * Formats a number with unit using the JS Internationalization Number Format API. * @@ -262,7 +296,7 @@ export const readableLargeNumber = ( number ) => { * or a currency code. * @return {string} The formatted number. */ -export const numFmt = ( number, options = {} ) => { +export function numFmt( number, options = {} ) { // Cast parsable values to numeric types. number = isFinite( number ) ? number : Number( number ); @@ -272,38 +306,19 @@ export const numFmt = ( number, options = {} ) => { number = 0; } - let formatOptions = {}; - - // Expand shorthand values for units. - if ( '%' === options ) { - formatOptions = { - style: 'percent', - maximumFractionDigits: 2, - }; - } else if ( 's' === options ) { - return durationFormat( number, { - unitDisplay: 'narrow', - } ); - } else if ( !! options && typeof options === 'string' ) { - formatOptions = { - style: 'currency', - currency: options, - }; - } else if ( isPlainObject( options ) ) { - formatOptions = { ...options }; - } - - // Note: `metric` is our custom, default style. - const { style = 'metric' } = formatOptions; + const formatOptions = expandNumFmtOptions( options ); + const { style = 'metric' } = formatOptions; // Note: `metric` is our custom, default style. if ( 'metric' === style ) { return readableLargeNumber( number ); - } else if ( 'duration' === style ) { - return durationFormat( number, options ); + } + + if ( 'duration' === style ) { + return durationFormat( number, formatOptions ); } return numberFormat( number, formatOptions ); -}; +} // Warn once for a given message. const warnOnce = memize( console.warn ); // eslint-disable-line no-console diff --git a/assets/js/util/index.js b/assets/js/util/index.js index b2b93bb913b..06c557449da 100644 --- a/assets/js/util/index.js +++ b/assets/js/util/index.js @@ -19,7 +19,7 @@ /** * External dependencies */ -import { isFinite, unescape } from 'lodash'; +import { unescape } from 'lodash'; /** * Internal dependencies @@ -84,21 +84,20 @@ export const getTimeInSeconds = ( period ) => { * @param {number} current The current value. * @return {(number|null)} The percent change. Null if the input or output is invalid. */ -export const calculateChange = ( previous, current ) => { +export function calculateChange( previous, current ) { // Prevent divide by zero errors. - if ( '0' === previous || 0 === previous || isNaN( previous ) ) { + if ( '0' === previous || 0 === previous || Number.isNaN( previous ) ) { return null; } - const change = ( current - previous ) / previous; - // Avoid NaN at all costs. - if ( isNaN( change ) || ! isFinite( change ) ) { + const change = ( current - previous ) / previous; + if ( Number.isNaN( change ) || ! Number.isFinite( change ) ) { return null; } return change; -}; +} /** * Verifies whether JSON is valid. diff --git a/tests/backstop/reference/google-site-kit_Components_KeyMetrics_Widgets_NewVisitorsWidget_Ready_0_document_0_small.png b/tests/backstop/reference/google-site-kit_Components_KeyMetrics_Widgets_NewVisitorsWidget_Ready_0_document_0_small.png deleted file mode 100644 index e0d4e28c0f7..00000000000 Binary files a/tests/backstop/reference/google-site-kit_Components_KeyMetrics_Widgets_NewVisitorsWidget_Ready_0_document_0_small.png and /dev/null differ diff --git a/tests/backstop/reference/google-site-kit_Components_KeyMetrics_Widgets_NewVisitorsWidget_Ready_0_document_1_medium.png b/tests/backstop/reference/google-site-kit_Components_KeyMetrics_Widgets_NewVisitorsWidget_Ready_0_document_1_medium.png deleted file mode 100644 index 7781c3e6c43..00000000000 Binary files a/tests/backstop/reference/google-site-kit_Components_KeyMetrics_Widgets_NewVisitorsWidget_Ready_0_document_1_medium.png and /dev/null differ diff --git a/tests/backstop/reference/google-site-kit_Components_KeyMetrics_Widgets_NewVisitorsWidget_Ready_0_document_2_large.png b/tests/backstop/reference/google-site-kit_Components_KeyMetrics_Widgets_NewVisitorsWidget_Ready_0_document_2_large.png deleted file mode 100644 index 29271269df6..00000000000 Binary files a/tests/backstop/reference/google-site-kit_Components_KeyMetrics_Widgets_NewVisitorsWidget_Ready_0_document_2_large.png and /dev/null differ diff --git a/tests/backstop/reference/google-site-kit_Components_KeyMetrics_Widgets_NewVisitorsWidget_ZeroData_0_document_0_small.png b/tests/backstop/reference/google-site-kit_Components_KeyMetrics_Widgets_NewVisitorsWidget_ZeroData_0_document_0_small.png deleted file mode 100644 index 2a07af3d95f..00000000000 Binary files a/tests/backstop/reference/google-site-kit_Components_KeyMetrics_Widgets_NewVisitorsWidget_ZeroData_0_document_0_small.png and /dev/null differ diff --git a/tests/backstop/reference/google-site-kit_Components_KeyMetrics_Widgets_NewVisitorsWidget_ZeroData_0_document_1_medium.png b/tests/backstop/reference/google-site-kit_Components_KeyMetrics_Widgets_NewVisitorsWidget_ZeroData_0_document_1_medium.png deleted file mode 100644 index 4e47199cace..00000000000 Binary files a/tests/backstop/reference/google-site-kit_Components_KeyMetrics_Widgets_NewVisitorsWidget_ZeroData_0_document_1_medium.png and /dev/null differ diff --git a/tests/backstop/reference/google-site-kit_Components_KeyMetrics_Widgets_NewVisitorsWidget_ZeroData_0_document_2_large.png b/tests/backstop/reference/google-site-kit_Components_KeyMetrics_Widgets_NewVisitorsWidget_ZeroData_0_document_2_large.png deleted file mode 100644 index 4fc011175e4..00000000000 Binary files a/tests/backstop/reference/google-site-kit_Components_KeyMetrics_Widgets_NewVisitorsWidget_ZeroData_0_document_2_large.png and /dev/null differ diff --git a/tests/backstop/reference/google-site-kit_KeyMetrics_LoyalVisitors_Ready_0_document_0_small.png b/tests/backstop/reference/google-site-kit_KeyMetrics_LoyalVisitors_Ready_0_document_0_small.png new file mode 100644 index 00000000000..f758384edb1 Binary files /dev/null and b/tests/backstop/reference/google-site-kit_KeyMetrics_LoyalVisitors_Ready_0_document_0_small.png differ diff --git a/tests/backstop/reference/google-site-kit_KeyMetrics_LoyalVisitors_Ready_0_document_1_medium.png b/tests/backstop/reference/google-site-kit_KeyMetrics_LoyalVisitors_Ready_0_document_1_medium.png new file mode 100644 index 00000000000..07ea76dc1d4 Binary files /dev/null and b/tests/backstop/reference/google-site-kit_KeyMetrics_LoyalVisitors_Ready_0_document_1_medium.png differ diff --git a/tests/backstop/reference/google-site-kit_KeyMetrics_LoyalVisitors_Ready_0_document_2_large.png b/tests/backstop/reference/google-site-kit_KeyMetrics_LoyalVisitors_Ready_0_document_2_large.png new file mode 100644 index 00000000000..6f342f13621 Binary files /dev/null and b/tests/backstop/reference/google-site-kit_KeyMetrics_LoyalVisitors_Ready_0_document_2_large.png differ diff --git a/tests/backstop/reference/google-site-kit_KeyMetrics_LoyalVisitors_ZeroData_0_document_0_small.png b/tests/backstop/reference/google-site-kit_KeyMetrics_LoyalVisitors_ZeroData_0_document_0_small.png new file mode 100644 index 00000000000..79805ffd81c Binary files /dev/null and b/tests/backstop/reference/google-site-kit_KeyMetrics_LoyalVisitors_ZeroData_0_document_0_small.png differ diff --git a/tests/backstop/reference/google-site-kit_KeyMetrics_LoyalVisitors_ZeroData_0_document_1_medium.png b/tests/backstop/reference/google-site-kit_KeyMetrics_LoyalVisitors_ZeroData_0_document_1_medium.png new file mode 100644 index 00000000000..e1f0fac2365 Binary files /dev/null and b/tests/backstop/reference/google-site-kit_KeyMetrics_LoyalVisitors_ZeroData_0_document_1_medium.png differ diff --git a/tests/backstop/reference/google-site-kit_KeyMetrics_LoyalVisitors_ZeroData_0_document_2_large.png b/tests/backstop/reference/google-site-kit_KeyMetrics_LoyalVisitors_ZeroData_0_document_2_large.png new file mode 100644 index 00000000000..7db3f03873f Binary files /dev/null and b/tests/backstop/reference/google-site-kit_KeyMetrics_LoyalVisitors_ZeroData_0_document_2_large.png differ diff --git a/tests/backstop/reference/google-site-kit_Components_KeyMetrics_Widgets_MetricTileNumeric_Negative_0_document_0_small.png b/tests/backstop/reference/google-site-kit_KeyMetrics_MetricTileNumeric_Negative_0_document_0_small.png similarity index 100% rename from tests/backstop/reference/google-site-kit_Components_KeyMetrics_Widgets_MetricTileNumeric_Negative_0_document_0_small.png rename to tests/backstop/reference/google-site-kit_KeyMetrics_MetricTileNumeric_Negative_0_document_0_small.png diff --git a/tests/backstop/reference/google-site-kit_Components_KeyMetrics_Widgets_MetricTileNumeric_Negative_0_document_1_medium.png b/tests/backstop/reference/google-site-kit_KeyMetrics_MetricTileNumeric_Negative_0_document_1_medium.png similarity index 100% rename from tests/backstop/reference/google-site-kit_Components_KeyMetrics_Widgets_MetricTileNumeric_Negative_0_document_1_medium.png rename to tests/backstop/reference/google-site-kit_KeyMetrics_MetricTileNumeric_Negative_0_document_1_medium.png diff --git a/tests/backstop/reference/google-site-kit_Components_KeyMetrics_Widgets_MetricTileNumeric_Negative_0_document_2_large.png b/tests/backstop/reference/google-site-kit_KeyMetrics_MetricTileNumeric_Negative_0_document_2_large.png similarity index 100% rename from tests/backstop/reference/google-site-kit_Components_KeyMetrics_Widgets_MetricTileNumeric_Negative_0_document_2_large.png rename to tests/backstop/reference/google-site-kit_KeyMetrics_MetricTileNumeric_Negative_0_document_2_large.png diff --git a/tests/backstop/reference/google-site-kit_Components_KeyMetrics_Widgets_MetricTileNumeric_Positive_0_document_0_small.png b/tests/backstop/reference/google-site-kit_KeyMetrics_MetricTileNumeric_Positive_0_document_0_small.png similarity index 100% rename from tests/backstop/reference/google-site-kit_Components_KeyMetrics_Widgets_MetricTileNumeric_Positive_0_document_0_small.png rename to tests/backstop/reference/google-site-kit_KeyMetrics_MetricTileNumeric_Positive_0_document_0_small.png diff --git a/tests/backstop/reference/google-site-kit_Components_KeyMetrics_Widgets_MetricTileNumeric_Positive_0_document_1_medium.png b/tests/backstop/reference/google-site-kit_KeyMetrics_MetricTileNumeric_Positive_0_document_1_medium.png similarity index 100% rename from tests/backstop/reference/google-site-kit_Components_KeyMetrics_Widgets_MetricTileNumeric_Positive_0_document_1_medium.png rename to tests/backstop/reference/google-site-kit_KeyMetrics_MetricTileNumeric_Positive_0_document_1_medium.png diff --git a/tests/backstop/reference/google-site-kit_Components_KeyMetrics_Widgets_MetricTileNumeric_Positive_0_document_2_large.png b/tests/backstop/reference/google-site-kit_KeyMetrics_MetricTileNumeric_Positive_0_document_2_large.png similarity index 100% rename from tests/backstop/reference/google-site-kit_Components_KeyMetrics_Widgets_MetricTileNumeric_Positive_0_document_2_large.png rename to tests/backstop/reference/google-site-kit_KeyMetrics_MetricTileNumeric_Positive_0_document_2_large.png diff --git a/tests/backstop/reference/google-site-kit_Components_KeyMetrics_Widgets_MetricTileNumeric_ZeroChange_0_document_0_small.png b/tests/backstop/reference/google-site-kit_KeyMetrics_MetricTileNumeric_ZeroChange_0_document_0_small.png similarity index 100% rename from tests/backstop/reference/google-site-kit_Components_KeyMetrics_Widgets_MetricTileNumeric_ZeroChange_0_document_0_small.png rename to tests/backstop/reference/google-site-kit_KeyMetrics_MetricTileNumeric_ZeroChange_0_document_0_small.png diff --git a/tests/backstop/reference/google-site-kit_Components_KeyMetrics_Widgets_MetricTileNumeric_ZeroChange_0_document_1_medium.png b/tests/backstop/reference/google-site-kit_KeyMetrics_MetricTileNumeric_ZeroChange_0_document_1_medium.png similarity index 100% rename from tests/backstop/reference/google-site-kit_Components_KeyMetrics_Widgets_MetricTileNumeric_ZeroChange_0_document_1_medium.png rename to tests/backstop/reference/google-site-kit_KeyMetrics_MetricTileNumeric_ZeroChange_0_document_1_medium.png diff --git a/tests/backstop/reference/google-site-kit_Components_KeyMetrics_Widgets_MetricTileNumeric_ZeroChange_0_document_2_large.png b/tests/backstop/reference/google-site-kit_KeyMetrics_MetricTileNumeric_ZeroChange_0_document_2_large.png similarity index 100% rename from tests/backstop/reference/google-site-kit_Components_KeyMetrics_Widgets_MetricTileNumeric_ZeroChange_0_document_2_large.png rename to tests/backstop/reference/google-site-kit_KeyMetrics_MetricTileNumeric_ZeroChange_0_document_2_large.png diff --git a/tests/backstop/reference/google-site-kit_KeyMetrics_NewVisitors_Ready_0_document_0_small.png b/tests/backstop/reference/google-site-kit_KeyMetrics_NewVisitors_Ready_0_document_0_small.png new file mode 100644 index 00000000000..1968b913837 Binary files /dev/null and b/tests/backstop/reference/google-site-kit_KeyMetrics_NewVisitors_Ready_0_document_0_small.png differ diff --git a/tests/backstop/reference/google-site-kit_KeyMetrics_NewVisitors_Ready_0_document_1_medium.png b/tests/backstop/reference/google-site-kit_KeyMetrics_NewVisitors_Ready_0_document_1_medium.png new file mode 100644 index 00000000000..08017f34aa5 Binary files /dev/null and b/tests/backstop/reference/google-site-kit_KeyMetrics_NewVisitors_Ready_0_document_1_medium.png differ diff --git a/tests/backstop/reference/google-site-kit_KeyMetrics_NewVisitors_Ready_0_document_2_large.png b/tests/backstop/reference/google-site-kit_KeyMetrics_NewVisitors_Ready_0_document_2_large.png new file mode 100644 index 00000000000..cc39be18ae9 Binary files /dev/null and b/tests/backstop/reference/google-site-kit_KeyMetrics_NewVisitors_Ready_0_document_2_large.png differ diff --git a/tests/backstop/reference/google-site-kit_KeyMetrics_NewVisitors_ZeroData_0_document_0_small.png b/tests/backstop/reference/google-site-kit_KeyMetrics_NewVisitors_ZeroData_0_document_0_small.png new file mode 100644 index 00000000000..2805934a49d Binary files /dev/null and b/tests/backstop/reference/google-site-kit_KeyMetrics_NewVisitors_ZeroData_0_document_0_small.png differ diff --git a/tests/backstop/reference/google-site-kit_KeyMetrics_NewVisitors_ZeroData_0_document_1_medium.png b/tests/backstop/reference/google-site-kit_KeyMetrics_NewVisitors_ZeroData_0_document_1_medium.png new file mode 100644 index 00000000000..e12b32f9e04 Binary files /dev/null and b/tests/backstop/reference/google-site-kit_KeyMetrics_NewVisitors_ZeroData_0_document_1_medium.png differ diff --git a/tests/backstop/reference/google-site-kit_KeyMetrics_NewVisitors_ZeroData_0_document_2_large.png b/tests/backstop/reference/google-site-kit_KeyMetrics_NewVisitors_ZeroData_0_document_2_large.png new file mode 100644 index 00000000000..d2ba7639ddc Binary files /dev/null and b/tests/backstop/reference/google-site-kit_KeyMetrics_NewVisitors_ZeroData_0_document_2_large.png differ diff --git a/tests/backstop/reference/google-site-kit_Global_KeyMetricsSetupCTAWidget_0_document_0_small.png b/tests/backstop/reference/google-site-kit_KeyMetrics_SetupCTAWidget_0_document_0_small.png similarity index 100% rename from tests/backstop/reference/google-site-kit_Global_KeyMetricsSetupCTAWidget_0_document_0_small.png rename to tests/backstop/reference/google-site-kit_KeyMetrics_SetupCTAWidget_0_document_0_small.png diff --git a/tests/backstop/reference/google-site-kit_Global_KeyMetricsSetupCTAWidget_0_document_1_medium.png b/tests/backstop/reference/google-site-kit_KeyMetrics_SetupCTAWidget_0_document_1_medium.png similarity index 100% rename from tests/backstop/reference/google-site-kit_Global_KeyMetricsSetupCTAWidget_0_document_1_medium.png rename to tests/backstop/reference/google-site-kit_KeyMetrics_SetupCTAWidget_0_document_1_medium.png diff --git a/tests/backstop/reference/google-site-kit_Global_KeyMetricsSetupCTAWidget_0_document_2_large.png b/tests/backstop/reference/google-site-kit_KeyMetrics_SetupCTAWidget_0_document_2_large.png similarity index 100% rename from tests/backstop/reference/google-site-kit_Global_KeyMetricsSetupCTAWidget_0_document_2_large.png rename to tests/backstop/reference/google-site-kit_KeyMetrics_SetupCTAWidget_0_document_2_large.png