Skip to content

Commit

Permalink
feat(PGIO-114): Analytics - track important events (#131)
Browse files Browse the repository at this point in the history
* feat: create initial FA events and formating utils
* feat: add events tracking for market details interactions
* feat: add events tracking for our landing and markets list display interactions
* feat: add events tracking to LiFi sDAI widget interaction
* feat: add footer and embed market tracking events
* chore: remove deprecated options from FA Load function
* feat: add bets view and redeem events
* feat: add the news URL to the FA news tracking event
* feat: add devconflict category and banner events
  • Loading branch information
ElRodrigote authored Oct 28, 2024
1 parent c78b054 commit a729c53
Show file tree
Hide file tree
Showing 14 changed files with 226 additions and 31 deletions.
62 changes: 62 additions & 0 deletions analytics/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { SDAI } from '@/constants';

const formatEventName = (eventName: string) =>
eventName.split(' ').join('-').toLocaleLowerCase();

export const FA_EVENTS = {
BETS: {
MY_BETS: 'click/bets/my-bets',
REDEEM: 'click/bets/redeem',
},
DEVCONFLICT: 'click/devconflict-banner',
FOOTER: {
CONNECT: {
DISCORD: 'click/footer/connect/discord',
GITHUB: 'click/footer/connect/github',
X: 'click/footer/connect/x',
},
HOME: 'click/footer/home',
MARKET_CATEGORY: (category: string) => `click/footer/markets/${category}`,
POWERED_BY: {
GNOSIS: 'click/footer/powered-by/gnosis',
GNOSIS_AI: 'click/footer/powered-by/gnosis-ai',
KLEROS: 'click/footer/powered-by/kleros',
REALITY: 'click/footer/powered-by/reality',
},
},
LIFI_WIDGET: {
OPEN: `click/lifi-widget/open-${SDAI.symbol}`,
ROUTE_FAILED: 'click/lifi-widget/route-failed',
ROUTE_SUCCESS: 'click/lifi-widget/route-success',
},
MARKETS: {
CATEGORY: (category: string) => `click/markets/category-${category}`,
DETAILS: {
EMBED: {
COPIED: 'click/markets/details/embed/copied',
ID: 'click/markets/details/embed',
},
ID: (id: string) => `click/markets/details/${id}`,
INFO: {
CONTRACT: 'click/markets/details/info/chain-scanner',
DISPUTE: 'click/markets/details/info/kleros',
ORACLE_ANSWER: 'click/markets/details/info/reality',
},
TABS: {
NAME: (tabName: string) => `click/markets/details/tabs/${tabName}`,
NEWS_ARTICLE: 'click/markets/details/tabs/news-article',
},
},
FILTERS: {
CREATOR: (creatorName: string) =>
`click/markets/filters/creator-${formatEventName(creatorName)}`,
ORDER: (orderName: string) =>
`click/markets/filters/order-${formatEventName(orderName)}`,
STATE: (stateName: string) =>
`click/markets/filters/state-${formatEventName(stateName)}`,
TOKEN: (tokenName: string) =>
`click/markets/filters/token-${formatEventName(tokenName)}`,
},
SEARCH_BAR: `click/markets/search-bar`,
},
};
9 changes: 8 additions & 1 deletion app/(main)/markets/HistorySection.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Icon, TabBody, TabGroup, TabHeader, TabPanel, TabStyled } from '@swapr/ui';
import { trackEvent } from 'fathom-client';

import { FA_EVENTS } from '@/analytics';
import { ActivityChart } from '@/app/(main)/markets/ActivityChart';
import { MarketActivity } from '@/app/(main)/markets/MarketActivity';

Expand All @@ -16,7 +18,12 @@ export const HistorySection = ({ id }: HistorySectionProps) => {
<Icon size={18} name="activity"></Icon>
<p>Activity</p>
</TabStyled>
<TabStyled className="space-x-2">
<TabStyled
className="space-x-2"
onClick={() =>
trackEvent(FA_EVENTS.MARKETS.DETAILS.TABS.NAME('history-charts'))
}
>
<Icon size={18} name="pie-chart"></Icon>
<p>Charts</p>
</TabStyled>
Expand Down
20 changes: 16 additions & 4 deletions app/(main)/markets/Info.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
import { useState } from 'react';

import { Icon, IconButton } from '@swapr/ui';
import { trackEvent } from 'fathom-client';

import { FA_EVENTS } from '@/analytics';
import { GNOSIS_SCAN_URL, KLEROS_URL, REALITY_QUESTION_URL } from '@/constants';
import { shortenAddress } from '@/utils';
import { FixedProductMarketMaker } from '@/queries/omen';
import { shortenAddress } from '@/utils';

interface InfoProps {
fixedProductMarketMaker: FixedProductMarketMaker;
}
export const Info = ({ fixedProductMarketMaker }: InfoProps) => {
const [clipboardIcon, setClipboardIcon] = useState<'copy' | 'tick'>('copy');
const id = fixedProductMarketMaker.id;
const questionId = fixedProductMarketMaker.question?.id;

return (
<>
Expand All @@ -33,15 +38,17 @@ export const Info = ({ fixedProductMarketMaker }: InfoProps) => {
href={`${GNOSIS_SCAN_URL}/address/${id}`}
target="_blank"
className="flex items-center space-x-1 py-4"
onClick={() => trackEvent(FA_EVENTS.MARKETS.DETAILS.INFO.CONTRACT)}
>
<span>View market contract</span>
<Icon name="arrow-top-right" size={16} />
</a>
{fixedProductMarketMaker.question && (
{questionId && (
<a
href={`${REALITY_QUESTION_URL}${fixedProductMarketMaker.question.id}`}
href={`${REALITY_QUESTION_URL}${questionId}`}
target="_blank"
className="flex items-center space-x-1 py-4"
onClick={() => trackEvent(FA_EVENTS.MARKETS.DETAILS.INFO.ORACLE_ANSWER)}
>
<p>
<span>
Expand All @@ -51,7 +58,12 @@ export const Info = ({ fixedProductMarketMaker }: InfoProps) => {
<Icon name="arrow-top-right" size={16} />
</a>
)}
<a href={KLEROS_URL} target="_blank" className="flex items-center space-x-1 py-4">
<a
href={KLEROS_URL}
target="_blank"
className="flex items-center space-x-1 py-4"
onClick={() => trackEvent(FA_EVENTS.MARKETS.DETAILS.INFO.DISPUTE)}
>
<p>
<span>
Dispute resolution by <span className="font-bold">kleros.io</span>
Expand Down
8 changes: 7 additions & 1 deletion app/(main)/markets/MarketDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
Skeleton,
TokenLogo,
} from '@/app/components';
import { trackEvent } from 'fathom-client';
import { useQuery } from '@tanstack/react-query';
import { getMarket } from '@/queries/omen';
import { IconButton, Tag, ToggleGroup, ToggleGroupOption } from '@swapr/ui';
Expand All @@ -19,6 +20,7 @@ import { HistorySection } from './HistorySection';
import { News } from './News';
import { Info } from './Info';
import { Bet } from './Bet';
import { FA_EVENTS } from '@/analytics';
import { ModalId, useModal } from '@/context';
import { EmbedMarketModal } from '@/app/components/EmbedMarketModal';
import { formatValueWithFixedDecimals } from '@/utils';
Expand Down Expand Up @@ -59,7 +61,10 @@ export const MarketDetails = ({ id }: MarketDetailsProps) => {
name="code"
variant="pastel"
size="sm"
onClick={() => openModal(ModalId.EMBED_MARKET)}
onClick={() => {
trackEvent(FA_EVENTS.MARKETS.DETAILS.EMBED.ID);
openModal(ModalId.EMBED_MARKET);
}}
/>
</div>
<div className="w-full rounded-16 border border-outline-base-em bg-surface-surface-0">
Expand Down Expand Up @@ -131,6 +136,7 @@ export const MarketDetails = ({ id }: MarketDetailsProps) => {
size="md"
value={tab}
className="flex justify-center font-semibold capitalize"
onClick={() => trackEvent(FA_EVENTS.MARKETS.DETAILS.TABS.NAME(tab))}
>
{tab}
</ToggleGroupOption>
Expand Down
3 changes: 3 additions & 0 deletions app/(main)/markets/News.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { useQuery } from '@tanstack/react-query';
import { format, parseISO } from 'date-fns';
import { trackEvent } from 'fathom-client';
import Image from 'next/image';

import { FA_EVENTS } from '@/analytics';
import { Skeleton } from '@/app/components';

interface NewsProps {
Expand Down Expand Up @@ -77,6 +79,7 @@ const NewsArticle = ({ url, title }: NewsArticleProps) => {
href={url}
target="_blank"
rel="noopener noreferrer"
onClick={() => trackEvent(FA_EVENTS.MARKETS.DETAILS.TABS.NEWS_ARTICLE)}
>
{data?.ogImage ? (
<Image
Expand Down
42 changes: 36 additions & 6 deletions app/(main)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,12 @@ import {
} from './filters';
import { isAddress } from 'viem';
import Image from 'next/image';
import { trackEvent } from 'fathom-client';

import { FA_EVENTS } from '@/analytics';
import { getOpenMarkets } from '@/queries/dune';
import { Categories } from '@/constants';

import { MarketsHighlight } from './MarketsHighlight';
import { DevconflictBanner } from '@/app/components/Devconflict';

Expand Down Expand Up @@ -290,13 +294,19 @@ export default function HomePage() {
onChange={handleCategory}
className="overflow-x-auto md:w-auto lg:w-fit"
>
<ToggleGroupOption size="md" value="" className="font-semibold">
<ToggleGroupOption
size="md"
value=""
className="font-semibold"
onClick={() => trackEvent(FA_EVENTS.MARKETS.CATEGORY('all'))}
>
All
</ToggleGroupOption>
<ToggleGroupOption
size="md"
value="devconflict"
className="font-semibold text-outline-primary-high-em"
onClick={() => trackEvent(FA_EVENTS.MARKETS.CATEGORY('devconflict'))}
>
Devconflict
</ToggleGroupOption>
Expand All @@ -311,6 +321,9 @@ export default function HomePage() {
value={categoryOption}
className="font-semibold capitalize"
size="md"
onClick={() =>
trackEvent(FA_EVENTS.MARKETS.CATEGORY(categoryOption as string))
}
>
{categoryOption}
</ToggleGroupOption>
Expand All @@ -325,6 +338,7 @@ export default function HomePage() {
placeholder="Search markets keywords or address"
leftIcon="search"
onChange={event => handleSearch(event.target.value)}
onClick={() => trackEvent(FA_EVENTS.MARKETS.SEARCH_BAR)}
value={search}
/>
{showClientUI ? (
Expand All @@ -342,7 +356,10 @@ export default function HomePage() {
{creatorFilters.map(option => (
<div
key={option.key}
onClick={() => selectCreatorFilter(option)}
onClick={() => {
selectCreatorFilter(option);
trackEvent(FA_EVENTS.MARKETS.FILTERS.CREATOR(option.name));
}}
className="flex cursor-pointer items-center justify-start space-x-2 px-3 py-2 font-semibold"
>
<Icon
Expand Down Expand Up @@ -382,7 +399,10 @@ export default function HomePage() {
{tokenFilters.map(option => (
<div
key={option.key}
onClick={() => selectTokenFilter(option)}
onClick={() => {
selectTokenFilter(option);
trackEvent(FA_EVENTS.MARKETS.FILTERS.TOKEN(option.name));
}}
className="flex cursor-pointer items-center justify-start space-x-2 px-3 py-2 font-semibold"
>
<Icon
Expand Down Expand Up @@ -417,7 +437,10 @@ export default function HomePage() {
{orderFilters.map(option => (
<div
key={option.key}
onClick={() => selectOrderFilter(option)}
onClick={() => {
selectOrderFilter(option);
trackEvent(FA_EVENTS.MARKETS.FILTERS.ORDER(option.name));
}}
className="flex cursor-pointer items-center justify-start space-x-2 px-3 py-2 font-semibold"
>
<Icon
Expand Down Expand Up @@ -453,7 +476,10 @@ export default function HomePage() {
{stateFilters.map(option => (
<div
key={option.key}
onClick={() => selectStateFilter(option)}
onClick={() => {
selectStateFilter(option);
trackEvent(FA_EVENTS.MARKETS.FILTERS.STATE(option.name));
}}
className="flex cursor-pointer items-center justify-start space-x-2 px-3 py-2 font-semibold"
>
<Icon
Expand Down Expand Up @@ -483,7 +509,11 @@ export default function HomePage() {
) : markets?.length ? (
<div className="grid w-full grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4">
{markets.map(market => (
<Link key={market.id} href={`markets?id=${market.id}`}>
<Link
key={market.id}
href={`markets?id=${market.id}`}
onClick={() => trackEvent(FA_EVENTS.MARKETS.DETAILS.ID(market.id))}
>
<CardMarket market={market} />
</Link>
))}
Expand Down
3 changes: 3 additions & 0 deletions app/components/CardBet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@

import { PropsWithChildren } from 'react';
import { cx } from 'class-variance-authority';
import { trackEvent } from 'fathom-client';
import Link from 'next/link';

import { Button, Tag } from '@swapr/ui';
import { Card, TokenLogo } from '@/app/components';

import { FA_EVENTS } from '@/analytics';
import { formatDateTimeWithYear, remainingTime } from '@/utils/dates';
import {
Market,
Expand Down Expand Up @@ -167,6 +169,7 @@ export const MyBetsCardBet = ({ userBets }: { userBets: UserBets }) => {
collateralToken: userBets.position.collateralTokenAddress,
})
);
trackEvent(FA_EVENTS.BETS.REDEEM);
};

return (
Expand Down
11 changes: 10 additions & 1 deletion app/components/Devconflict.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
import { trackEvent } from 'fathom-client';

import { FA_EVENTS } from '@/analytics';

export const DevconflictBanner = () => (
<a href="https://devconflict.com/" className="w-full cursor-pointer" target="_blank">
<a
href="https://devconflict.com/"
className="w-full cursor-pointer"
target="_blank"
onClick={() => trackEvent(FA_EVENTS.DEVCONFLICT)}
>
<div className="flex w-full flex-wrap items-center justify-between gap-x-6 gap-y-8 rounded-12 border border-outline-primary-low-em bg-[#948e9474] px-6 py-5 text-center font-medium text-[#000] dark:border-outline-primary-base-em dark:bg-[#b4b3b3cc] md:gap-4 lg:gap-1">
<DevconflictLogoSvg />
<p className="text-md">
Expand Down
3 changes: 3 additions & 0 deletions app/components/EmbedMarketModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@ import {
PopoverContent,
PopoverTrigger,
} from '@swapr/ui';
import { FA_EVENTS } from '@/analytics';
import { ModalId, useModal } from '@/context/ModalContext';
import { APP_URL } from '@/constants';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { atomDark } from 'react-syntax-highlighter/dist/esm/styles/prism';
import { useMemo, useState } from 'react';
import { cx } from 'class-variance-authority';
import { trackEvent } from 'fathom-client';
import { isMobile } from 'react-device-detect';
import { Address } from 'viem';

Expand Down Expand Up @@ -105,6 +107,7 @@ export const EmbedMarketModal = ({ id }: EmbedMarketModalProps) => {
onClick={() => {
navigator.clipboard.writeText(iframeCode);
setClipboardIcon('tick');
trackEvent(FA_EVENTS.MARKETS.DETAILS.EMBED.COPIED);

setTimeout(() => {
setClipboardIcon('copy');
Expand Down
Loading

0 comments on commit a729c53

Please sign in to comment.