diff --git a/frontend/common/stores/account-store.js b/frontend/common/stores/account-store.js index 2deb58f93073..60bf4ea3c7f6 100644 --- a/frontend/common/stores/account-store.js +++ b/frontend/common/stores/account-store.js @@ -17,6 +17,8 @@ import { hidePylon, identifyChatUser } from 'common/loadChat' import { service } from 'common/service' import { getBuildVersion } from 'common/services/useBuildVersion' import { createOnboardingSupportOptIn } from 'common/services/useOnboardingSupportOptIn' +import flagsmith from '@flagsmith/flagsmith' +import isFreeEmailDomain from 'common/utils/isFreeEmailDomain' const controller = { acceptInvite: (id) => { @@ -265,6 +267,16 @@ const controller = { .then(async (res) => { data.setToken(Project.cookieAuthEnabled ? 'true' : res.key) API.trackEvent(Constants.events.REGISTER) + const freeEmailDomain = isFreeEmailDomain(user.email) + flagsmith.trackEvent('new_signup', { + metadata: { + ...(freeEmailDomain && { domain: user.email.split('@')[1] }), + free_email_domain: freeEmailDomain, + invite: !!API.getInvite(), + signup_method: 'email', + utm_source: user.utm_data?.utm_source, + }, + }) if (API.getReferrer()) { API.trackEvent( Constants.events.REFERRER_REGISTERED(API.getReferrer().utm_source), diff --git a/frontend/common/useSignupExperiment.ts b/frontend/common/useSignupExperiment.ts new file mode 100644 index 000000000000..a25fa15b7b56 --- /dev/null +++ b/frontend/common/useSignupExperiment.ts @@ -0,0 +1,24 @@ +import { useEffect, useState } from 'react' +import flagsmith from '@flagsmith/flagsmith' +import { storageGet, storageSet } from './safeLocalStorage' + +export default function useSignupExperiment(useEnvironmentFlag: boolean) { + const [variant, setVariant] = useState() + + useEffect(() => { + if (useEnvironmentFlag) { + return + } + const identifyAndExpose = async () => { + const id = storageGet('signup_anonymous_id') || crypto.randomUUID() + storageSet('signup_anonymous_id', id) + // @ts-expect-error transient is missing from the SDK's identify type + await flagsmith.identify(id, {}, true) + const flag = flagsmith.getExperimentFlag('signup_corporate_only') + setVariant(flag?.enabled ? flag.variant : undefined) + } + identifyAndExpose() + }, [useEnvironmentFlag]) + + return variant +} diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 4577b744f36e..2906ede9d66a 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -25,7 +25,7 @@ "@dnd-kit/abstract": "^0.3.2", "@dnd-kit/helpers": "^0.3.2", "@dnd-kit/react": "^0.3.2", - "@flagsmith/flagsmith": "11.0.0-internal.11", + "@flagsmith/flagsmith": "12.1.0", "@ionic/react": "^7.5.3", "@react-oauth/google": "^0.2.8", "@reduxjs/toolkit": "1.9.1", @@ -3234,9 +3234,9 @@ } }, "node_modules/@flagsmith/flagsmith": { - "version": "11.0.0-internal.11", - "resolved": "https://registry.npmjs.org/@flagsmith/flagsmith/-/flagsmith-11.0.0-internal.11.tgz", - "integrity": "sha512-u2Mprn3GLz53TUEo1rpfK/18BMQbwf9Z5mKhs9jnUnRDjqh23Ud+83AwSPNjif5EjgXbrEg4p76gY8k/E/1RoA==", + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/@flagsmith/flagsmith/-/flagsmith-12.1.0.tgz", + "integrity": "sha512-xcT1J4gHWLYYXv+0jUNVSFM3ZPtKPdSe6n0ruAjwbqaGmTXL+B6W66b46J78SLJcCCgOlAuoYNYgGa/trPCBdw==", "license": "BSD-3-Clause" }, "node_modules/@floating-ui/core": { diff --git a/frontend/package.json b/frontend/package.json index 419e9ff0fc6f..e88a766e2eaf 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -63,7 +63,7 @@ "@dnd-kit/abstract": "^0.3.2", "@dnd-kit/helpers": "^0.3.2", "@dnd-kit/react": "^0.3.2", - "@flagsmith/flagsmith": "11.0.0-internal.11", + "@flagsmith/flagsmith": "12.1.0", "@ionic/react": "^7.5.3", "@react-oauth/google": "^0.2.8", "@reduxjs/toolkit": "1.9.1", diff --git a/frontend/web/components/pages/HomePage.tsx b/frontend/web/components/pages/HomePage.tsx index debcf25d64f3..55becef5684e 100644 --- a/frontend/web/components/pages/HomePage.tsx +++ b/frontend/web/components/pages/HomePage.tsx @@ -31,6 +31,7 @@ import AccountStore from 'common/stores/account-store' import { LoginRequest, RegisterRequest } from 'common/types/requests' import { useGetBuildVersionQuery } from 'common/services/useBuildVersion' import { useUTMs } from 'common/useUTMs' +import useSignupExperiment from 'common/useSignupExperiment' const HomePage: React.FC = () => { const history = useHistory() @@ -180,6 +181,12 @@ const HomePage: React.FC = () => { currentLocation.indexOf('signup') !== -1) const disableSignup = preventSignup && isSignup const preventEmailPassword = Project.preventEmailPassword + + const signupVariant = useSignupExperiment( + !isSignup || isInvite || !!preventEmailPassword || !!AccountStore.getUser(), + ) + const blockGenericEmailDomain = + signupVariant === 'signup_corporate_only' && isFreeEmailDomain(email) const disableForgotPassword = Project.preventForgotPassword const oauths: React.ReactNode[] = [] const disableOauthRegister = Utils.getFlagsmithHasFeature( @@ -627,12 +634,16 @@ const HomePage: React.FC = () => { name='email' id='email' /> - {isFreeEmailDomain(email) && ( - - Signing up with a work email makes it easier - for co-workers to join your Flagsmith - organisation. - + {blockGenericEmailDomain ? ( + + ) : ( + isFreeEmailDomain(email) && ( + + Signing up with a work email makes it + easier for co-workers to join your + Flagsmith organisation. + + ) )} { disabled={ isLoading || isSaving || - !allRequirementsMet + !allRequirementsMet || + !firstName.trim() || + !lastName.trim() || + blockGenericEmailDomain } className='px-4 mt-3 full-width' type='submit'