Repository: Automattic/wp-calypso
Pull request #101274: Experiment: emphasize longer term savings v2
Author: login: aneeshd16
Created: 2025-03-13T00:15:57Z | Merged: 2025-03-19T18:16:51Z

<!--
Link a related issue to this PR. If the PR does not immediately resolve the issue,
for example, it requires a separate deployment to production, avoid
using the "fixes" keyword and instead attach the [Status] Fix Inbound label to
the linked issue.
-->

Fixes https://github.com/Automattic/martech/issues/3725

## Proposed Changes

* Implements the "Emphasize Longer Term Savings Experiment v2". Please see pau2Xa-6J7-p2 for more details.
* Also cleans up code from the previous experiment (pbxNRc-4tx-p2) 

## Why are these changes being made?
<!--
It's easy to see what a PR does but much harder to find out why it was made,
particularly when researching old changes in history. Record an explanation of
the motivation behind this change and how it will help.
-->

* Experiment implementation.

## Testing Instructions

<!--
Add as many details as possible to help others reproduce the issue and test the fix.
"Before / After" screenshots can also be very helpful when the change is visual.
-->

* Assign yourself to the treatment variant: 22217-explat-experiment
* Go `/setup/onboarding/plans`. Confirm that the savings badge is shown.
<img width="1686" alt="image" src="https://github.com/user-attachments/assets/874eeddc-8ecb-44ef-a3d8-c3efbb3fe4ef" />

* Go to different flows like `/setup/new-hosted-site/plans`, `/setup/newsletter/plans` or `/start/onboarding-pm/plans` and verify that the savings badge is shown.
* Go to `/plans/:siteslug` and verify that the savings badge is shown.

## Pre-merge Checklist

<!--
Complete applicable items on this checklist **before** merging into trunk. Inapplicable items can be left unchecked.

Both the PR author and reviewer are responsible for ensuring the checklist is completed.
-->

- [ ] Has the general commit checklist been followed? (PCYsg-hS-p2)
- [ ] [Have you written new tests](https://wpcalypso.wordpress.com/devdocs/docs/testing/index.md) for your changes?
- [ ] Have you tested the feature in Simple (P9HQHe-k8-p2), Atomic (P9HQHe-jW-p2), and self-hosted Jetpack sites (PCYsg-g6b-p2)?
- [ ] Have you checked for TypeScript, React or other console errors?
- [ ] Have you used memoizing on expensive computations? More info in [Memoizing with create-selector](https://github.com/Automattic/wp-calypso/blob/trunk/packages/state-utils/src/create-selector/README.md) and [Using memoizing selectors](https://react-redux.js.org/api/hooks#using-memoizing-selectors) and [Our Approach to Data](https://github.com/Automattic/wp-calypso/blob/trunk/docs/our-approach-to-data.md)
- [ ] Have we added the "[Status] String Freeze" label as soon as any new strings were ready for translation (p4TIVU-5Jq-p2)?
    - [ ] For UI changes, have we tested the change in various languages (for example, ES, PT, FR, or DE)? The length of text and words vary significantly between languages. 
- [ ] For changes affecting Jetpack: Have we added the "[Status] Needs Privacy Updates" label if this pull request changes what data or activity we track or use (p4TIVU-aUh-p2)?


Diff:
diff --git a/client/landing/stepper/declarative-flow/internals/steps-repository/unified-plans/unified-plans-step.tsx b/client/landing/stepper/declarative-flow/internals/steps-repository/unified-plans/unified-plans-step.tsx
index d4e171a083a8..2ef68394b6a8 100644
--- a/client/landing/stepper/declarative-flow/internals/steps-repository/unified-plans/unified-plans-step.tsx
+++ b/client/landing/stepper/declarative-flow/internals/steps-repository/unified-plans/unified-plans-step.tsx
@@ -21,7 +21,6 @@ import { SIGNUP_DOMAIN_ORIGIN } from 'calypso/lib/analytics/signup';
 import { triggerGuidesForStep } from 'calypso/lib/guides/trigger-guides-for-step';
 import { buildUpgradeFunction } from 'calypso/lib/signup/step-actions';
 import PlansFeaturesMain from 'calypso/my-sites/plans-features-main';
-import useLongerPlanTermDefaultExperiment from 'calypso/my-sites/plans-features-main/hooks/experiments/use-longer-plan-term-default-experiment';
 import { getStepUrl } from 'calypso/signup/utils';
 import { getDomainFromUrl } from 'calypso/site-profiler/utils/get-valid-url';
 import { useDispatch as reduxUseDispatch, useSelector } from 'calypso/state';
@@ -210,7 +209,6 @@ function UnifiedPlansStep( {
 }: UnifiedPlansStepProps ) {
 	const [ isDesktop, setIsDesktop ] = useState< boolean | undefined >( isDesktopViewport() );
 	const dispatch = reduxUseDispatch();
-	const longerPlanTermDefaultExperiment = useLongerPlanTermDefaultExperiment( flowName );
 	const translate = useTranslate();
 	const initializedSitesBackUrl = useSelector( ( state ) =>
 		getCurrentUserSiteCount( state ) ? '/sites/' : null
@@ -430,14 +428,7 @@ function UnifiedPlansStep( {
 		}
 	}
 
-	const intervalTypeValue =
-		intervalType ||
-		getIntervalType(
-			path,
-			flowName === ONBOARDING_FLOW && longerPlanTermDefaultExperiment?.term
-				? longerPlanTermDefaultExperiment.term
-				: undefined
-		);
+	const intervalTypeValue = intervalType || getIntervalType( path );
 
 	let paidDomainName = domainItem?.meta;
 
diff --git a/client/my-sites/plans-features-main/hooks/experiments/use-longer-plan-term-default-experiment.ts b/client/my-sites/plans-features-main/hooks/experiments/use-longer-plan-term-default-experiment.ts
deleted file mode 100644
index 4ec3f72ac882..000000000000
--- a/client/my-sites/plans-features-main/hooks/experiments/use-longer-plan-term-default-experiment.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-import { ONBOARDING_FLOW } from '@automattic/onboarding';
-import { useExperiment } from 'calypso/lib/explat';
-
-const useTermFromExperimentVariant = (
-	experimentVariant: string | null | undefined
-): string | null => {
-	switch ( experimentVariant ) {
-		case 'default_to_three_year_plans':
-			return '3yearly';
-		case 'default_to_two_year_plans':
-			return '2yearly';
-		default:
-			return null;
-	}
-};
-
-/**
- * Returns:
- * - the term as yearly, 2yearly, 3yearly (etc.) to be used as default in the plans
- * page based on the experiment variant
- * - OR null/undefined if control variant or if the experiment is still loading (Subject to change)
- *
- * This hook although used for the experiment, it can be refactored in the end to
- * define the default term in the grid/plans page.
- *
- */
-const useLongerPlanTermDefaultExperiment = (
-	flowName?: string | null
-): {
-	isLoadingExperiment: boolean;
-	term?: string | null;
-	// TODO: Consider removing this and always return concrete term values (where undefined/null would mean no term savings)
-	isEligibleForTermSavings: boolean;
-} => {
-	// TODO: Figure out how to define explicit types for the experiment assignment
-	// variation names 'default_to_three_year_plans', 'default_to_two_year_plans'
-	// and 'emphasize_savings_only'.
-	const [ isLoadingExperimentAssignment, experimentAssignment ] = useExperiment(
-		'calypso_plans_page_emphasize_longer_plan_savings',
-		{
-			isEligible: flowName === ONBOARDING_FLOW,
-		}
-	);
-	const term = useTermFromExperimentVariant( experimentAssignment?.variationName );
-
-	return {
-		isLoadingExperiment: isLoadingExperimentAssignment,
-		term: isLoadingExperimentAssignment ? undefined : term,
-		isEligibleForTermSavings: !! (
-			experimentAssignment?.variationName && experimentAssignment.variationName !== 'control'
-		),
-	};
-};
-
-export default useLongerPlanTermDefaultExperiment;
diff --git a/client/my-sites/plans-features-main/hooks/use-eligibility-for-term-savings-price-display.ts b/client/my-sites/plans-features-main/hooks/use-eligibility-for-term-savings-price-display.ts
index 905d349ff7c7..dc93ccaa94e2 100644
--- a/client/my-sites/plans-features-main/hooks/use-eligibility-for-term-savings-price-display.ts
+++ b/client/my-sites/plans-features-main/hooks/use-eligibility-for-term-savings-price-display.ts
@@ -12,11 +12,10 @@ import {
 	usePlansFromTypes,
 	usePlanTypesWithIntent,
 } from '@automattic/plans-grid-next';
-import useLongerPlanTermDefaultExperiment from './experiments/use-longer-plan-term-default-experiment';
+import { useExperiment } from 'calypso/lib/explat';
 import useCheckPlanAvailabilityForPurchase from './use-check-plan-availability-for-purchase';
 
-const useEligibilityForTermSavingsPriceDisplay = ( {
-	flowName,
+const useIsAnyGridPlanDiscounted = ( {
 	hiddenPlans,
 	intent,
 	isSubdomainNotGenerated,
@@ -25,9 +24,7 @@ const useEligibilityForTermSavingsPriceDisplay = ( {
 	displayedIntervals,
 	coupon,
 	siteId,
-	isInSignup,
 }: {
-	flowName?: string | null;
 	hiddenPlans?: HiddenPlans;
 	intent?: PlansIntent;
 	isSubdomainNotGenerated?: boolean;
@@ -36,9 +33,7 @@ const useEligibilityForTermSavingsPriceDisplay = ( {
 	displayedIntervals: UrlFriendlyTermType[];
 	coupon?: string;
 	siteId?: number | null;
-	isInSignup?: boolean;
 } ) => {
-	const longerPlanTermDefaultExperiment = useLongerPlanTermDefaultExperiment( flowName );
 	const availablePlanSlugs = usePlansFromTypes( {
 		planTypes: usePlanTypesWithIntent( {
 			intent,
@@ -75,11 +70,50 @@ const useEligibilityForTermSavingsPriceDisplay = ( {
 		false
 	);
 
-	if ( isAnyGridPlanDiscounted ) {
-		return false;
-	}
+	return isAnyGridPlanDiscounted;
+};
+
+const useEligibilityForTermSavingsPriceDisplay = ( {
+	hiddenPlans,
+	intent,
+	isSubdomainNotGenerated,
+	selectedPlan,
+	term,
+	displayedIntervals,
+	coupon,
+	siteId,
+}: {
+	hiddenPlans?: HiddenPlans;
+	intent?: PlansIntent;
+	isSubdomainNotGenerated?: boolean;
+	selectedPlan?: PlanSlug;
+	term: ( typeof TERMS_LIST )[ number ];
+	displayedIntervals: UrlFriendlyTermType[];
+	coupon?: string;
+	siteId?: number | null;
+} ) => {
+	const isAnyGridPlanDiscounted = useIsAnyGridPlanDiscounted( {
+		hiddenPlans,
+		intent,
+		isSubdomainNotGenerated,
+		selectedPlan,
+		term,
+		displayedIntervals,
+		coupon,
+		siteId,
+	} );
+
+	const [ isLoading, experimentAssignment ] = useExperiment(
+		'wpcom_plans_page_emphasize_longer_term_savings',
+		{
+			isEligible: ! isAnyGridPlanDiscounted,
+		}
+	);
 
-	return longerPlanTermDefaultExperiment.isEligibleForTermSavings && isInSignup;
+	return {
+		isEligibleForTermSavingsPriceDisplay: experimentAssignment?.variationName === 'treatment',
+		isLoading,
+	};
 };
 
 export default useEligibilityForTermSavingsPriceDisplay;
diff --git a/client/my-sites/plans-features-main/index.tsx b/client/my-sites/plans-features-main/index.tsx
index 2efd4153cde7..1cc1d52ed343 100644
--- a/client/my-sites/plans-features-main/index.tsx
+++ b/client/my-sites/plans-features-main/index.tsx
@@ -70,7 +70,6 @@ import ComparisonGridToggle from './components/comparison-grid-toggle';
 import PlanUpsellModal from './components/plan-upsell-modal';
 import { useModalResolutionCallback } from './components/plan-upsell-modal/hooks/use-modal-resolution-callback';
 import PlansPageSubheader from './components/plans-page-subheader';
-import useLongerPlanTermDefaultExperiment from './hooks/experiments/use-longer-plan-term-default-experiment';
 import useCheckPlanAvailabilityForPurchase from './hooks/use-check-plan-availability-for-purchase';
 import useDefaultWpcomPlansIntent from './hooks/use-default-wpcom-plans-intent';
 import useEligibilityForTermSavingsPriceDisplay from './hooks/use-eligibility-for-term-savings-price-display';
@@ -245,8 +244,6 @@ const PlansFeaturesMain = ( {
 	const showUpgradeableStorage = config.isEnabled( 'plans/upgradeable-storage' );
 	const getPlanTypeDestination = usePlanTypeDestinationCallback();
 
-	const longerPlanTermDefaultExperiment = useLongerPlanTermDefaultExperiment( flowName );
-
 	const { createWithBigSky } = useSelect(
 		( select ) => ( {
 			createWithBigSky: ( select( ONBOARD_STORE ) as OnboardSelect ).getCreateWithBigSky(),
@@ -407,8 +404,10 @@ const PlansFeaturesMain = ( {
 		hideEnterprisePlan,
 	};
 
-	const enableTermSavingsPriceDisplay = useEligibilityForTermSavingsPriceDisplay( {
-		flowName: flowName,
+	const {
+		isEligibleForTermSavingsPriceDisplay: enableTermSavingsPriceDisplay,
+		isLoading: isLoadingemphasizeLongerTermSavingsExperiment,
+	} = useEligibilityForTermSavingsPriceDisplay( {
 		selectedPlan,
 		hiddenPlans,
 		isSubdomainNotGenerated: ! resolvedSubdomainName.result,
@@ -417,7 +416,6 @@ const PlansFeaturesMain = ( {
 		displayedIntervals: filteredDisplayedIntervals,
 		coupon,
 		siteId,
-		isInSignup,
 	} );
 
 	// we need all the plans that are available to pick for comparison grid (these should extend into plans-ui data store selectors)
@@ -667,7 +665,7 @@ const PlansFeaturesMain = ( {
 			! defaultWpcomPlansIntent || // this may be unnecessary, but just in case
 			! gridPlansForFeaturesGrid ||
 			! gridPlansForComparisonGrid ||
-			longerPlanTermDefaultExperiment.isLoadingExperiment
+			isLoadingemphasizeLongerTermSavingsExperiment
 	);
 
 	const isPlansGridReady = ! isLoadingGridPlans && ! resolvedSubdomainName.isLoading;
diff --git a/client/my-sites/plans-features-main/test/index.jsx b/client/my-sites/plans-features-main/test/index.jsx
index 490859e326bd..24f16bdf33a9 100644
--- a/client/my-sites/plans-features-main/test/index.jsx
+++ b/client/my-sites/plans-features-main/test/index.jsx
@@ -46,12 +46,11 @@ jest.mock( '@automattic/data-stores', () => ( {
 jest.mock( 'calypso/components/data/query-active-promotions', () => jest.fn() );
 jest.mock( 'calypso/components/data/query-products-list', () => jest.fn() );
 
-jest.mock( '../hooks/experiments/use-longer-plan-term-default-experiment', () => () => ( {
-	isLoadingExperiment: false,
+jest.mock( '../hooks/use-eligibility-for-term-savings-price-display', () => () => ( {
+	isEligibleForTermSavingsPriceDisplay: false,
+	isLoading: false,
 } ) );
 
-jest.mock( '../hooks/use-eligibility-for-term-savings-price-display', () => () => false );
-
 import {
 	PLAN_FREE,
 	PLAN_BUSINESS_MONTHLY,


Reviews:
user: login: aneeshd16
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-14T18:44:36Z
user: login: southp
body: Works as described and LGTM. Thanks for including nice clean-up as well :) 
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-17T09:10:21Z
user: login: jeyip
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-17T21:55:37Z
user: login: jeyip
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-17T22:07:41Z
user: login: jeyip
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-17T22:08:06Z
user: login: jeyip
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-17T22:14:20Z
user: login: jeyip
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-17T22:17:06Z

Review comments:
diff_hunk: @@ -75,11 +70,52 @@ const useEligibilityForTermSavingsPriceDisplay = ( {
 		false
 	);
 
-	if ( isAnyGridPlanDiscounted ) {
-		return false;
-	}
+	return isAnyGridPlanDiscounted;
+};
+
+const useEligibilityForTermSavingsPriceDisplay = ( {
+	hiddenPlans,
+	intent,
+	isSubdomainNotGenerated,
+	selectedPlan,
+	term,
+	displayedIntervals,
+	coupon,
+	siteId,
+	isInSignup,
+}: {
+	hiddenPlans?: HiddenPlans;
+	intent?: PlansIntent;
+	isSubdomainNotGenerated?: boolean;
+	selectedPlan?: PlanSlug;
+	term: ( typeof TERMS_LIST )[ number ];
+	displayedIntervals: UrlFriendlyTermType[];
+	coupon?: string;
+	siteId?: number | null;
+	isInSignup?: boolean;
+} ) => {
+	const isAnyGridPlanDiscounted = useIsAnyGridPlanDiscounted( {
+		hiddenPlans,
+		intent,
+		isSubdomainNotGenerated,
+		selectedPlan,
+		term,
+		displayedIntervals,
+		coupon,
+		siteId,
+	} );
+
+	const [ isLoading, experimentAssignment ] = useExperiment(
+		'calypso_plans_page_emphasize_longer_term_savings_v2',
+		{
+			isEligible: isInSignup && ! isAnyGridPlanDiscounted,
+		}
+	);
 
-	return longerPlanTermDefaultExperiment.isEligibleForTermSavings && isInSignup;
path: client/my-sites/plans-features-main/hooks/use-eligibility-for-term-savings-price-display.ts
user: login: aneeshd16
body: In the current implementation, if `isAnyGridPlanDiscounted` is `true` or `isInSignup` is `false`, the user will still be assigned to the experiment, but will not see either experiment variation, skewing the results towards control. I have moved these checks to the `isEligible` param of `useExperiment` so that users who are not eligible will not be assigned.
created_at: 2025-03-14T18:44:36Z
author_association: CONTRIBUTOR
diff_hunk: @@ -75,11 +70,52 @@ const useEligibilityForTermSavingsPriceDisplay = ( {
 		false
 	);
 
-	if ( isAnyGridPlanDiscounted ) {
-		return false;
-	}
+	return isAnyGridPlanDiscounted;
+};
+
+const useEligibilityForTermSavingsPriceDisplay = ( {
+	hiddenPlans,
+	intent,
+	isSubdomainNotGenerated,
+	selectedPlan,
+	term,
+	displayedIntervals,
+	coupon,
+	siteId,
+	isInSignup,
+}: {
+	hiddenPlans?: HiddenPlans;
+	intent?: PlansIntent;
+	isSubdomainNotGenerated?: boolean;
+	selectedPlan?: PlanSlug;
+	term: ( typeof TERMS_LIST )[ number ];
+	displayedIntervals: UrlFriendlyTermType[];
+	coupon?: string;
+	siteId?: number | null;
+	isInSignup?: boolean;
+} ) => {
+	const isAnyGridPlanDiscounted = useIsAnyGridPlanDiscounted( {
+		hiddenPlans,
+		intent,
+		isSubdomainNotGenerated,
+		selectedPlan,
+		term,
+		displayedIntervals,
+		coupon,
+		siteId,
+	} );
+
+	const [ isLoading, experimentAssignment ] = useExperiment(
+		'calypso_plans_page_emphasize_longer_term_savings_v2',
+		{
+			isEligible: isInSignup && ! isAnyGridPlanDiscounted,
+		}
+	);
 
-	return longerPlanTermDefaultExperiment.isEligibleForTermSavings && isInSignup;
path: client/my-sites/plans-features-main/hooks/use-eligibility-for-term-savings-price-display.ts
user: login: jeyip
body: Ah makes sense. Thanks for catching this @aneeshd16 👍  
created_at: 2025-03-17T21:55:37Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,55 +0,0 @@
-import { ONBOARDING_FLOW } from '@automattic/onboarding';
-import { useExperiment } from 'calypso/lib/explat';
-
-const useTermFromExperimentVariant = (
-	experimentVariant: string | null | undefined
-): string | null => {
-	switch ( experimentVariant ) {
-		case 'default_to_three_year_plans':
-			return '3yearly';
-		case 'default_to_two_year_plans':
-			return '2yearly';
-		default:
-			return null;
-	}
-};
-
-/**
- * Returns:
- * - the term as yearly, 2yearly, 3yearly (etc.) to be used as default in the plans
- * page based on the experiment variant
- * - OR null/undefined if control variant or if the experiment is still loading (Subject to change)
- *
- * This hook although used for the experiment, it can be refactored in the end to
path: client/my-sites/plans-features-main/hooks/experiments/use-longer-plan-term-default-experiment.ts
user: login: jeyip
body: `Non-blocking:`

It's been a while so I don't have the clearest memory, but there was some complexity around calculating the default plan term used for the plans grid. This hook was meant to be repurposed to that end after the conclusion of the emphasize longer term plan savings experiment.

It might be worth double-checking if this is still the case.
created_at: 2025-03-17T22:07:41Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,55 +0,0 @@
-import { ONBOARDING_FLOW } from '@automattic/onboarding';
-import { useExperiment } from 'calypso/lib/explat';
-
-const useTermFromExperimentVariant = (
-	experimentVariant: string | null | undefined
-): string | null => {
-	switch ( experimentVariant ) {
-		case 'default_to_three_year_plans':
-			return '3yearly';
-		case 'default_to_two_year_plans':
-			return '2yearly';
-		default:
-			return null;
-	}
-};
-
-/**
- * Returns:
- * - the term as yearly, 2yearly, 3yearly (etc.) to be used as default in the plans
- * page based on the experiment variant
- * - OR null/undefined if control variant or if the experiment is still loading (Subject to change)
- *
- * This hook although used for the experiment, it can be refactored in the end to
path: client/my-sites/plans-features-main/hooks/experiments/use-longer-plan-term-default-experiment.ts
user: login: jeyip
body: I'll create an issue for this before I sign off.
created_at: 2025-03-17T22:08:06Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,55 +0,0 @@
-import { ONBOARDING_FLOW } from '@automattic/onboarding';
-import { useExperiment } from 'calypso/lib/explat';
-
-const useTermFromExperimentVariant = (
-	experimentVariant: string | null | undefined
-): string | null => {
-	switch ( experimentVariant ) {
-		case 'default_to_three_year_plans':
-			return '3yearly';
-		case 'default_to_two_year_plans':
-			return '2yearly';
-		default:
-			return null;
-	}
-};
-
-/**
- * Returns:
- * - the term as yearly, 2yearly, 3yearly (etc.) to be used as default in the plans
- * page based on the experiment variant
- * - OR null/undefined if control variant or if the experiment is still loading (Subject to change)
- *
- * This hook although used for the experiment, it can be refactored in the end to
path: client/my-sites/plans-features-main/hooks/experiments/use-longer-plan-term-default-experiment.ts
user: login: jeyip
body: https://github.com/Automattic/martech/issues/3756
created_at: 2025-03-17T22:14:19Z
author_association: CONTRIBUTOR

PR comments:
user: login: github-actions[bot]
created_at: 2025-03-13T00:16:08Z
body: <details>
<summary>Calypso Live <a href="https://calypso.live?image=registry.a8c.com/calypso/app:build-137483">(direct link)</a></summary>
<table>
<tr>
<td>
<img src="https://chart.googleapis.com/chart?chs=150x150&cht=qr&chl=https%3A%2F%2Fcalypso.live%3Fimage%3Dregistry.a8c.com%2Fcalypso%2Fapp%3Abuild-137483%26flags%3Doauth&choe=UTF-8" />
</td>
<td>
<a href="https://calypso.live?image=registry.a8c.com/calypso/app:build-137483">https://calypso.live?image=registry.a8c.com/calypso/app:build-137483</a>
</td>
</tr>
</table>
</details>
<details>
<summary>Jetpack Cloud live <a href="https://calypso.live?image=registry.a8c.com/calypso/app:build-137483&env=jetpack">(direct link)</a></summary>
<table>
<tr>
<td>
<img src="https://chart.googleapis.com/chart?chs=150x150&cht=qr&chl=https%3A%2F%2Fcalypso.live%3Fimage%3Dregistry.a8c.com%2Fcalypso%2Fapp%3Abuild-137483%26env%3Djetpack%26flags%3Doauth&choe=UTF-8" />
</td>
<td>
<a href="https://calypso.live?image=registry.a8c.com/calypso/app:build-137483&env=jetpack">https://calypso.live?image=registry.a8c.com/calypso/app:build-137483&env=jetpack</a>
</td>
</tr>
</table>
</details>
<details>
<summary>Automattic for Agencies live <a href="https://calypso.live?image=registry.a8c.com/calypso/app:build-137483&env=a8c-for-agencies">(direct link)</a></summary>
<table>
<tr>
<td>
<img src="https://chart.googleapis.com/chart?chs=150x150&cht=qr&chl=https%3A%2F%2Fcalypso.live%3Fimage%3Dregistry.a8c.com%2Fcalypso%2Fapp%3Abuild-137483%26env%3Da8c-for-agencies%26flags%3Doauth&choe=UTF-8" />
</td>
<td>
<a href="https://calypso.live?image=registry.a8c.com/calypso/app:build-137483&env=a8c-for-agencies">https://calypso.live?image=registry.a8c.com/calypso/app:build-137483&env=a8c-for-agencies</a>
</td>
</tr>
</table>
</details>
<!--calypso-live-watermark:apr@v1-->
author_association: NONE
user: login: matticbot
created_at: 2025-03-13T00:17:02Z
body: <!-- icfy-watermark: c52822 -->
Here is how your PR affects size of JS and CSS bundles shipped to the user's browser:

**Sections** (~204 bytes removed 📉 [gzipped])
<details>

```
name                      parsed_size           gzip_size
async-step-unified-plans       -473 B  (-0.1%)     -204 B  (-0.1%)
plugins                        -320 B  (-0.0%)     -137 B  (-0.0%)
plans                          -320 B  (-0.0%)     -137 B  (-0.0%)
jetpack-app                    -320 B  (-0.1%)     -137 B  (-0.1%)
```

Sections contain code specific for a given set of routes. Is downloaded and parsed only when a particular route is navigated to.
</details>

**Async-loaded Components** (~204 bytes removed 📉 [gzipped])
<details>

```
name                                             parsed_size           gzip_size
async-load-signup-steps-plans-theme-preselected       -473 B  (-0.1%)     -204 B  (-0.1%)
async-load-signup-steps-plans                         -473 B  (-0.1%)     -204 B  (-0.1%)
```

React components that are loaded lazily, when a certain part of UI is displayed for the first time.
</details>

**Legend**
<details>
<summary>What is parsed and gzip size?</summary>

**Parsed Size:** Uncompressed size of the JS and CSS files. This much code needs to be parsed and stored in memory.
**Gzip Size:** Compressed size of the JS and CSS files. This much data needs to be downloaded over network.
</details>

Generated by performance advisor bot at [iscalypsofastyet.com](http://iscalypsofastyet.com).
author_association: CONTRIBUTOR
user: login: jeyip
created_at: 2025-03-17T20:52:57Z
body: I'll sit down and look later today or early tomorrow. Since @southp already went through the PR though, feel free to deploy and I can provide retroactive code review 🙂
author_association: CONTRIBUTOR
user: login: jeyip
created_at: 2025-03-17T22:01:29Z
body: ## Testing
### Requirements

- [x] Go /setup/onboarding/plans. Confirm that the savings badge is shown.
  - Verify that, when a coupon is applied, that the savings badges are hidden and coupon badges are rendered instead  
- [x] Go to different flows like /setup/new-hosted-site/plans, /setup/newsletter/plans or /start/onboarding-pm/plans and verify that the savings badge is shown.
- [x] Go to /plans/:siteslug and verify that the savings badge is shown.

### Browsers
- [x] Chrome
author_association: CONTRIBUTOR
user: login: matticbot
created_at: 2025-03-18T19:50:17Z
body: **This PR modifies the release build for the following Calypso Apps:**

_For info about this notification, see here: PCYsg-OT6-p2_

* notifications
* wpcom-block-editor

To test WordPress.com changes, run `install-plugin.sh $pluginSlug update/experiment-longer-term-savings` on your sandbox.
<!--calypso-app-artifacts-watermark:apr@v1-->
author_association: CONTRIBUTOR