- { 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