Skip to content

Commit

Permalink
[SWA-198][INFRA] - Track click events on Landing page "Launch App" bu…
Browse files Browse the repository at this point in the history
…ttons (#130)

* infra(STK-198): apply click tracking to Launch App buttons
* infra(STK-198): update FAQ section structure to support QA abstraction and FA events
  • Loading branch information
ElRodrigote authored and berteotti committed Nov 9, 2023
1 parent 6ddef2c commit 826ceed
Show file tree
Hide file tree
Showing 26 changed files with 442 additions and 176 deletions.
1 change: 1 addition & 0 deletions packages/landing/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
NEXT_PUBLIC_FATHOM_SITE_ID=
32 changes: 32 additions & 0 deletions packages/landing/analytics/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
const LAUNCH_APP = "click/launch-app";
const LAUNCH_APP_NAVBAR = `${LAUNCH_APP}-navbar`;
const FAQ = "click/faq";
const FAQ_WHAT_IS = `${FAQ}-what-is`;
const FAQ_HOW = `${FAQ}-how`;

export const EVENTS = {
NAVBAR: {
DESKTOP: {
LAUNCH_APP_CLICK: `${LAUNCH_APP_NAVBAR}-desktop`,
},
MOBILE: {
LAUNCH_APP_CLICK: `${LAUNCH_APP_NAVBAR}-mobile`,
},
},
SECTIONS: {
FAQ: {
HOW_CANCEL_STACK: `${FAQ_HOW}-cancel-stack`,
HOW_STACKLY_WORKS: `${FAQ_HOW}-stackly-works`,
WHAT_IS_STACKLY_CLICK: `${FAQ_WHAT_IS}-stackly`,
WHAT_IS_STACK_CLICK: `${FAQ_WHAT_IS}-stack`,
WHAT_IS_DCA: `${FAQ_WHAT_IS}-dca`,
WHY_TO_DCA: `${FAQ}-why-to-dca`,
},
HERO_BANNER: {
STACK_NOW_CLICK: `${LAUNCH_APP}-hero-banner`,
},
TRY_STACKLY_BANNER: {
TRY_STACKLY_NOW_CLICK: `${LAUNCH_APP}-try-stackly-banner`,
},
},
};
2 changes: 2 additions & 0 deletions packages/landing/analytics/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./constants";
export * from "./types";
25 changes: 25 additions & 0 deletions packages/landing/analytics/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
type PageViewOptions = {
referrer?: string;
url?: string;
};

export type EventName = string;

export type EventOptions = {
_site_id?: string;
_value?: number;
};

export interface Fathom {
blockTrackingForMe: () => void;
enableTrackingForMe: () => void;
setSite: (siteId: string) => void;
trackEvent(eventId: string, opts?: EventOptions): void;
trackPageview: (opts?: PageViewOptions) => void;
}

declare global {
interface Window {
fathom: Fathom;
}
}
21 changes: 18 additions & 3 deletions packages/landing/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { Metadata } from "next";
import localFont from "next/font/local";
import { Metadata } from "next";
import Script from "next/script";

import { Navbar } from "@/components";
import { Providers } from "@/providers";
import { STACKLY_LANDING_URL } from "@/constants";

import "@/styles/global.css";

const stabilGrotesk = localFont({
Expand Down Expand Up @@ -34,6 +37,8 @@ export const metadata: Metadata = {
"Stackly is a simple, non-custodial tool that uses the CoW protocol to place recurring swaps based on DCA",
};

const siteId = process.env.NEXT_PUBLIC_FATHOM_SITE_ID;

export default function RootLayout({
children,
}: {
Expand All @@ -42,8 +47,18 @@ export default function RootLayout({
return (
<html lang="en" className={stabilGrotesk.variable}>
<body className="font-sans bg-surface-25 text-em-high">
<Navbar />
{children}
<Script
src="https://cdn.usefathom.com/script.js"
data-auto
data-site={siteId}
data-spa="hash"
defer
/>

<Providers>
<Navbar />
{children}
</Providers>
</body>
</html>
);
Expand Down
137 changes: 7 additions & 130 deletions packages/landing/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,97 +1,21 @@
import { PropsWithChildren } from "react";

import Link from "next/link";
import Image from "next/image";

import { BodyText, ButtonLink, HeadingText, Icon } from "@/ui";
import {
BodyText,
ButtonLink,
DisplayText,
HeadingText,
Icon,
TitleText,
} from "@/ui";
import {
STACKLY_APP_URL,
STACKLY_DISCORD_URL,
STACKLY_TWITTER_URL,
SWAPR_URL,
} from "@/constants";
import { StacklyLogoIcon } from "@/public/assets";
import { PropsWithChildren } from "react";
import { QAndAAccordion, TryStacklyBanner } from "@/components";
import { FAQ, HeroBanner, TryStacklyBanner } from "@/components";

export default function Home() {
return (
<main>
<section className="px-6 pt-16 border-b border-gray-100 md:pt-20">
<div className="space-y-4 text-center md:space-y-6 ">
<DisplayText>DCA simplified</DisplayText>
<HeadingText className="!font-medium text-em-med max-w-2xl mx-auto">
Say goodbye to market timing and hello to effortless recurrent
swaps.
</HeadingText>
</div>
<ButtonLink
target="_blank"
href={STACKLY_APP_URL}
size="lg"
width="fit"
className="!py-4 mx-auto text-lg !px-16 md:!px-28 mt-8"
>
Stack now
</ButtonLink>
<div className="relative max-w-4xl mx-auto mt-12 mb-24 md:my-20">
<Link
passHref
href={STACKLY_APP_URL}
className="relative block mx-auto w-fit"
>
<div className="invisible sm:visible absolute w-[3px] h-[26px] bg-em-med bottom-[60px] left-[17px] animate-cursor-blink"></div>
<Image
className="mx-auto border shadow-xl hover:shadow-2xl rounded-2xl border-surface-50"
alt="amount widget"
src="/assets/images/landing-widget.png"
height={200}
width={512}
/>
</Link>
<div className="absolute w-full -top-36 -z-10 h-[460px] md:bg-radial-gradient"></div>
</div>
<Link
href="https://ipfs.io/ipfs/QmUmmFkKvktZ14iA3237WuDrzNuhi4BMb4MoYMJHeFFbey"
target="_blank"
>
<div className="mx-auto flex items-center px-5 py-3 bg-primary-50 rounded-[20px] w-fit space-x-3 my-20 shadow-sm hover:shadow-md hover:bg-primary-75">
<Icon name="check" className="text-primary-600" />
<TitleText>Stackly has undergone an audit by Omega.</TitleText>
<Image
alt="omega team logo"
src="/assets/images/omega-team-logo.svg"
height={30}
width={30}
/>
</div>
</Link>

{false && (
<div className="mx-auto flex items-center px-5 py-2 bg-black/5 rounded-[20px] w-fit space-x-6 mt-20">
<div className="flex items-center space-x-2">
<BodyText size={3} weight="medium" className="text-em-med">
Total Stacks created:
</BodyText>
<BodyText size={3} weight="bold">
732
</BodyText>
</div>
<div className="flex items-center space-x-2">
<BodyText size={3} weight="medium" className="text-em-med">
Total transactions:
</BodyText>
<BodyText size={3} weight="bold">
1232
</BodyText>
</div>
</div>
)}
</section>
<HeroBanner />
<section
className="py-20 bg-white border-b border-gray-100 md:py-32"
id="how-it-works"
Expand Down Expand Up @@ -136,54 +60,7 @@ export default function Home() {
</div>
</div>
</section>
<section className="px-6 py-12 md:py-32" id="faqs">
<div className="max-w-6xl mx-auto">
<div className="flex flex-col md:flex-row md:justify-between">
<HeadingText size={4} className="pb-10 md:pb-0">
Frequently asked questions
</HeadingText>
<div className="w-full max-w-lg space-y-4">
<QAndAAccordion question="What is Stackly?" startOpen>
Stackly is a simple non-custodial DCA app that makes it easy to
do recurring swaps of any token.
</QAndAAccordion>
<QAndAAccordion question="What is a stack?">
<p>
We call it stack the creation of the recurrent order with the
total amount that will be used to swap the choosen tokens on
the choosen frequency (hourly, daily, etc).
</p>
<p>
Example: A stack of WETH using 500WXDAI that will do recurrent
swaps every day till the end of the week.
</p>
</QAndAAccordion>
<QAndAAccordion question="How does Stackly work?">
When you stack a token, stackly creates a contract for you with
the funds and uses CoW protocol to place recurring orders
(stacks) at the frequency you choose.
</QAndAAccordion>
<QAndAAccordion question="What is DCA?">
DCA stands for Dollar-Cost Averaging, which is an investment
strategy used in the financial markets. DCA involves regularly
investing a fixed amount of money at predetermined intervals,
regardless of the {"asset's"} price.
</QAndAAccordion>
<QAndAAccordion question="Why one should do DCA?">
Recurring swaps (aka DCA) remove the need to time the market,
neutralising the short term market volatility, and helps you
build a portfolio, distributed over a period of time.
</QAndAAccordion>
<QAndAAccordion question="Can I cancel my stacks?">
Yes. You can cancel your stacks anytime. Your funds will be
withdrawn immediately to your wallet. To do it, you have to
connect your wallet, go to your stacks, choose a stack, click
cancel and confirm transaction with your wallet.
</QAndAAccordion>
</div>
</div>
</div>
</section>
<FAQ />
<section className="px-6 mx-auto mb-20 max-w-7xl lg:px-0 md:mb-32">
<TryStacklyBanner />
</section>
Expand Down
1 change: 0 additions & 1 deletion packages/landing/components/QAndAAccordion/index.ts

This file was deleted.

24 changes: 0 additions & 24 deletions packages/landing/components/TryStacklyBanner/TryStacklyBanner.tsx

This file was deleted.

3 changes: 1 addition & 2 deletions packages/landing/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
export * from "./navbar";
export * from "./QAndAAccordion";
export * from "./TryStacklyBanner";
export * from "./sections";
9 changes: 8 additions & 1 deletion packages/landing/components/navbar/MobileMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
"use client";

import { useState } from "react";

import Link from "next/link";

import { Button, ButtonLink } from "@/ui";
import { EVENTS } from "@/analytics";
import { STACKLY_APP_URL } from "@/constants";
import { useFathomAnalytics } from "@/contexts";

export default function MobileMenu({
passedThresholdHeight,
}: {
passedThresholdHeight: boolean;
}) {
const [isOpen, setIsOpen] = useState(false);
const { trackClick } = useFathomAnalytics();

const toggle = () => setIsOpen(!isOpen);

Expand All @@ -20,7 +25,9 @@ export default function MobileMenu({
target="_blank"
variant={passedThresholdHeight ? "primary" : "secondary"}
href={STACKLY_APP_URL}
onClick={toggle}
onClick={() => {
trackClick(EVENTS.NAVBAR.MOBILE.LAUNCH_APP_CLICK);
}}
>
Launch app
</ButtonLink>
Expand Down
15 changes: 12 additions & 3 deletions packages/landing/components/navbar/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
"use client";

import { useEffect, useState } from "react";

import Link from "next/link";
import MobileMenu from "./MobileMenu";

import { EVENTS } from "@/analytics";
import { ButtonLink } from "@/ui";
import Logo from "./Logo";
import { STACKLY_APP_URL } from "@/constants";
import { useEffect, useRef, useState } from "react";
import { useFathomAnalytics } from "@/contexts";

import MobileMenu from "./MobileMenu";
import Logo from "./Logo";

const THRESHOLD_HEIGHT = 320;

export function Navbar() {
const [scrollYPos, setScrollYPos] = useState(0);
const { trackClick } = useFathomAnalytics();

useEffect(() => {
const handleScroll = () => {
Expand Down Expand Up @@ -51,6 +57,9 @@ export function Navbar() {
target="_blank"
variant={passedThresholdHeight ? "primary" : "quaternary"}
href={STACKLY_APP_URL}
onClick={() => {
trackClick(EVENTS.NAVBAR.DESKTOP.LAUNCH_APP_CLICK);
}}
>
Launch app
</ButtonLink>
Expand Down
Loading

0 comments on commit 826ceed

Please sign in to comment.