Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add landing page experiment #5434

Merged
merged 36 commits into from
Jan 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
66cfce7
feat: Add feature flag for landing page redesign
flozia Dec 16, 2024
4ae5d63
feat: Add experiment for landing page redesign
flozia Dec 16, 2024
095729d
chore: Add landing page menu
flozia Dec 16, 2024
c69ee4e
chore: Global menu header styling
flozia Dec 16, 2024
ca4ea5f
fix: Only show MobileShell when landing page redesign is enabled
flozia Dec 17, 2024
fe4364d
chore: Add stories for landing page redesign
flozia Dec 17, 2024
56ee8d0
chore: Add initial unit tests for landing page redesign
flozia Dec 17, 2024
218a13d
chore: Match submenu items with main menu
flozia Dec 18, 2024
dfea4ab
merge: main -> mntor-3825
flozia Dec 19, 2024
58057d1
fix: Country code props for landing story
flozia Dec 19, 2024
e53a3b9
Merge branch 'main' into mntor-3825
flozia Dec 19, 2024
9681142
Merge branch 'mntor-3825' of github.com:mozilla/blurts-server into mn…
flozia Dec 19, 2024
248d198
fix: E2E
flozia Dec 19, 2024
6c396f7
chore: Fix mobile shell menu
flozia Dec 19, 2024
a0503a8
Merge branch 'main' into mntor-3825
flozia Dec 20, 2024
d665757
chore: Remove mobile menu carets
flozia Dec 20, 2024
ea376fe
Merge branch 'main' into mntor-3825
flozia Dec 20, 2024
0f4404a
merge: main -> mntor-3825
flozia Dec 20, 2024
1439816
fix: NavBar styling
flozia Dec 20, 2024
cac5077
chore: Update mobile navbar hoverstate
flozia Dec 20, 2024
aef16bc
fix: Linter
flozia Dec 20, 2024
5dc3a67
fix: Unit test for LandingPageRedesign
flozia Dec 20, 2024
2d72801
Merge branch 'main' into mntor-3825
flozia Dec 23, 2024
f133a04
Merge branch 'main' into mntor-3825
flozia Jan 2, 2025
261324c
Merge branch 'mntor-3825' of github.com:mozilla/blurts-server into mn…
flozia Jan 2, 2025
9ff39c9
Merge branch 'main' into mntor-3825
flozia Jan 2, 2025
bd0974e
chore: Update landing page experiment id
flozia Jan 8, 2025
d8f3fa0
merge: main -> mntor-3825
flozia Jan 8, 2025
de615e7
merge: main -> mntor-3825
flozia Jan 8, 2025
d621af1
Merge branch 'mntor-3825' of github.com:mozilla/blurts-server into mn…
flozia Jan 8, 2025
6b0b4e0
Merge branch 'main' into mntor-3825
flozia Jan 9, 2025
f51bfad
chore: Add unit test coverage for the experiments context provider
flozia Jan 9, 2025
ef97831
chore: Correct telemetry unit test coverage
flozia Jan 9, 2025
ee5768c
merge: Resolve conflicts with main
flozia Jan 9, 2025
fecb559
Merge branch 'main' into mntor-3825
flozia Jan 9, 2025
1245bd4
fix: SCSS update conflict
flozia Jan 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions config/nimbus.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,33 @@ features:
value: { "enabled": true }
- channel: production
value: { "enabled": true }
landing-page-redesign-plus-eligible-experiment:
description: Landing page redesign
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if this might be confusing later, could we give it a more unique name? Do we ever remove these?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point — I’ve updated the experiment ID to be a bit more explicit in bd0974e.

variables:
enabled:
description: If the feature is enabled
type: Boolean
default: false
variant:
description: The landing page variant to show
type: LandingPageVariant
default: default
defaults:
- channel: local
value: {
"enabled": true,
"variant": redesign,
}
- channel: staging
value: {
"enabled": false,
"variant": default,
}
- channel: production
value: {
"enabled": false,
"variant": default,
}
enums:
OptionalBrokerScanInfoFields:
description: An enum of optional broker scan info fields
Expand All @@ -122,3 +149,10 @@ enums:
description: Only show a CTA button with the label “Get free scan”
ctaOnlyAlternativeLabel:
description: Only show a CTA button with the label “Sign up to get free scan”
LandingPageVariant:
description: An enum of landing page variants
variants:
default:
description: Show the default landing page
redesign:
description: Show the redesigned landing page
55 changes: 28 additions & 27 deletions src/app/(proper_react)/(redesign)/(public)/LandingView.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,57 @@
flex-direction: column;
height: 100%;
}

.waitlistSection {
display: flex;
flex-direction: column;
align-items: center;
gap: tokens.$spacing-lg;
padding: tokens.$layout-md tokens.$spacing-md;

.waitlistTitle {
text-align: center;
font: tokens.$text-title-2xs;
font-weight: 600;
line-height: 1.4;
font-family: var(--font-inter);
color: tokens.$color-purple-70;
}

a {
align-self: center;
}
}

.navbar {
font: tokens.$text-body-xl;
padding: tokens.$layout-xs;
display: flex;
flex-direction: row;
justify-content: flex-start;
background-color: tokens.$color-grey-05;
.navbarLinksContainer {
ul {
display: flex;
flex-direction: column;
.navbarLinks {
a {
text-decoration: none;
color: tokens.$color-grey-50;
}
}
@media screen and (min-width: tokens.$screen-sm) {
justify-content: flex-end;
.navbarLinksContainer {
ul {
flex-direction: row;
justify-content: flex-end;
.navbarLinks {
a {
margin-left: tokens.$spacing-lg;
}
}
}
@media screen and (min-width: tokens.$screen-md) {
padding: tokens.$layout-xs tokens.$layout-xl;
.navbarLinksContainer {
.navbarLinks {
ul {
a {
margin-left: tokens.$spacing-xl;
}
}
Expand Down Expand Up @@ -396,24 +418,3 @@
align-self: center;
}
}

.waitlistSection {
display: flex;
flex-direction: column;
align-items: center;
gap: tokens.$spacing-lg;
padding: tokens.$layout-md tokens.$spacing-md;

.waitlistTitle {
text-align: center;
font: tokens.$text-title-2xs;
font-weight: 600;
line-height: 1.4;
font-family: var(--font-inter);
color: tokens.$color-purple-70;
}

a {
align-self: center;
}
}
15 changes: 13 additions & 2 deletions src/app/(proper_react)/(redesign)/(public)/LandingView.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { AccountsMetricsFlowProvider } from "../../../../contextProviders/accoun
import { CONST_URL_MONITOR_LANDING_PAGE_ID } from "../../../../constants";

const meta: Meta<typeof View> = {
title: "Pages/Public/Landing page",
title: "Pages/Public/Landing page/Default",
component: (props: ViewProps) => {
const experimentData =
props.experimentData ?? defaultExperimentData["Features"];
Expand All @@ -31,7 +31,18 @@ const meta: Meta<typeof View> = {
service: process.env.OAUTH_CLIENT_ID as string,
}}
>
<PublicShell l10n={getL10n("en")} countryCode={props.countryCode}>
<PublicShell
l10n={getL10n("en")}
countryCode={props.countryCode}
enabledFeatureFlags={[]}
experimentData={{
...defaultExperimentData["Features"],
"landing-page-redesign-plus-eligible-experiment": {
enabled: false,
variant: "default",
},
}}
>
<View {...props} experimentData={experimentData} />
</PublicShell>
</AccountsMetricsFlowProvider>
Expand Down
55 changes: 7 additions & 48 deletions src/app/(proper_react)/(redesign)/(public)/LandingView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@ import { TelemetryLink } from "../../../components/client/TelemetryLink";
import { HeresHowWeHelp } from "./HeresHowWeHelp";
import { ScanLimit } from "./ScanLimit";
import { FaqSection } from "./Faq";
import { AccountDeletionNotification } from "./AccountDeletionNotification";
import { ExperimentData } from "../../../../telemetry/generated/nimbus/experiments";
import { FreeScanCta } from "./FreeScanCta";
import { TopNavBar } from "./TopNavBar";
import { AccountDeletionNotification } from "./AccountDeletionNotification";

export type Props = {
eligibleForPremium: boolean;
Expand All @@ -43,7 +44,11 @@ export const View = (props: Props) => {
<>
<AccountDeletionNotification />
<main className={styles.wrapper}>
{props.eligibleForPremium && <TopNavBar l10n={props.l10n} />}
{props.eligibleForPremium && (
<div className={styles.navbar}>
<TopNavBar />
</div>
)}
<header className={styles.hero}>
<div className={styles.heroContent}>
<h1>{props.l10n.getString("landing-all-hero-title")}</h1>
Expand Down Expand Up @@ -258,52 +263,6 @@ export const View = (props: Props) => {
);
};

export const TopNavBar = ({ l10n }: { l10n: ExtendedReactLocalization }) => {
return (
<div className={styles.navbar}>
<div className={styles.navbarLinksContainer}>
<TelemetryLink
className={styles.navbarLinks}
href="/how-it-works"
eventData={{
link_id: "navbar_how_it_works",
}}
>
{l10n.getString("landing-premium-hero-navbar-link-how-it-works")}
</TelemetryLink>
<TelemetryLink
className={styles.navbarLinks}
href="#pricing"
eventData={{
link_id: "navbar_pricing",
}}
>
{l10n.getString("landing-premium-hero-navbar-link-pricing")}
</TelemetryLink>
<TelemetryLink
data-testid="navbar_faqs"
className={styles.navbarLinks}
href="#faq"
eventData={{
link_id: "navbar_faqs",
}}
>
{l10n.getString("landing-premium-hero-navbar-link-faqs")}
</TelemetryLink>
<TelemetryLink
className={styles.navbarLinks}
href="/breaches"
eventData={{
link_id: "navbar_recent_breaches",
}}
>
{l10n.getString("landing-premium-hero-navbar-link-recent-breaches")}
</TelemetryLink>
</div>
</div>
);
};

const HeroImage = (props: Props) => {
if (!props.eligibleForPremium) {
return (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
@import "../../../tokens";

.wrapper {
display: flex;
flex-direction: column;
height: 100%;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

import type { Meta, StoryObj } from "@storybook/react";
import { View, Props as ViewProps } from "./LandingViewRedesign";
import { getL10n } from "../../../functions/l10n/storybookAndJest";
import { PublicShell } from "./PublicShell";
import { defaultExperimentData } from "../../../../telemetry/generated/nimbus/experiments";
import { AccountsMetricsFlowProvider } from "../../../../contextProviders/accounts-metrics-flow";
import { CONST_URL_MONITOR_LANDING_PAGE_ID } from "../../../../constants";

const meta: Meta<typeof View> = {
title: "Pages/Public/Landing page/Redesign",
component: (props: ViewProps) => {
const experimentData =
props.experimentData ?? defaultExperimentData["Features"];
return (
<AccountsMetricsFlowProvider
enabled={
experimentData["landing-page-redesign-plus-eligible-experiment"]
.enabled
}
metricsFlowParams={{
entrypoint: CONST_URL_MONITOR_LANDING_PAGE_ID,
entrypoint_experiment:
"landing-page-redesign-plus-eligible-experiment",
entrypoint_variation:
experimentData["landing-page-redesign-plus-eligible-experiment"]
.variant,
form_type: "email",
service: process.env.OAUTH_CLIENT_ID as string,
}}
>
<PublicShell
l10n={getL10n("en")}
countryCode={props.countryCode}
enabledFeatureFlags={["LandingPageRedesign"]}
experimentData={{
...defaultExperimentData["Features"],
"landing-page-redesign-plus-eligible-experiment": {
enabled: true,
variant: "redesign",
},
}}
>
<View {...props} experimentData={experimentData} />
</PublicShell>
</AccountsMetricsFlowProvider>
);
},
args: {
l10n: getL10n(),
},
};

export default meta;
type Story = StoryObj<typeof View>;

export const LandingRedesignUs: Story = {
name: "US visitors",
args: {
eligibleForPremium: true,
countryCode: "us",
scanLimitReached: false,
},
};

export const LandingRedesignUsScanLimit: Story = {
name: "US visitors - Scan limit reached",
args: {
eligibleForPremium: true,
countryCode: "us",
scanLimitReached: true,
},
};

export const LandingRedesignNonUs: Story = {
name: "Non-US visitors",
args: {
eligibleForPremium: false,
countryCode: "nz",
},
};

export const LandingRedesignNonUsDe: Story = {
name: "German",
args: {
eligibleForPremium: false,
countryCode: "de",
l10n: getL10n("de"),
},
};

export const LandingRedesignNonUsFr: Story = {
name: "French",
args: {
eligibleForPremium: false,
countryCode: "fr",
l10n: getL10n("fr"),
},
};
Loading
Loading