diff --git a/client/landing/stepper/declarative-flow/internals/global.scss b/client/landing/stepper/declarative-flow/internals/global.scss
index ddf1920f6edbc..be07373955ac9 100644
--- a/client/landing/stepper/declarative-flow/internals/global.scss
+++ b/client/landing/stepper/declarative-flow/internals/global.scss
@@ -75,6 +75,7 @@ button {
.site-setup,
.onboarding.goals,
.onboarding.design-setup,
+.onboarding.difm-starting-point,
.site-migration,
.migration,
.migration-signup,
diff --git a/client/landing/stepper/declarative-flow/internals/steps-repository/difm-starting-point/index.tsx b/client/landing/stepper/declarative-flow/internals/steps-repository/difm-starting-point/index.tsx
index f7fdf8094cff8..76f038e8f901d 100644
--- a/client/landing/stepper/declarative-flow/internals/steps-repository/difm-starting-point/index.tsx
+++ b/client/landing/stepper/declarative-flow/internals/steps-repository/difm-starting-point/index.tsx
@@ -1,21 +1,28 @@
import { StepContainer } from '@automattic/onboarding';
import { useTranslate } from 'i18n-calypso';
+import { useSelector } from 'react-redux';
import DocumentHead from 'calypso/components/data/document-head';
import { useSite } from 'calypso/landing/stepper/hooks/use-site';
import { recordTracksEvent } from 'calypso/lib/analytics/tracks';
import DIFMLanding from 'calypso/my-sites/marketing/do-it-for-me/difm-landing';
+import { getCurrentUserSiteCount } from 'calypso/state/current-user/selectors';
import type { Step } from '../../types';
+import type { AppState } from 'calypso/types';
const STEP_NAME = 'difmStartingPoint';
const DIFMStartingPoint: Step = function ( { navigation } ) {
const { goNext, goBack, submit } = navigation;
const translate = useTranslate();
+ const existingSiteCount = useSelector( ( state: AppState ) => getCurrentUserSiteCount( state ) );
+ const siteId = useSite()?.ID;
+ const showNewOrExistingSiteChoice = ! siteId && !! existingSiteCount && existingSiteCount > 0;
- const onSubmit = () => {
- submit?.();
+ const onSubmit = ( value: string ) => {
+ submit?.( {
+ newOrExistingSiteChoice: value,
+ } );
};
- const siteId = useSite()?.ID;
return (
<>
@@ -29,8 +36,11 @@ const DIFMStartingPoint: Step = function ( { navigation } ) {
skipLabelText={ translate( 'No Thanks, I’ll Build It' ) }
stepContent={
+ showNewOrExistingSiteChoice ? onSubmit( 'existing-site' ) : onSubmit( 'new-site' )
+ }
+ onSecondarySubmit={ () => onSubmit( 'new-site' ) }
+ showNewOrExistingSiteChoice={ showNewOrExistingSiteChoice }
siteId={ siteId }
isStoreFlow={ false }
/>
diff --git a/client/landing/stepper/declarative-flow/onboarding.ts b/client/landing/stepper/declarative-flow/onboarding.ts
index 48dc78a1e4d04..985e90673577d 100644
--- a/client/landing/stepper/declarative-flow/onboarding.ts
+++ b/client/landing/stepper/declarative-flow/onboarding.ts
@@ -1,4 +1,4 @@
-import { OnboardSelect, Onboard } from '@automattic/data-stores';
+import { OnboardSelect, Onboard, UserSelect } from '@automattic/data-stores';
import { ONBOARDING_FLOW } from '@automattic/onboarding';
import { useDispatch, useSelect } from '@wordpress/data';
import { addQueryArgs, getQueryArg, getQueryArgs, removeQueryArgs } from '@wordpress/url';
@@ -16,7 +16,8 @@ import {
} from '../constants';
import { useFlowLocale } from '../hooks/use-flow-locale';
import { useQuery } from '../hooks/use-query';
-import { ONBOARD_STORE } from '../stores';
+import { ONBOARD_STORE, USER_STORE } from '../stores';
+import { getLoginUrl } from '../utils/path';
import { stepsWithRequiredLogin } from '../utils/steps-with-required-login';
import { useGoalsFirstExperiment } from './helpers/use-goals-first-experiment';
import { recordStepNavigation } from './internals/analytics/record-step-navigation';
@@ -83,7 +84,7 @@ const onboarding: Flow = {
if ( isGoalsAtFrontExperiment ) {
// Note: these steps are not wrapped in `stepsWithRequiredLogin`
- steps.unshift( STEPS.GOALS, STEPS.DESIGN_SETUP );
+ steps.unshift( STEPS.GOALS, STEPS.DESIGN_SETUP, STEPS.DIFM_STARTING_POINT );
}
return steps;
@@ -101,11 +102,12 @@ const onboarding: Flow = {
} = useDispatch( ONBOARD_STORE );
const locale = useFlowLocale();
- const { planCartItem, signupDomainOrigin } = useSelect(
- ( select: ( key: string ) => OnboardSelect ) => ( {
- domainCartItem: select( ONBOARD_STORE ).getDomainCartItem(),
- planCartItem: select( ONBOARD_STORE ).getPlanCartItem(),
+ const { planCartItem, signupDomainOrigin, isUserLoggedIn } = useSelect(
+ ( select ) => ( {
+ domainCartItem: ( select( ONBOARD_STORE ) as OnboardSelect ).getDomainCartItem(),
+ planCartItem: ( select( ONBOARD_STORE ) as OnboardSelect ).getPlanCartItem(),
signupDomainOrigin: ( select( ONBOARD_STORE ) as OnboardSelect ).getSignupDomainOrigin(),
+ isUserLoggedIn: ( select( USER_STORE ) as UserSelect ).isCurrentUserLoggedIn(),
} ),
[]
);
@@ -142,18 +144,8 @@ const onboarding: Flow = {
);
}
- case SiteIntent.DIFM: {
- const difmFlowLink =
- locale && locale !== 'en'
- ? `/start/do-it-for-me/${ locale }`
- : '/start/do-it-for-me';
-
- return window.location.assign(
- addQueryArgs( difmFlowLink, {
- back_to: goalsUrl,
- } )
- );
- }
+ case SiteIntent.DIFM:
+ return navigate( 'difmStartingPoint' );
default: {
return navigate( 'designSetup' );
@@ -165,6 +157,32 @@ const onboarding: Flow = {
return navigate( 'domains' );
}
+ case 'difmStartingPoint': {
+ const { newOrExistingSiteChoice } = providedDependencies;
+ const difmFlowLink = addQueryArgs(
+ locale && locale !== 'en' ? `/start/do-it-for-me/${ locale }` : '/start/do-it-for-me',
+ {
+ back_to: window.location.href.replace( window.location.origin, '' ),
+ newOrExistingSiteChoice,
+ }
+ );
+
+ if ( isUserLoggedIn ) {
+ return window.location.assign( difmFlowLink );
+ }
+
+ const loginUrl = getLoginUrl( {
+ variationName: flowName,
+ redirectTo: difmFlowLink,
+ locale,
+ extra: {
+ back_to: window.location.href.replace( window.location.origin, '' ),
+ },
+ } );
+
+ return window.location.assign( loginUrl );
+ }
+
case 'domains':
setSiteUrl( providedDependencies.siteUrl );
setDomain( providedDependencies.suggestion );
@@ -249,6 +267,7 @@ const onboarding: Flow = {
siteSlug: providedDependencies.siteSlug,
...( isGoalsAtFrontExperiment && { 'goals-at-front-experiment': true } ),
} );
+
persistSignupDestination( destination );
setSignupCompleteFlowName( flowName );
setSignupCompleteSlug( providedDependencies.siteSlug );
@@ -309,6 +328,8 @@ const onboarding: Flow = {
if ( isGoalsAtFrontExperiment ) {
return navigate( 'goals' );
}
+ case 'difmStartingPoint':
+ return navigate( 'goals' );
default:
return;
}
diff --git a/client/landing/stepper/declarative-flow/site-setup-flow.ts b/client/landing/stepper/declarative-flow/site-setup-flow.ts
index 1de834ca78abf..4106c42350c8b 100644
--- a/client/landing/stepper/declarative-flow/site-setup-flow.ts
+++ b/client/landing/stepper/declarative-flow/site-setup-flow.ts
@@ -491,7 +491,12 @@ const siteSetupFlow: Flow = {
return navigate( `importerWordpress?${ urlQueryParams.toString() }` );
case 'difmStartingPoint': {
- return exitFlow( `/start/website-design-services/?siteSlug=${ siteSlug }` );
+ const backUrl = window.location.href.replace( window.location.origin, '' );
+ return exitFlow(
+ `/start/website-design-services/?siteSlug=${ siteSlug }&back_to=${ encodeURIComponent(
+ backUrl
+ ) }`
+ );
}
}
}
diff --git a/client/landing/stepper/declarative-flow/test/onboarding-flow.tsx b/client/landing/stepper/declarative-flow/test/onboarding-flow.tsx
index cd0dd41643cd7..8a2d7414e1bff 100644
--- a/client/landing/stepper/declarative-flow/test/onboarding-flow.tsx
+++ b/client/landing/stepper/declarative-flow/test/onboarding-flow.tsx
@@ -64,9 +64,7 @@ describe( 'Onboarding Flow', () => {
},
} );
- expect( window.location.assign ).toHaveBeenCalledWith(
- '/start/do-it-for-me?back_to=%2Fsetup%2Fonboarding%2Fgoals'
- );
+ expect( getFlowLocation().path ).toBe( '/difmStartingPoint' );
} );
it( 'should navigate to designSetup step for other intents', async () => {
diff --git a/client/signup/config/flows-pure.js b/client/signup/config/flows-pure.js
index 8d325aaa813f7..9b938574484e7 100644
--- a/client/signup/config/flows-pure.js
+++ b/client/signup/config/flows-pure.js
@@ -463,8 +463,8 @@ export function generateFlows( {
enableBranchSteps: true,
hideProgressIndicator: true,
enablePresales: false,
- providesDependenciesInQuery: [ 'coupon' ],
- optionalDependenciesInQuery: [ 'coupon' ],
+ providesDependenciesInQuery: [ 'coupon', 'back_to', 'newOrExistingSiteChoice' ],
+ optionalDependenciesInQuery: [ 'coupon', 'back_to', 'newOrExistingSiteChoice' ],
},
{
name: 'do-it-for-me-store',
@@ -493,7 +493,8 @@ export function generateFlows( {
destination: getDIFMSignupDestination,
description: 'A flow for DIFM onboarding',
excludeFromManageSiteFlows: true,
- providesDependenciesInQuery: [ 'siteSlug' ],
+ providesDependenciesInQuery: [ 'siteSlug', 'back_to' ],
+ optionalDependenciesInQuery: [ 'back_to' ],
lastModified: '2024-06-14',
enablePresales: false,
},
diff --git a/client/signup/steps/difm-site-picker/index.tsx b/client/signup/steps/difm-site-picker/index.tsx
index c5cabc82ab35b..0392404517a07 100644
--- a/client/signup/steps/difm-site-picker/index.tsx
+++ b/client/signup/steps/difm-site-picker/index.tsx
@@ -15,6 +15,7 @@ interface Props {
stepSectionName: string | null;
stepName: string;
flowName: string;
+ signupDependencies: any;
goToStep: () => void;
goToNextStep: () => void;
}
@@ -36,7 +37,8 @@ const DIFMSitePicker = ( {
export default function DIFMSitePickerStep( props: Props ) {
const translate = useTranslate();
const dispatch = useDispatch();
- const { goToNextStep } = props;
+ const { signupDependencies, goToNextStep } = props;
+ const { back_to: backUrl } = signupDependencies;
const store = useStore();
const headerText = translate( 'Choose where you want us to build your site.' );
@@ -108,6 +110,8 @@ export default function DIFMSitePickerStep( props: Props ) {
fallbackSubHeaderText={ subHeaderText }
stepContent={ }
hideSkip
+ backUrl={ backUrl }
+ allowBackFirstStep={ !! backUrl }
{ ...props }
/>
);
diff --git a/client/signup/steps/new-or-existing-site/index.tsx b/client/signup/steps/new-or-existing-site/index.tsx
index 40eda449e886c..eccadb676f9a3 100644
--- a/client/signup/steps/new-or-existing-site/index.tsx
+++ b/client/signup/steps/new-or-existing-site/index.tsx
@@ -18,19 +18,26 @@ interface Props {
flowName: string;
stepName: string;
existingSiteCount: number;
+ signupDependencies: {
+ back_to?: string;
+ newOrExistingSiteChoice?: ChoiceType;
+ };
}
export default function NewOrExistingSiteStep( props: Props ) {
const dispatch = useDispatch();
- const { stepName, goToNextStep, existingSiteCount, flowName } = props;
+ const { stepName, goToNextStep, existingSiteCount, flowName, signupDependencies } = props;
+ const { back_to: backUrl, newOrExistingSiteChoice: preselectedChoice } = signupDependencies;
useEffect( () => {
dispatch( saveSignupStep( { stepName } ) );
triggerGuidesForStep( flowName, stepName );
}, [ dispatch, flowName, stepName ] );
- const branchSteps = useBranchSteps( stepName, () => [ 'difm-site-picker' ] );
+ const branchSteps = useBranchSteps( stepName, () =>
+ preselectedChoice ? [ 'new-or-existing-site', 'difm-site-picker' ] : [ 'difm-site-picker' ]
+ );
const newOrExistingSiteSelected = ( value: ChoiceType ) => {
// If 'new-site' is selected, skip the `difm-site-picker` step.
@@ -52,6 +59,17 @@ export default function NewOrExistingSiteStep( props: Props ) {
const showNewOrExistingSiteChoice = existingSiteCount > 0;
+ // Support pre-selected choice.
+ useEffect( () => {
+ if ( preselectedChoice ) {
+ newOrExistingSiteSelected( preselectedChoice );
+ }
+ }, [ preselectedChoice ] );
+
+ if ( preselectedChoice ) {
+ return null;
+ }
+
return (
( siteId ? getSite( state, siteId ) : null ) );
@@ -127,6 +127,8 @@ export default function SiteOptionsStep( props: Props ) {
skipButtonAlign="top"
skipLabelText={ translate( 'Skip this step' ) }
isHorizontalLayout
+ backUrl={ backUrl }
+ allowBackFirstStep={ !! backUrl }
defaultDependencies={ {
siteTitle: '',
tagline: '',