diff --git a/js/src/components/experience-rating-banner/banner.js b/js/src/components/experience-rating-banner/banner.js
new file mode 100644
index 0000000000..77981b278b
--- /dev/null
+++ b/js/src/components/experience-rating-banner/banner.js
@@ -0,0 +1,185 @@
+/**
+ * External dependencies
+ */
+import { __ } from '@wordpress/i18n';
+import { useDispatch } from '@wordpress/data';
+import { Notice, Icon } from '@wordpress/components';
+import { external as externalIcon } from '@wordpress/icons';
+import { useState, useEffect, useMemo } from '@wordpress/element';
+import { store as preferencesStore } from '@wordpress/preferences';
+
+/**
+ * Internal dependencies
+ */
+import { recordGlaEvent } from '~/utils/tracks';
+import { BANNER_DISMISSED_KEY } from './constants';
+import {
+ REPORT_SOURCE_PAID,
+ PREFERENCES_STORE_NAMESPACE,
+ APP_RATINGS_BANNER_CONTEXT,
+} from '~/constants';
+import AppButton from '~/components/app-button';
+import useMCProductStatistics from '~/hooks/useMCProductStatistics';
+import useProductsReport from '~/pages/reports/products/useProductsReport';
+import FeedbackModal from './feedback-modal';
+import './index.scss';
+
+/**
+ * When the experience rating banner is displayed to the user.
+ *
+ * @event gla_app_ratings_shown
+ * @property {string} context The context in which the event is triggered.
+ */
+
+/**
+ * When the user clicks the "Good" button on the banner.
+ *
+ * @event gla_app_ratings_good_clicked
+ * @property {string} context The context in which the event is triggered.
+ */
+
+/**
+ * When the feedback modal is closed by the user.
+ *
+ * @event gla_app_ratings_close
+ * @property {string} context The context in which the event is triggered.
+ */
+
+/**
+ * When the user clicks the "Need help" button on the banner.
+ *
+ * @event gla_app_ratings_need_help_clicked
+ * @property {string} context The context in which the event is triggered.
+ */
+
+/**
+ * Banner component.
+ *
+ * Displays a dismissible banner asking users to rate their experience with Google for WooCommerce.
+ * Handles user interactions such as clicking "Good", "Need help", and dismissing the banner,
+ * and records corresponding events. Shows a feedback modal when "Good" is clicked.
+ *
+ * @return {JSX.Element|null} The Banner component, or null if dismissed.
+ *
+ * @fires gla_app_ratings_shown When the banner is shown.
+ * @fires gla_app_ratings_good_clicked When the "Good" button is clicked.
+ * @fires gla_app_ratings_close When the feedback modal is closed.
+ * @fires gla_app_ratings_need_help_clicked When the "Need help" button is clicked.
+ */
+const Banner = () => {
+ const { data: statisticsData } = useMCProductStatistics();
+ const { data: productsReport } = useProductsReport( REPORT_SOURCE_PAID );
+ const [ showModal, setShowModal ] = useState( false );
+ const { set } = useDispatch( preferencesStore ) || {};
+
+ const shouldDisplayBanner = useMemo( () => {
+ const statistics = statisticsData?.statistics || {};
+
+ if ( Object.keys( statistics ).length === 0 ) {
+ return false;
+ }
+
+ const totalProducts = Object.values( statistics ).reduce(
+ ( total, value ) => total + value,
+ 0
+ );
+
+ if ( ! totalProducts ) {
+ return false;
+ }
+
+ const notSyncedProducts = statistics.not_synced;
+ const activeProducts = statistics.active;
+ const conversions = productsReport?.totals?.conversions?.value || 0;
+
+ const hasEnoughActiveProducts =
+ ( activeProducts / totalProducts ) * 100 >= 70;
+ const hasAllProductsSynced =
+ notSyncedProducts === 0 && activeProducts > 0;
+ const hasConversions = conversions > 0;
+
+ return (
+ hasEnoughActiveProducts && hasAllProductsSynced && hasConversions
+ );
+ }, [ statisticsData, productsReport ] );
+
+ useEffect( () => {
+ if ( shouldDisplayBanner ) {
+ recordGlaEvent( 'gla_app_ratings_shown', {
+ context: APP_RATINGS_BANNER_CONTEXT,
+ } );
+ }
+ }, [ shouldDisplayBanner ] );
+
+ if ( ! shouldDisplayBanner ) {
+ return null;
+ }
+
+ const handleGoodOnClick = () => {
+ recordGlaEvent( 'gla_app_ratings_good_clicked', {
+ context: APP_RATINGS_BANNER_CONTEXT,
+ } );
+ setShowModal( true );
+ };
+
+ const handleRequestClose = () => {
+ recordGlaEvent( 'gla_app_ratings_close', {
+ context: APP_RATINGS_BANNER_CONTEXT,
+ } );
+ setShowModal( false );
+ };
+
+ const handleNeedHelpOnClick = () => {
+ recordGlaEvent( 'gla_app_ratings_need_help_clicked', {
+ context: APP_RATINGS_BANNER_CONTEXT,
+ } );
+ };
+
+ const dismissBanner = () => {
+ set( PREFERENCES_STORE_NAMESPACE, BANNER_DISMISSED_KEY, true );
+ };
+
+ return (
+
+ { showModal && (
+
+ ) }
+
+
+ { __(
+ 'How was your experience with Google for WooCommerce?',
+ 'google-listings-and-ads'
+ ) }
+
+
+
+
+ { __( 'Good', 'google-listings-and-ads' ) }
+
+
+
}
+ iconPosition="right"
+ iconSize={ 16 }
+ >
+ { __( 'Need help', 'google-listings-and-ads' ) }
+
+
+
+
+ );
+};
+
+export default Banner;
diff --git a/js/src/components/experience-rating-banner/constants.js b/js/src/components/experience-rating-banner/constants.js
new file mode 100644
index 0000000000..de5970d7db
--- /dev/null
+++ b/js/src/components/experience-rating-banner/constants.js
@@ -0,0 +1 @@
+export const BANNER_DISMISSED_KEY = 'experience-rating-banner-dismissed';
diff --git a/js/src/components/experience-rating-banner/index.js b/js/src/components/experience-rating-banner/index.js
index 8ec62d8a3d..10d65b3ff7 100644
--- a/js/src/components/experience-rating-banner/index.js
+++ b/js/src/components/experience-rating-banner/index.js
@@ -1,193 +1,30 @@
-/**
- * External dependencies
- */
-import { Notice, Icon } from '@wordpress/components';
-import { useDispatch } from '@wordpress/data';
-import { useState, useEffect } from '@wordpress/element';
-import { __ } from '@wordpress/i18n';
-import { external as externalIcon } from '@wordpress/icons';
-import { store as preferencesStore } from '@wordpress/preferences';
-
/**
* Internal dependencies
*/
-import AppButton from '../app-button';
-import {
- REPORT_SOURCE_PAID,
- PREFERENCES_STORE_NAMESPACE,
- APP_RATINGS_BANNER_CONTEXT,
-} from '~/constants';
-import useMCProductStatistics from '~/hooks/useMCProductStatistics';
-import useGoogleMCAccount from '~/hooks/useGoogleMCAccount';
-import useProductsReport from '~/pages/reports/products/useProductsReport';
+import Banner from './banner';
import usePreference from '~/hooks/usePreference';
-import FeedbackModal from './feedback-modal';
-import { recordGlaEvent } from '~/utils/tracks';
+import useGoogleAdsAccount from '~/hooks/useGoogleAdsAccount';
+import useGoogleMCAccount from '~/hooks/useGoogleMCAccount';
+import { BANNER_DISMISSED_KEY } from './constants';
import './index.scss';
-const BANNER_DISMISSED_KEY = 'experience-rating-banner-dismissed';
-
-/**
- * When the experience rating banner is displayed to the user.
- *
- * @event gla_app_ratings_shown
- * @property {string} context The context in which the event is triggered.
- */
-
-/**
- * When the user clicks the "Good" button on the banner.
- *
- * @event gla_app_ratings_good_clicked
- * @property {string} context The context in which the event is triggered.
- */
-
-/**
- * When the feedback modal is closed by the user.
- *
- * @event gla_app_ratings_close
- * @property {string} context The context in which the event is triggered.
- */
-
-/**
- * When the user clicks the "Need help" button on the banner.
- *
- * @event gla_app_ratings_need_help_clicked
- * @property {string} context The context in which the event is triggered.
- */
-
/**
* ExperienceRatingBanner component.
*
- * Displays a dismissible banner asking users to rate their experience with Google for WooCommerce.
- * Handles user interactions such as clicking "Good", "Need help", and dismissing the banner,
- * and records corresponding events. Shows a feedback modal when "Good" is clicked.
- *
- * @return {JSX.Element|null} The ExperienceRatingBanner component, or null if dismissed.
+ * Displays a banner asking users to rate their experience with Google for WooCommerce.
*
- * @fires gla_app_ratings_shown When the banner is shown.
- * @fires gla_app_ratings_good_clicked When the "Good" button is clicked.
- * @fires gla_app_ratings_close When the feedback modal is closed.
- * @fires gla_app_ratings_need_help_clicked When the "Need help" button is clicked.
+ * @return {JSX.Element|null} The ExperienceRatingBanner component, or null if dismissed or Ads account is disconnected or the MC account is not ready.
*/
const ExperienceRatingBanner = () => {
- const { data: statisticsData } = useMCProductStatistics();
+ const { hasGoogleAdsConnection } = useGoogleAdsAccount();
const { isReady: isMCAccountReady } = useGoogleMCAccount();
- const { data: productsReport } = useProductsReport( REPORT_SOURCE_PAID );
- const [ showModal, setShowModal ] = useState( false );
- const { set } = useDispatch( preferencesStore );
const isDismissed = usePreference( BANNER_DISMISSED_KEY );
- const statistics = statisticsData?.statistics || {};
-
- const shouldDisplayBanner = () => {
- if ( Object.keys( statistics ).length === 0 ) {
- return false;
- }
-
- const totalProducts = Object.values( statistics ).reduce(
- ( total, value ) => total + value,
- 0
- );
-
- if ( ! totalProducts ) {
- return false;
- }
-
- const notSyncedProducts = statistics.not_synced;
- const activeProducts = statistics.active;
- const conversions = productsReport?.totals?.conversions?.value || 0;
- const hasEnoughActiveProducts =
- ( activeProducts / totalProducts ) * 100 >= 70;
- const hasAllProductsSynced =
- notSyncedProducts === 0 && activeProducts > 0;
- const hasConversions = conversions > 0;
-
- return (
- hasEnoughActiveProducts &&
- hasAllProductsSynced &&
- isMCAccountReady &&
- hasConversions
- );
- };
-
- // Fire event when banner is shown.
- useEffect( () => {
- if ( ! isDismissed ) {
- recordGlaEvent( 'gla_app_ratings_shown', {
- context: APP_RATINGS_BANNER_CONTEXT,
- } );
- }
- }, [ isDismissed ] );
-
- if ( ! shouldDisplayBanner() || isDismissed ) {
+ if ( ! hasGoogleAdsConnection || ! isMCAccountReady || isDismissed ) {
return null;
}
- const handleGoodOnClick = () => {
- recordGlaEvent( 'gla_app_ratings_good_clicked', {
- context: APP_RATINGS_BANNER_CONTEXT,
- } );
- setShowModal( true );
- };
-
- const handleRequestClose = () => {
- recordGlaEvent( 'gla_app_ratings_close', {
- context: APP_RATINGS_BANNER_CONTEXT,
- } );
- setShowModal( false );
- };
-
- const handleNeedHelpOnClick = () => {
- recordGlaEvent( 'gla_app_ratings_need_help_clicked', {
- context: APP_RATINGS_BANNER_CONTEXT,
- } );
- };
-
- const dismissBanner = () => {
- set( PREFERENCES_STORE_NAMESPACE, BANNER_DISMISSED_KEY, true );
- };
-
- return (
-
- { showModal && (
-
- ) }
-
-
- { __(
- 'How was your experience with Google for WooCommerce?',
- 'google-listings-and-ads'
- ) }
-
-
-
-
- { __( 'Good', 'google-listings-and-ads' ) }
-
-
-
}
- iconPosition="right"
- iconSize={ 16 }
- >
- { __( 'Need help', 'google-listings-and-ads' ) }
-
-
-
-
- );
+ return ;
};
export default ExperienceRatingBanner;
diff --git a/src/Tracking/README.md b/src/Tracking/README.md
index e58a20181b..bd13bd6194 100644
--- a/src/Tracking/README.md
+++ b/src/Tracking/README.md
@@ -188,23 +188,23 @@ Clicking on the button to disconnect the Google Ads account.
#### Emitters
- [`BillingSetupCard`](../../js/src/components/paid-ads/billing-card/billing-setup-card.js#L39) When the user clicks on the button to set up billing in Google Ads.
-### [`gla_app_ratings_close`](../../js/src/components/experience-rating-banner/index.js#L44)
+### [`gla_app_ratings_close`](../../js/src/components/experience-rating-banner/banner.js#L41)
When the feedback modal is closed by the user.
#### Properties
| name | type | description |
| ---- | ---- | ----------- |
`context` | `string` | The context in which the event is triggered.
#### Emitters
-- [`ExperienceRatingBanner`](../../js/src/components/experience-rating-banner/index.js#L72) When the feedback modal is closed.
+- [`Banner`](../../js/src/components/experience-rating-banner/banner.js#L69) When the feedback modal is closed.
-### [`gla_app_ratings_good_clicked`](../../js/src/components/experience-rating-banner/index.js#L37)
+### [`gla_app_ratings_good_clicked`](../../js/src/components/experience-rating-banner/banner.js#L34)
When the user clicks the "Good" button on the banner.
#### Properties
| name | type | description |
| ---- | ---- | ----------- |
`context` | `string` | The context in which the event is triggered.
#### Emitters
-- [`ExperienceRatingBanner`](../../js/src/components/experience-rating-banner/index.js#L72) When the "Good" button is clicked.
+- [`Banner`](../../js/src/components/experience-rating-banner/banner.js#L69) When the "Good" button is clicked.
### [`gla_app_ratings_maybe_later_clicked`](../../js/src/components/experience-rating-banner/feedback-modal.js#L16)
@@ -215,14 +215,14 @@ When the user clicks the "Good" button on the banner.
#### Emitters
- [`FeedbackModal`](../../js/src/components/experience-rating-banner/feedback-modal.js#L39) Fired when the user clicks the "Maybe later" button.
-### [`gla_app_ratings_need_help_clicked`](../../js/src/components/experience-rating-banner/index.js#L51)
+### [`gla_app_ratings_need_help_clicked`](../../js/src/components/experience-rating-banner/banner.js#L48)
When the user clicks the "Need help" button on the banner.
#### Properties
| name | type | description |
| ---- | ---- | ----------- |
`context` | `string` | The context in which the event is triggered.
#### Emitters
-- [`ExperienceRatingBanner`](../../js/src/components/experience-rating-banner/index.js#L72) When the "Need help" button is clicked.
+- [`Banner`](../../js/src/components/experience-rating-banner/banner.js#L69) When the "Need help" button is clicked.
### [`gla_app_ratings_rate_clicked`](../../js/src/components/experience-rating-banner/feedback-modal.js#L21)
@@ -233,14 +233,14 @@ When the user clicks the "Need help" button on the banner.
#### Emitters
- [`FeedbackModal`](../../js/src/components/experience-rating-banner/feedback-modal.js#L39) Fired when the user clicks the "Rate us" button.
-### [`gla_app_ratings_shown`](../../js/src/components/experience-rating-banner/index.js#L30)
+### [`gla_app_ratings_shown`](../../js/src/components/experience-rating-banner/banner.js#L27)
When the experience rating banner is displayed to the user.
#### Properties
| name | type | description |
| ---- | ---- | ----------- |
`context` | `string` | The context in which the event is triggered.
#### Emitters
-- [`ExperienceRatingBanner`](../../js/src/components/experience-rating-banner/index.js#L72) When the banner is shown.
+- [`Banner`](../../js/src/components/experience-rating-banner/banner.js#L69) When the banner is shown.
### [`gla_attribute_mapping_create_rule`](../../js/src/pages/attribute-mapping/attribute-mapping-rule-modal.js#L32)
Creates the rule successfully