Skip to content

Commit 8b97f7c

Browse files
authored
Merge pull request #5434 from mozilla/mntor-3825
Add landing page experiment
2 parents 4576a37 + 1245bd4 commit 8b97f7c

26 files changed

+991
-291
lines changed

config/nimbus.yaml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,33 @@ features:
101101
value: { "enabled": true }
102102
- channel: production
103103
value: { "enabled": true }
104+
landing-page-redesign-plus-eligible-experiment:
105+
description: Landing page redesign
106+
variables:
107+
enabled:
108+
description: If the feature is enabled
109+
type: Boolean
110+
default: false
111+
variant:
112+
description: The landing page variant to show
113+
type: LandingPageVariant
114+
default: default
115+
defaults:
116+
- channel: local
117+
value: {
118+
"enabled": true,
119+
"variant": redesign,
120+
}
121+
- channel: staging
122+
value: {
123+
"enabled": false,
124+
"variant": default,
125+
}
126+
- channel: production
127+
value: {
128+
"enabled": false,
129+
"variant": default,
130+
}
104131
enums:
105132
OptionalBrokerScanInfoFields:
106133
description: An enum of optional broker scan info fields
@@ -122,3 +149,10 @@ enums:
122149
description: Only show a CTA button with the label “Get free scan”
123150
ctaOnlyAlternativeLabel:
124151
description: Only show a CTA button with the label “Sign up to get free scan”
152+
LandingPageVariant:
153+
description: An enum of landing page variants
154+
variants:
155+
default:
156+
description: Show the default landing page
157+
redesign:
158+
description: Show the redesigned landing page

src/app/(proper_react)/(redesign)/(public)/LandingView.module.scss

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,35 +5,57 @@
55
flex-direction: column;
66
height: 100%;
77
}
8+
9+
.waitlistSection {
10+
display: flex;
11+
flex-direction: column;
12+
align-items: center;
13+
gap: tokens.$spacing-lg;
14+
padding: tokens.$layout-md tokens.$spacing-md;
15+
16+
.waitlistTitle {
17+
text-align: center;
18+
font: tokens.$text-title-2xs;
19+
font-weight: 600;
20+
line-height: 1.4;
21+
font-family: var(--font-inter);
22+
color: tokens.$color-purple-70;
23+
}
24+
25+
a {
26+
align-self: center;
27+
}
28+
}
29+
830
.navbar {
931
font: tokens.$text-body-xl;
1032
padding: tokens.$layout-xs;
1133
display: flex;
1234
flex-direction: row;
1335
justify-content: flex-start;
1436
background-color: tokens.$color-grey-05;
15-
.navbarLinksContainer {
37+
ul {
1638
display: flex;
1739
flex-direction: column;
18-
.navbarLinks {
40+
a {
1941
text-decoration: none;
2042
color: tokens.$color-grey-50;
2143
}
2244
}
2345
@media screen and (min-width: tokens.$screen-sm) {
2446
justify-content: flex-end;
25-
.navbarLinksContainer {
47+
ul {
2648
flex-direction: row;
2749
justify-content: flex-end;
28-
.navbarLinks {
50+
a {
2951
margin-left: tokens.$spacing-lg;
3052
}
3153
}
3254
}
3355
@media screen and (min-width: tokens.$screen-md) {
3456
padding: tokens.$layout-xs tokens.$layout-xl;
35-
.navbarLinksContainer {
36-
.navbarLinks {
57+
ul {
58+
a {
3759
margin-left: tokens.$spacing-xl;
3860
}
3961
}
@@ -396,24 +418,3 @@
396418
align-self: center;
397419
}
398420
}
399-
400-
.waitlistSection {
401-
display: flex;
402-
flex-direction: column;
403-
align-items: center;
404-
gap: tokens.$spacing-lg;
405-
padding: tokens.$layout-md tokens.$spacing-md;
406-
407-
.waitlistTitle {
408-
text-align: center;
409-
font: tokens.$text-title-2xs;
410-
font-weight: 600;
411-
line-height: 1.4;
412-
font-family: var(--font-inter);
413-
color: tokens.$color-purple-70;
414-
}
415-
416-
a {
417-
align-self: center;
418-
}
419-
}

src/app/(proper_react)/(redesign)/(public)/LandingView.stories.tsx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { AccountsMetricsFlowProvider } from "../../../../contextProviders/accoun
1111
import { CONST_URL_MONITOR_LANDING_PAGE_ID } from "../../../../constants";
1212

1313
const meta: Meta<typeof View> = {
14-
title: "Pages/Public/Landing page",
14+
title: "Pages/Public/Landing page/Default",
1515
component: (props: ViewProps) => {
1616
const experimentData =
1717
props.experimentData ?? defaultExperimentData["Features"];
@@ -31,7 +31,18 @@ const meta: Meta<typeof View> = {
3131
service: process.env.OAUTH_CLIENT_ID as string,
3232
}}
3333
>
34-
<PublicShell l10n={getL10n("en")} countryCode={props.countryCode}>
34+
<PublicShell
35+
l10n={getL10n("en")}
36+
countryCode={props.countryCode}
37+
enabledFeatureFlags={[]}
38+
experimentData={{
39+
...defaultExperimentData["Features"],
40+
"landing-page-redesign-plus-eligible-experiment": {
41+
enabled: false,
42+
variant: "default",
43+
},
44+
}}
45+
>
3546
<View {...props} experimentData={experimentData} />
3647
</PublicShell>
3748
</AccountsMetricsFlowProvider>

src/app/(proper_react)/(redesign)/(public)/LandingView.tsx

Lines changed: 7 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,10 @@ import { TelemetryLink } from "../../../components/client/TelemetryLink";
2626
import { HeresHowWeHelp } from "./HeresHowWeHelp";
2727
import { ScanLimit } from "./ScanLimit";
2828
import { FaqSection } from "./Faq";
29-
import { AccountDeletionNotification } from "./AccountDeletionNotification";
3029
import { ExperimentData } from "../../../../telemetry/generated/nimbus/experiments";
3130
import { FreeScanCta } from "./FreeScanCta";
31+
import { TopNavBar } from "./TopNavBar";
32+
import { AccountDeletionNotification } from "./AccountDeletionNotification";
3233

3334
export type Props = {
3435
eligibleForPremium: boolean;
@@ -43,7 +44,11 @@ export const View = (props: Props) => {
4344
<>
4445
<AccountDeletionNotification />
4546
<main className={styles.wrapper}>
46-
{props.eligibleForPremium && <TopNavBar l10n={props.l10n} />}
47+
{props.eligibleForPremium && (
48+
<div className={styles.navbar}>
49+
<TopNavBar />
50+
</div>
51+
)}
4752
<header className={styles.hero}>
4853
<div className={styles.heroContent}>
4954
<h1>{props.l10n.getString("landing-all-hero-title")}</h1>
@@ -258,52 +263,6 @@ export const View = (props: Props) => {
258263
);
259264
};
260265

261-
export const TopNavBar = ({ l10n }: { l10n: ExtendedReactLocalization }) => {
262-
return (
263-
<div className={styles.navbar}>
264-
<div className={styles.navbarLinksContainer}>
265-
<TelemetryLink
266-
className={styles.navbarLinks}
267-
href="/how-it-works"
268-
eventData={{
269-
link_id: "navbar_how_it_works",
270-
}}
271-
>
272-
{l10n.getString("landing-premium-hero-navbar-link-how-it-works")}
273-
</TelemetryLink>
274-
<TelemetryLink
275-
className={styles.navbarLinks}
276-
href="#pricing"
277-
eventData={{
278-
link_id: "navbar_pricing",
279-
}}
280-
>
281-
{l10n.getString("landing-premium-hero-navbar-link-pricing")}
282-
</TelemetryLink>
283-
<TelemetryLink
284-
data-testid="navbar_faqs"
285-
className={styles.navbarLinks}
286-
href="#faq"
287-
eventData={{
288-
link_id: "navbar_faqs",
289-
}}
290-
>
291-
{l10n.getString("landing-premium-hero-navbar-link-faqs")}
292-
</TelemetryLink>
293-
<TelemetryLink
294-
className={styles.navbarLinks}
295-
href="/breaches"
296-
eventData={{
297-
link_id: "navbar_recent_breaches",
298-
}}
299-
>
300-
{l10n.getString("landing-premium-hero-navbar-link-recent-breaches")}
301-
</TelemetryLink>
302-
</div>
303-
</div>
304-
);
305-
};
306-
307266
const HeroImage = (props: Props) => {
308267
if (!props.eligibleForPremium) {
309268
return (
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
@import "../../../tokens";
2+
3+
.wrapper {
4+
display: flex;
5+
flex-direction: column;
6+
height: 100%;
7+
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
import type { Meta, StoryObj } from "@storybook/react";
6+
import { View, Props as ViewProps } from "./LandingViewRedesign";
7+
import { getL10n } from "../../../functions/l10n/storybookAndJest";
8+
import { PublicShell } from "./PublicShell";
9+
import { defaultExperimentData } from "../../../../telemetry/generated/nimbus/experiments";
10+
import { AccountsMetricsFlowProvider } from "../../../../contextProviders/accounts-metrics-flow";
11+
import { CONST_URL_MONITOR_LANDING_PAGE_ID } from "../../../../constants";
12+
13+
const meta: Meta<typeof View> = {
14+
title: "Pages/Public/Landing page/Redesign",
15+
component: (props: ViewProps) => {
16+
const experimentData =
17+
props.experimentData ?? defaultExperimentData["Features"];
18+
return (
19+
<AccountsMetricsFlowProvider
20+
enabled={
21+
experimentData["landing-page-redesign-plus-eligible-experiment"]
22+
.enabled
23+
}
24+
metricsFlowParams={{
25+
entrypoint: CONST_URL_MONITOR_LANDING_PAGE_ID,
26+
entrypoint_experiment:
27+
"landing-page-redesign-plus-eligible-experiment",
28+
entrypoint_variation:
29+
experimentData["landing-page-redesign-plus-eligible-experiment"]
30+
.variant,
31+
form_type: "email",
32+
service: process.env.OAUTH_CLIENT_ID as string,
33+
}}
34+
>
35+
<PublicShell
36+
l10n={getL10n("en")}
37+
countryCode={props.countryCode}
38+
enabledFeatureFlags={["LandingPageRedesign"]}
39+
experimentData={{
40+
...defaultExperimentData["Features"],
41+
"landing-page-redesign-plus-eligible-experiment": {
42+
enabled: true,
43+
variant: "redesign",
44+
},
45+
}}
46+
>
47+
<View {...props} experimentData={experimentData} />
48+
</PublicShell>
49+
</AccountsMetricsFlowProvider>
50+
);
51+
},
52+
args: {
53+
l10n: getL10n(),
54+
},
55+
};
56+
57+
export default meta;
58+
type Story = StoryObj<typeof View>;
59+
60+
export const LandingRedesignUs: Story = {
61+
name: "US visitors",
62+
args: {
63+
eligibleForPremium: true,
64+
countryCode: "us",
65+
scanLimitReached: false,
66+
},
67+
};
68+
69+
export const LandingRedesignUsScanLimit: Story = {
70+
name: "US visitors - Scan limit reached",
71+
args: {
72+
eligibleForPremium: true,
73+
countryCode: "us",
74+
scanLimitReached: true,
75+
},
76+
};
77+
78+
export const LandingRedesignNonUs: Story = {
79+
name: "Non-US visitors",
80+
args: {
81+
eligibleForPremium: false,
82+
countryCode: "nz",
83+
},
84+
};
85+
86+
export const LandingRedesignNonUsDe: Story = {
87+
name: "German",
88+
args: {
89+
eligibleForPremium: false,
90+
countryCode: "de",
91+
l10n: getL10n("de"),
92+
},
93+
};
94+
95+
export const LandingRedesignNonUsFr: Story = {
96+
name: "French",
97+
args: {
98+
eligibleForPremium: false,
99+
countryCode: "fr",
100+
l10n: getL10n("fr"),
101+
},
102+
};

0 commit comments

Comments
 (0)