Commit 434fe263e3 for woocommerce

commit 434fe263e339dd6e8d712801cd496d2eade6f88b
Author: Chi-Hsuan Huang <chihsuan.tw@gmail.com>
Date:   Fri Dec 5 11:44:12 2025 +0900

    Add scheduled updates promotion admin notice (#62225)

    * Add Scheduled Updates Promotion Notice component and user preference handling

    - Introduced a new ScheduledUpdatesPromotionNotice component to inform users about scheduled updates in analytics.
    - Updated user preferences to track dismissal of the promotion notice.
    - Integrated the notice into the analytics report and dashboard components.
    - Added necessary type definitions and updated the analytics PHP backend to support the new feature.

    * Update default setting for analytics data import to null for new sites

    * Add changelog

    * Add changelog

    * Fix notice logic

    * Use explicit check

    * Update plugins/woocommerce/src/Internal/Admin/Settings.php

    Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

    * Add tests

    * Refactor report component wrapping logic in useReports

    - Updated the getReports function to create a new array of wrapped reports, preventing mutation of the original reports array.
    - Introduced a WrappedComponent function to include the ScheduledUpdatesPromotionNotice, enhancing debugging with a displayName property.
    - Ensured the wrapped reports are returned from the getReports function.

    * Fix lint

    ---------

    Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

diff --git a/packages/js/data/changelog/wooa7s-795-onboarding-scheduled-updates-promotion-notices b/packages/js/data/changelog/wooa7s-795-onboarding-scheduled-updates-promotion-notices
new file mode 100644
index 0000000000..6933cc745d
--- /dev/null
+++ b/packages/js/data/changelog/wooa7s-795-onboarding-scheduled-updates-promotion-notices
@@ -0,0 +1,4 @@
+Significance: patch
+Type: update
+
+Update UserPreferences type to include scheduled_updates_promotion_notice_dismissed field
diff --git a/packages/js/data/src/user/types.ts b/packages/js/data/src/user/types.ts
index 90b5dbb39e..1cc6e5a2b7 100644
--- a/packages/js/data/src/user/types.ts
+++ b/packages/js/data/src/user/types.ts
@@ -34,6 +34,7 @@ export type UserPreferences = {
 	};
 	launch_your_store_tour_hidden?: 'yes' | 'no' | '';
 	coming_soon_banner_dismissed?: 'yes' | 'no' | '';
+	scheduled_updates_promotion_notice_dismissed?: 'yes' | 'no' | '';
 };

 export type WoocommerceMeta = {
diff --git a/plugins/woocommerce/changelog/wooa7s-795-onboarding-scheduled-updates-promotion-notices b/plugins/woocommerce/changelog/wooa7s-795-onboarding-scheduled-updates-promotion-notices
new file mode 100644
index 0000000000..73701c74c6
--- /dev/null
+++ b/plugins/woocommerce/changelog/wooa7s-795-onboarding-scheduled-updates-promotion-notices
@@ -0,0 +1,4 @@
+Significance: minor
+Type: add
+
+Add scheduled updates promotion notices
diff --git a/plugins/woocommerce/client/admin/client/analytics/components/index.js b/plugins/woocommerce/client/admin/client/analytics/components/index.js
index 4ee3476b0b..ab4b62ec06 100644
--- a/plugins/woocommerce/client/admin/client/analytics/components/index.js
+++ b/plugins/woocommerce/client/admin/client/analytics/components/index.js
@@ -1,3 +1,4 @@
 export { default as ReportChart } from './report-chart';
 export { default as ReportSummary } from './report-summary';
 export { default as ReportTable } from './report-table';
+export { default as ScheduledUpdatesPromotionNotice } from './scheduled-updates-promotion-notice';
diff --git a/plugins/woocommerce/client/admin/client/analytics/components/scheduled-updates-promotion-notice/index.tsx b/plugins/woocommerce/client/admin/client/analytics/components/scheduled-updates-promotion-notice/index.tsx
new file mode 100644
index 0000000000..22cb447e2a
--- /dev/null
+++ b/plugins/woocommerce/client/admin/client/analytics/components/scheduled-updates-promotion-notice/index.tsx
@@ -0,0 +1,80 @@
+/**
+ * External dependencies
+ */
+import { getAdminLink } from '@woocommerce/settings';
+import { __ } from '@wordpress/i18n';
+import { useSettings, useUserPreferences } from '@woocommerce/data';
+import { createInterpolateElement } from '@wordpress/element';
+import { Button } from '@wordpress/components';
+import { recordEvent } from '@woocommerce/tracks';
+
+const IMMEDIATE_IMPORT_OPTION = 'woocommerce_analytics_immediate_import';
+
+export default function ScheduledUpdatesPromotionNotice() {
+	// Get settings to check option value (hooks must be called before early returns)
+	const settings = useSettings( 'wc_admin', [ 'wcAdminSettings' ] );
+	const wcAdminSettings = (
+		settings as { wcAdminSettings?: Record< string, string > }
+	 )?.wcAdminSettings;
+
+	const { updateUserPreferences, ...userData } = useUserPreferences();
+
+	// Check if feature flag is enabled
+	if ( ! window.wcAdminFeatures?.[ 'analytics-scheduled-import' ] ) {
+		return null;
+	}
+
+	const optionValue = wcAdminSettings?.[ IMMEDIATE_IMPORT_OPTION ];
+	// No need to show notice if option is already set.
+	if ( optionValue === 'no' || optionValue === 'yes' ) {
+		return null;
+	}
+
+	const isDismissed =
+		userData?.scheduled_updates_promotion_notice_dismissed === 'yes';
+
+	if ( isDismissed ) {
+		return null;
+	}
+
+	const onDismiss = () => {
+		updateUserPreferences( {
+			scheduled_updates_promotion_notice_dismissed: 'yes',
+		} );
+		recordEvent( 'scheduled_updates_promotion_notice_dismissed' );
+	};
+
+	return (
+		<div className="notice notice-info is-dismissible">
+			<Button
+				variant="tertiary"
+				aria-label={ __( 'Dismiss this notice.', 'woocommerce' ) }
+				className="woocommerce-message-close notice-dismiss"
+				onClick={ onDismiss }
+			/>
+
+			<p>
+				{ createInterpolateElement(
+					/* translators: <a> is a link to the analytics settings page. */
+					__(
+						'Analytics now supports scheduled updates, providing improved performance. Enable it in <a>Settings</a>.',
+						'woocommerce'
+					),
+					{
+						a: (
+							<a
+								href={ getAdminLink(
+									'admin.php?page=wc-admin&path=/analytics/settings'
+								) }
+								aria-label={ __(
+									'Analytics settings',
+									'woocommerce'
+								) }
+							/>
+						),
+					}
+				) }
+			</p>
+		</div>
+	);
+}
diff --git a/plugins/woocommerce/client/admin/client/analytics/components/scheduled-updates-promotion-notice/test/index.tsx b/plugins/woocommerce/client/admin/client/analytics/components/scheduled-updates-promotion-notice/test/index.tsx
new file mode 100644
index 0000000000..66ce3d6256
--- /dev/null
+++ b/plugins/woocommerce/client/admin/client/analytics/components/scheduled-updates-promotion-notice/test/index.tsx
@@ -0,0 +1,421 @@
+/* eslint-disable @typescript-eslint/no-explicit-any */
+/**
+ * External dependencies
+ */
+import React from 'react';
+import { createElement } from '@wordpress/element';
+import { render, screen } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
+import { recordEvent } from '@woocommerce/tracks';
+import { useSettings, useUserPreferences } from '@woocommerce/data';
+import { getAdminLink } from '@woocommerce/settings';
+
+/**
+ * Internal dependencies
+ */
+import ScheduledUpdatesPromotionNotice from '../index';
+
+// Mock dependencies
+jest.mock( '@woocommerce/tracks', () => ( {
+	recordEvent: jest.fn(),
+} ) );
+
+jest.mock( '@woocommerce/data', () => {
+	const originalModule = jest.requireActual( '@woocommerce/data' );
+	return {
+		...originalModule,
+		useSettings: jest.fn(),
+		useUserPreferences: jest.fn(),
+	};
+} );
+
+jest.mock( '@woocommerce/settings', () => ( {
+	getAdminLink: jest.fn( ( path: string ) => `http://example.com/${ path }` ),
+} ) );
+
+const mockUseSettings = useSettings as jest.MockedFunction<
+	typeof useSettings
+>;
+const mockUseUserPreferences = useUserPreferences as jest.MockedFunction<
+	typeof useUserPreferences
+>;
+const mockRecordEvent = recordEvent as jest.MockedFunction<
+	typeof recordEvent
+>;
+const mockGetAdminLink = getAdminLink as jest.MockedFunction<
+	typeof getAdminLink
+>;
+
+describe( 'ScheduledUpdatesPromotionNotice', () => {
+	beforeEach( () => {
+		jest.clearAllMocks();
+
+		// Set up default feature flag
+		( window as any ).wcAdminFeatures = {
+			'analytics-scheduled-import': true,
+		};
+
+		// Set up default mocks
+		mockUseSettings.mockReturnValue( {
+			wcAdminSettings: {},
+		} as unknown as ReturnType< typeof useSettings > );
+
+		mockUseUserPreferences.mockReturnValue( {
+			updateUserPreferences: jest.fn(),
+			scheduled_updates_promotion_notice_dismissed: undefined,
+			isRequesting: false,
+		} as unknown as ReturnType< typeof useUserPreferences > );
+
+		mockGetAdminLink.mockReturnValue(
+			'http://example.com/admin.php?page=wc-admin&path=/analytics/settings'
+		);
+	} );
+
+	describe( 'Feature flag check', () => {
+		test( 'should not render when feature flag is disabled', () => {
+			( window as any ).wcAdminFeatures = {
+				'analytics-scheduled-import': false,
+			};
+
+			const { container } = render( <ScheduledUpdatesPromotionNotice /> );
+
+			expect( container.firstChild ).toBeNull();
+		} );
+
+		test( 'should not render when feature flag is undefined', () => {
+			( window as any ).wcAdminFeatures = {};
+
+			const { container } = render( <ScheduledUpdatesPromotionNotice /> );
+
+			expect( container.firstChild ).toBeNull();
+		} );
+
+		test( 'should render when feature flag is enabled', () => {
+			( window as any ).wcAdminFeatures = {
+				'analytics-scheduled-import': true,
+			};
+
+			render( <ScheduledUpdatesPromotionNotice /> );
+
+			expect(
+				screen.getByText( ( content, element ) => {
+					const textContent = element?.textContent || '';
+					return (
+						element?.tagName.toLowerCase() === 'p' &&
+						textContent.includes(
+							'Analytics now supports scheduled updates, providing improved performance. Enable it in'
+						) &&
+						textContent.includes( 'Settings' )
+					);
+				} )
+			).toBeInTheDocument();
+		} );
+	} );
+
+	describe( 'Option value check', () => {
+		test( 'should not render when option is set to "yes"', () => {
+			mockUseSettings.mockReturnValue( {
+				wcAdminSettings: {
+					woocommerce_analytics_immediate_import: 'yes',
+				},
+			} as unknown as ReturnType< typeof useSettings > );
+
+			const { container } = render( <ScheduledUpdatesPromotionNotice /> );
+
+			expect( container.firstChild ).toBeNull();
+		} );
+
+		test( 'should not render when option is set to "no"', () => {
+			mockUseSettings.mockReturnValue( {
+				wcAdminSettings: {
+					woocommerce_analytics_immediate_import: 'no',
+				},
+			} as unknown as ReturnType< typeof useSettings > );
+
+			const { container } = render( <ScheduledUpdatesPromotionNotice /> );
+
+			expect( container.firstChild ).toBeNull();
+		} );
+
+		test( 'should render when option is undefined', () => {
+			mockUseSettings.mockReturnValue( {
+				wcAdminSettings: {},
+			} as unknown as ReturnType< typeof useSettings > );
+
+			render( <ScheduledUpdatesPromotionNotice /> );
+
+			expect(
+				screen.getByText( ( content, element ) => {
+					const textContent = element?.textContent || '';
+					return (
+						element?.tagName.toLowerCase() === 'p' &&
+						textContent.includes(
+							'Analytics now supports scheduled updates, providing improved performance. Enable it in'
+						) &&
+						textContent.includes( 'Settings' )
+					);
+				} )
+			).toBeInTheDocument();
+		} );
+
+		test( 'should render when option is null', () => {
+			mockUseSettings.mockReturnValue( {
+				wcAdminSettings: {
+					woocommerce_analytics_immediate_import: null,
+				},
+			} as unknown as ReturnType< typeof useSettings > );
+
+			render( <ScheduledUpdatesPromotionNotice /> );
+
+			expect(
+				screen.getByText( ( content, element ) => {
+					const textContent = element?.textContent || '';
+					return (
+						element?.tagName.toLowerCase() === 'p' &&
+						textContent.includes(
+							'Analytics now supports scheduled updates, providing improved performance. Enable it in'
+						) &&
+						textContent.includes( 'Settings' )
+					);
+				} )
+			).toBeInTheDocument();
+		} );
+	} );
+
+	describe( 'Dismissal check', () => {
+		test( 'should not render when notice is dismissed', () => {
+			mockUseUserPreferences.mockReturnValue( {
+				updateUserPreferences: jest.fn(),
+				scheduled_updates_promotion_notice_dismissed: 'yes',
+				isRequesting: false,
+			} as unknown as ReturnType< typeof useUserPreferences > );
+
+			const { container } = render( <ScheduledUpdatesPromotionNotice /> );
+
+			expect( container.firstChild ).toBeNull();
+		} );
+
+		test( 'should render when notice is not dismissed', () => {
+			mockUseUserPreferences.mockReturnValue( {
+				updateUserPreferences: jest.fn(),
+				scheduled_updates_promotion_notice_dismissed: undefined,
+				isRequesting: false,
+			} as unknown as ReturnType< typeof useUserPreferences > );
+
+			render( <ScheduledUpdatesPromotionNotice /> );
+
+			expect(
+				screen.getByText( ( content, element ) => {
+					const textContent = element?.textContent || '';
+					return (
+						element?.tagName.toLowerCase() === 'p' &&
+						textContent.includes(
+							'Analytics now supports scheduled updates, providing improved performance. Enable it in'
+						) &&
+						textContent.includes( 'Settings' )
+					);
+				} )
+			).toBeInTheDocument();
+		} );
+	} );
+
+	describe( 'Dismissal functionality', () => {
+		test( 'should call updateUserPreferences when dismiss button is clicked', async () => {
+			const mockUpdateUserPreferences = jest.fn();
+			mockUseUserPreferences.mockReturnValue( {
+				updateUserPreferences: mockUpdateUserPreferences,
+				scheduled_updates_promotion_notice_dismissed: undefined,
+				isRequesting: false,
+			} as unknown as ReturnType< typeof useUserPreferences > );
+
+			render( <ScheduledUpdatesPromotionNotice /> );
+
+			const dismissButton = screen.getByLabelText(
+				'Dismiss this notice.'
+			);
+			await userEvent.click( dismissButton );
+
+			expect( mockUpdateUserPreferences ).toHaveBeenCalledWith( {
+				scheduled_updates_promotion_notice_dismissed: 'yes',
+			} );
+		} );
+
+		test( 'should fire tracking event when dismiss button is clicked', async () => {
+			mockUseUserPreferences.mockReturnValue( {
+				updateUserPreferences: jest.fn(),
+				scheduled_updates_promotion_notice_dismissed: undefined,
+				isRequesting: false,
+			} as unknown as ReturnType< typeof useUserPreferences > );
+
+			render( <ScheduledUpdatesPromotionNotice /> );
+
+			const dismissButton = screen.getByLabelText(
+				'Dismiss this notice.'
+			);
+			await userEvent.click( dismissButton );
+
+			expect( mockRecordEvent ).toHaveBeenCalledWith(
+				'scheduled_updates_promotion_notice_dismissed'
+			);
+		} );
+	} );
+
+	describe( 'Link generation', () => {
+		test( 'should generate correct settings link', () => {
+			render( <ScheduledUpdatesPromotionNotice /> );
+
+			const settingsLink = screen.getByLabelText( 'Analytics settings' );
+
+			expect( settingsLink ).toBeInTheDocument();
+			expect( settingsLink ).toHaveAttribute(
+				'href',
+				'http://example.com/admin.php?page=wc-admin&path=/analytics/settings'
+			);
+		} );
+
+		test( 'should call getAdminLink with correct path', () => {
+			render( <ScheduledUpdatesPromotionNotice /> );
+
+			expect( mockGetAdminLink ).toHaveBeenCalledWith(
+				'admin.php?page=wc-admin&path=/analytics/settings'
+			);
+		} );
+	} );
+
+	describe( 'Notice content', () => {
+		test( 'should display correct notice message', () => {
+			render( <ScheduledUpdatesPromotionNotice /> );
+
+			expect(
+				screen.getByText( ( content, element ) => {
+					const textContent = element?.textContent || '';
+					return (
+						element?.tagName.toLowerCase() === 'p' &&
+						textContent.includes(
+							'Analytics now supports scheduled updates, providing improved performance. Enable it in'
+						) &&
+						textContent.includes( 'Settings' )
+					);
+				} )
+			).toBeInTheDocument();
+		} );
+
+		test( 'should have correct CSS classes', () => {
+			const { container } = render( <ScheduledUpdatesPromotionNotice /> );
+
+			const notice = container.querySelector(
+				'.notice.notice-info.is-dismissible'
+			);
+			expect( notice ).toBeInTheDocument();
+		} );
+
+		test( 'should render dismiss button with correct attributes', () => {
+			render( <ScheduledUpdatesPromotionNotice /> );
+
+			const dismissButton = screen.getByLabelText(
+				'Dismiss this notice.'
+			);
+
+			expect( dismissButton ).toBeInTheDocument();
+			expect( dismissButton ).toHaveClass(
+				'woocommerce-message-close',
+				'notice-dismiss'
+			);
+		} );
+	} );
+
+	describe( 'Combined conditions', () => {
+		test( 'should render when all conditions are met', () => {
+			( window as any ).wcAdminFeatures = {
+				'analytics-scheduled-import': true,
+			};
+
+			mockUseSettings.mockReturnValue( {
+				wcAdminSettings: {},
+			} as unknown as ReturnType< typeof useSettings > );
+
+			mockUseUserPreferences.mockReturnValue( {
+				updateUserPreferences: jest.fn(),
+				scheduled_updates_promotion_notice_dismissed: undefined,
+				isRequesting: false,
+			} as unknown as ReturnType< typeof useUserPreferences > );
+
+			render( <ScheduledUpdatesPromotionNotice /> );
+
+			expect(
+				screen.getByText( ( content, element ) => {
+					const textContent = element?.textContent || '';
+					return (
+						element?.tagName.toLowerCase() === 'p' &&
+						textContent.includes(
+							'Analytics now supports scheduled updates, providing improved performance. Enable it in'
+						) &&
+						textContent.includes( 'Settings' )
+					);
+				} )
+			).toBeInTheDocument();
+		} );
+
+		test( 'should not render when feature flag is disabled even if other conditions are met', () => {
+			( window as any ).wcAdminFeatures = {
+				'analytics-scheduled-import': false,
+			};
+
+			mockUseSettings.mockReturnValue( {
+				wcAdminSettings: {},
+			} as unknown as ReturnType< typeof useSettings > );
+
+			mockUseUserPreferences.mockReturnValue( {
+				updateUserPreferences: jest.fn(),
+				scheduled_updates_promotion_notice_dismissed: undefined,
+				isRequesting: false,
+			} as unknown as ReturnType< typeof useUserPreferences > );
+
+			const { container } = render( <ScheduledUpdatesPromotionNotice /> );
+
+			expect( container.firstChild ).toBeNull();
+		} );
+
+		test( 'should not render when option is set even if feature flag is enabled', () => {
+			( window as any ).wcAdminFeatures = {
+				'analytics-scheduled-import': true,
+			};
+
+			mockUseSettings.mockReturnValue( {
+				wcAdminSettings: {
+					woocommerce_analytics_immediate_import: 'yes',
+				},
+			} as unknown as ReturnType< typeof useSettings > );
+
+			mockUseUserPreferences.mockReturnValue( {
+				updateUserPreferences: jest.fn(),
+				scheduled_updates_promotion_notice_dismissed: undefined,
+				isRequesting: false,
+			} as unknown as ReturnType< typeof useUserPreferences > );
+
+			const { container } = render( <ScheduledUpdatesPromotionNotice /> );
+
+			expect( container.firstChild ).toBeNull();
+		} );
+
+		test( 'should not render when dismissed even if feature flag is enabled and option is not set', () => {
+			( window as any ).wcAdminFeatures = {
+				'analytics-scheduled-import': true,
+			};
+
+			mockUseSettings.mockReturnValue( {
+				wcAdminSettings: {},
+			} as unknown as ReturnType< typeof useSettings > );
+
+			mockUseUserPreferences.mockReturnValue( {
+				updateUserPreferences: jest.fn(),
+				scheduled_updates_promotion_notice_dismissed: 'yes',
+				isRequesting: false,
+			} as unknown as ReturnType< typeof useUserPreferences > );
+
+			const { container } = render( <ScheduledUpdatesPromotionNotice /> );
+
+			expect( container.firstChild ).toBeNull();
+		} );
+	} );
+} );
diff --git a/plugins/woocommerce/client/admin/client/analytics/report/use-reports.js b/plugins/woocommerce/client/admin/client/analytics/report/use-reports.js
index 2cc85fb9fa..9b213f98e3 100644
--- a/plugins/woocommerce/client/admin/client/analytics/report/use-reports.js
+++ b/plugins/woocommerce/client/admin/client/analytics/report/use-reports.js
@@ -3,13 +3,14 @@
  */
 import { __ } from '@wordpress/i18n';
 import { applyFilters } from '@wordpress/hooks';
-import { lazy } from '@wordpress/element';
+import { lazy, Fragment } from '@wordpress/element';

 /**
  * Internal dependencies
  */
 import { getAdminSetting } from '~/utils/admin-settings';
 import { useFilterHook } from '~/utils/use-filter-hook';
+import { ScheduledUpdatesPromotionNotice } from '~/analytics/components';

 const RevenueReport = lazy( () =>
 	import( /* webpackChunkName: "analytics-report-revenue" */ './revenue' )
@@ -132,6 +133,32 @@ const getReports = () => {
 		},
 	].filter( Boolean );

+	// Wrap the report component with the scheduled updates promotion notice
+	// Create a new array to avoid mutating the original, which could lead to
+	// multiple wrappings if getReports() is called multiple times.
+	const wrappedReports = reports.map( ( report ) => {
+		const OriginalComponent = report.component;
+
+		function WrappedComponent( props ) {
+			return (
+				<Fragment>
+					<ScheduledUpdatesPromotionNotice />
+					<OriginalComponent { ...props } />
+				</Fragment>
+			);
+		}
+
+		// Add displayName to help with debugging
+		WrappedComponent.displayName = `WithScheduledNotice(${
+			OriginalComponent.displayName || OriginalComponent.name || 'Report'
+		})`;
+
+		return {
+			...report,
+			component: WrappedComponent,
+		};
+	} );
+
 	/**
 	 * An object defining a report page.
 	 *
@@ -148,7 +175,7 @@ const getReports = () => {
 	 * @filter woocommerce_admin_reports_list
 	 * @param {Array.<report>} reports Report pages list.
 	 */
-	return applyFilters( REPORTS_FILTER, reports );
+	return applyFilters( REPORTS_FILTER, wrappedReports );
 };

 export function useReports() {
diff --git a/plugins/woocommerce/client/admin/client/dashboard/index.js b/plugins/woocommerce/client/admin/client/dashboard/index.js
index 3428c00df0..5be57e704a 100644
--- a/plugins/woocommerce/client/admin/client/dashboard/index.js
+++ b/plugins/woocommerce/client/admin/client/dashboard/index.js
@@ -13,6 +13,7 @@ import {
 	OrderAttributionInstallBannerImage,
 } from '~/order-attribution-install-banner';
 import './style.scss';
+import { ScheduledUpdatesPromotionNotice } from '~/analytics/components';

 const CustomizableDashboard = lazy( () =>
 	import( /* webpackChunkName: "customizable-dashboard" */ './customizable' )
@@ -38,6 +39,7 @@ class Dashboard extends Component {
 					bannerImage={ <OrderAttributionInstallBannerImage /> }
 					dismissable
 				/>
+				<ScheduledUpdatesPromotionNotice />
 				<CustomizableDashboard query={ query } path={ path } />
 			</Suspense>
 		);
diff --git a/plugins/woocommerce/client/admin/client/typings/global.d.ts b/plugins/woocommerce/client/admin/client/typings/global.d.ts
index 8ca10394e3..6baeb64f92 100644
--- a/plugins/woocommerce/client/admin/client/typings/global.d.ts
+++ b/plugins/woocommerce/client/admin/client/typings/global.d.ts
@@ -49,6 +49,7 @@ declare global {
 			};
 		};
 		wcAdminFeatures: {
+			'analytics-scheduled-import': boolean;
 			'activity-panels': boolean;
 			analytics: boolean;
 			'coming-soon-newsletter-template': boolean;
diff --git a/plugins/woocommerce/src/Internal/Admin/Analytics.php b/plugins/woocommerce/src/Internal/Admin/Analytics.php
index f706689a19..5f7398173b 100644
--- a/plugins/woocommerce/src/Internal/Admin/Analytics.php
+++ b/plugins/woocommerce/src/Internal/Admin/Analytics.php
@@ -146,6 +146,7 @@ class Analytics {
 				'dashboard_chart_interval',
 				'dashboard_leaderboard_rows',
 				'order_attribution_install_banner_dismissed',
+				'scheduled_updates_promotion_notice_dismissed',
 			)
 		);
 	}
diff --git a/plugins/woocommerce/src/Internal/Admin/Settings.php b/plugins/woocommerce/src/Internal/Admin/Settings.php
index 4e19552cac..ab9333910b 100644
--- a/plugins/woocommerce/src/Internal/Admin/Settings.php
+++ b/plugins/woocommerce/src/Internal/Admin/Settings.php
@@ -356,7 +356,7 @@ class Settings {
 				'label'       => __( 'Updates', 'woocommerce' ),
 				'description' => __( 'Controls how analytics data is imported from orders.', 'woocommerce' ),
 				'type'        => 'radio',
-				'default'     => 'yes', // Default to immediate import for backward compatibility to ensure we don't accidentally change the behavior for existing stores.
+				'default'     => null, // Default to null so we can know if it's a new site or an existing site. New sites will have the option set.
 				'options'     => array(
 					'no'  => __( 'Scheduled (recommended)', 'woocommerce' ),
 					'yes' => __( 'Immediately', 'woocommerce' ),