Skip to content

Commit

Permalink
Stepper: Apply extended props to calypso_signup_start. Update `tail…
Browse files Browse the repository at this point in the history
…ored-ecommerce` flow (#93941)
  • Loading branch information
chriskmnds authored Oct 3, 2024
1 parent 51df53d commit d521b18
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 19 deletions.
2 changes: 1 addition & 1 deletion client/landing/stepper/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ To create a flow, you only have to implement `useSteps` and `useStepNavigation`.

There is also an optional `useSideEffect` hook. You can implement this hook to run any side-effects to the flow. You can prefetch information, send track events when something changes, etc...

There is a required `isSignupFlow` flag that _MUST be `true` for signup flows_ (generally where a new site may be created), and should be `false` for other flows. The `isSignupFlow` flag controls whether we'll trigger a `calypso_signup_start` Tracks event when the flow starts. For signup flows, you can also supply additional event props to the `calypso_signup_start` event by implementing the optional `useSignupStartEventProps()` hook on the flow.
There is a required `isSignupFlow` flag that _MUST be `true` for signup flows_ (generally where a new site may be created), and should be `false` for other flows. The `isSignupFlow` flag controls whether we'll trigger a `calypso_signup_start` Tracks event when the flow starts. For signup flows, you can also supply additional event props to the `calypso_signup_start` event by implementing the optional `useTracksEventProps()` hook on the flow.

```tsx
// prettier-ignore
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { useEffect, useMemo } from 'react';
import { useEffect } from 'react';
import { useSearchParams } from 'react-router-dom';
import { STEPPER_TRACKS_EVENT_SIGNUP_START } from 'calypso/landing/stepper/constants';
import recordSignupStart from 'calypso/landing/stepper/declarative-flow/internals/analytics/record-signup-start';
import useSnakeCasedKeys from 'calypso/landing/stepper/utils/use-snake-cased-keys';
import { adTrackSignupStart } from 'calypso/lib/analytics/ad-tracking';
import { gaRecordEvent } from 'calypso/lib/analytics/ga';
import { setSignupStartTime } from 'calypso/signup/storageUtils';
Expand All @@ -16,17 +18,12 @@ interface Props {
export const useSignUpStartTracking = ( { flow }: Props ) => {
const [ queryParams ] = useSearchParams();
const ref = queryParams.get( 'ref' ) || '';
const flowVariant = flow.variantSlug;
const flowName = flow.name;
const flowVariant = flow.variantSlug;
const isSignupFlow = flow.isSignupFlow;
const signupStartEventProps = flow.useSignupStartEventProps?.();
const extraProps = useMemo(
() => ( {
...signupStartEventProps,
...( flowVariant && { flow_variant: flowVariant } ),
} ),
[ signupStartEventProps, flowVariant ]
);
const signupStartEventProps = useSnakeCasedKeys( {
input: flow.useTracksEventProps?.()[ STEPPER_TRACKS_EVENT_SIGNUP_START ],
} );

/**
* Timers and other analytics
Expand All @@ -51,6 +48,13 @@ export const useSignUpStartTracking = ( { flow }: Props ) => {
return;
}

recordSignupStart( { flow: flowName, ref, optionalProps: extraProps || {} } );
}, [ isSignupFlow, flowName, ref, extraProps ] );
recordSignupStart( {
flow: flowName,
ref,
optionalProps: {
...signupStartEventProps,
...( flowVariant && { flow_variant: flowVariant } ),
},
} );
}, [ isSignupFlow, flowName, ref, signupStartEventProps, flowVariant ] );
};
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { gaRecordEvent } from 'calypso/lib/analytics/ga';
import { setSignupStartTime } from 'calypso/signup/storageUtils';
import { renderHookWithProvider } from 'calypso/test-helpers/testing-library';
import { useSignUpStartTracking } from '../';
import { STEPPER_TRACKS_EVENT_SIGNUP_START } from '../../../../../constants';
import type { Flow, StepperStep } from '../../../types';

const steps = [ { slug: 'step-1' }, { slug: 'step-2' } ] as StepperStep[];
Expand Down Expand Up @@ -86,7 +87,9 @@ describe( 'useSignUpTracking', () => {
render( {
flow: {
...signUpFlow,
useSignupStartEventProps: () => ( { extra: 'props' } ),
useTracksEventProps: () => ( {
[ STEPPER_TRACKS_EVENT_SIGNUP_START ]: { extra: 'props' },
} ),
} satisfies Flow,
queryParams: { ref: 'another-flow-or-cta' },
} );
Expand Down Expand Up @@ -132,7 +135,9 @@ describe( 'useSignUpTracking', () => {
const { rerender } = render( {
flow: {
...signUpFlow,
useSignupStartEventProps: () => ( { extra: 'props' } ),
useTracksEventProps: () => ( {
[ STEPPER_TRACKS_EVENT_SIGNUP_START ]: { extra: 'props' },
} ),
} satisfies Flow,
} );

Expand Down
2 changes: 0 additions & 2 deletions client/landing/stepper/declarative-flow/internals/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,6 @@ export type Flow = {
* Required flag to indicate if the flow is a signup flow.
*/
isSignupFlow: boolean;
useSignupStartEventProps?: () => Record< string, string | number >;

/**
* You can use this hook to configure the login url.
* @returns An object describing the configuration.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ import {
} from '@automattic/calypso-products';
import { ECOMMERCE_FLOW, ecommerceFlowRecurTypes } from '@automattic/onboarding';
import { useSelect, useDispatch } from '@wordpress/data';
import { useMemo } from '@wordpress/element';
import { stepsWithRequiredLogin } from 'calypso/landing/stepper/utils/steps-with-required-login';
import { recordTracksEvent } from 'calypso/lib/analytics/tracks';
import {
setSignupCompleteSlug,
persistSignupDestination,
setSignupCompleteFlowName,
} from 'calypso/signup/storageUtils';
import { STEPPER_TRACKS_EVENT_SIGNUP_START } from '../constants';
import { useSite } from '../hooks/use-site';
import { useSiteSlugParam } from '../hooks/use-site-slug-param';
import { USER_STORE, ONBOARD_STORE, SITE_STORE } from '../stores';
Expand Down Expand Up @@ -46,13 +48,13 @@ function getPlanFromRecurType( recurType: string ) {
const ecommerceFlow: Flow = {
name: ECOMMERCE_FLOW,
isSignupFlow: true,
useSignupStartEventProps() {
useTracksEventProps() {
const recur = useSelect(
( select ) => ( select( ONBOARD_STORE ) as OnboardSelect ).getEcommerceFlowRecurType(),
[]
);

return { recur };
return useMemo( () => ( { [ STEPPER_TRACKS_EVENT_SIGNUP_START ]: { recur } } ), [ recur ] );
},
useSteps() {
const steps = [
Expand Down
51 changes: 51 additions & 0 deletions client/landing/stepper/utils/test/use-snake-cased-keys.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* @jest-environment jsdom
*/
import { renderHook } from '@testing-library/react';
import useSnakeCasedKeys from '../use-snake-cased-keys';

describe( 'useSnakeCasedKeys', () => {
test( 'ensures reference equality given same input', () => {
const input = { fooBar: 'fooBar' };
const { result, rerender } = renderHook( ( params ) => useSnakeCasedKeys( params ), {
initialProps: { input },
} );
const previous = result.current;

rerender( { input } );
expect( result.current ).toBe( previous );
} );

test( 'given fooBar it will convert correctly', () => {
const input = { fooBar: 'fooBar' };
const expectedOutput = { foo_bar: 'fooBar' };

const { result } = renderHook( ( params ) => useSnakeCasedKeys( params ), {
initialProps: { input },
} );

expect( result.current ).toEqual( expectedOutput );
} );

test( 'given foo_bar it will convert correctly', () => {
const input = { foo_bar: 'fooBar' };
const expectedOutput = { foo_bar: 'fooBar' };

const { result } = renderHook( ( params ) => useSnakeCasedKeys( params ), {
initialProps: { input },
} );

expect( result.current ).toEqual( expectedOutput );
} );

test( 'given foo123 it will convert correctly', () => {
const input = { foo123bar: 'fooBar' };
const expectedOutput = { foo_123_bar: 'fooBar' };

const { result } = renderHook( ( params ) => useSnakeCasedKeys( params ), {
initialProps: { input },
} );

expect( result.current ).toEqual( expectedOutput );
} );
} );
12 changes: 12 additions & 0 deletions client/landing/stepper/utils/use-snake-cased-keys.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { useMemo } from '@wordpress/element';
import { convertToSnakeCase } from 'calypso/state/data-layer/utils';

interface Params {
input?: Record< string, unknown >;
}

const useSnakeCasedKeys = ( { input }: Params ) => {
return useMemo( () => input && ( convertToSnakeCase( input ) as Params[ 'input' ] ), [ input ] );
};

export default useSnakeCasedKeys;

0 comments on commit d521b18

Please sign in to comment.