Skip to content

Commit

Permalink
Signed out home-page variations
Browse files Browse the repository at this point in the history
  • Loading branch information
IanPhilips committed Mar 13, 2024
1 parent 0805dd7 commit c91f698
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 43 deletions.
48 changes: 48 additions & 0 deletions web/components/home/typewriter.tsx
@@ -0,0 +1,48 @@
import { useEffect, useRef } from 'react'

export const Typewriter = (props: { words: string[] }) => {
const { words } = props
const typingElement = useRef<HTMLSpanElement>(null)
const wordIndex = useRef(0)
const charIndex = useRef(0)
const deleteTimeout = 2000
const typeTimeout = 100

useEffect(() => {
typeWords()
}, [])

const typeWords = () => {
if (typingElement.current) {
if (charIndex.current < words[wordIndex.current].length) {
typingElement.current.textContent =
words[wordIndex.current].substring(0, charIndex.current) + '_'
charIndex.current++
setTimeout(typeWords, typeTimeout)
} else {
typingElement.current.textContent = words[wordIndex.current]
setTimeout(eraseWords, deleteTimeout)
}
}
}

const eraseWords = () => {
if (typingElement.current) {
if (charIndex.current > 0) {
typingElement.current.textContent =
words[wordIndex.current].substring(0, charIndex.current - 1) + '_'
charIndex.current--
setTimeout(eraseWords, 50)
} else {
wordIndex.current++
if (wordIndex.current >= words.length) {
wordIndex.current = 0
}
charIndex.current = 0
setTimeout(typeWords, 500)
}
}
}

return <span className={'min-h-5'} ref={typingElement}></span>
}
10 changes: 5 additions & 5 deletions web/hooks/use-ab-test.ts
Expand Up @@ -8,7 +8,7 @@ const AB_TEST_CACHE: { [testName: string]: boolean } = {}

export const useABTest = <T>(
testName: string,
variants: { [variantName: string]: T },
variants: T[],
trackingProperties?: any
) => {
const [variant, setVariant] = useState<T | undefined>(undefined)
Expand All @@ -18,16 +18,16 @@ export const useABTest = <T>(
if (!deviceId) return

const rand = createRNG(testName + deviceId)
const keys = Object.keys(variants).sort()
const key = keys[Math.floor(rand() * keys.length)]
const keys = variants.sort()
const randomVariant = keys[Math.floor(rand() * keys.length)]

setVariant(variants[key])
setVariant(randomVariant)

// only track once per user session
if (!AB_TEST_CACHE[testName]) {
AB_TEST_CACHE[testName] = true

track(testName, { ...trackingProperties, variant: key })
track(testName, { ...trackingProperties, variant })
}
}, [testName, trackingProperties, variants])

Expand Down
8 changes: 0 additions & 8 deletions web/hooks/use-is-feed-test.ts

This file was deleted.

113 changes: 83 additions & 30 deletions web/pages/index.tsx
Expand Up @@ -11,9 +11,7 @@ import { firebaseLogin } from 'web/lib/firebase/users'
import { Button } from 'web/components/buttons/button'
import { redirectIfLoggedIn } from 'web/lib/firebase/server-auth'
import { AboutPrivacyTerms } from 'web/components/privacy-terms'
import { formatMoney } from 'common/util/format'
import { useRedirectIfSignedIn } from 'web/hooks/use-redirect-if-signed-in'
import { MARKET_VISIT_BONUS_TOTAL, STARTING_BALANCE } from 'common/economy'
import { ManifoldLogo } from 'web/components/nav/manifold-logo'
import { LogoSEO } from 'web/components/LogoSEO'
import { MobileAppsQRCodeDialog } from 'web/components/buttons/mobile-apps-qr-code-button'
Expand All @@ -26,28 +24,30 @@ import { useUser } from 'web/hooks/use-user'
import { some } from 'd3-array'
import { getContract } from 'web/lib/supabase/contracts'
import { useABTest } from 'web/hooks/use-ab-test'
import { Typewriter } from 'web/components/home/typewriter'
import { filterDefined } from 'common/util/array'

const excluded = [...DEEMPHASIZED_GROUP_SLUGS, 'manifold-6748e065087e']

export const getServerSideProps = redirectIfLoggedIn('/home', async (_) => {
const { data } = await db
.from('trending_contracts')
.from('contracts')
.select('data')
.neq('outcome_type', 'STONK')
.gt('data->uniqueBettorCount', 10)
.not(
'outcome_type',
'in',
`(${['STONK', 'BOUNTIED_QUESTION', 'POLL'].join(',')})`
)
.order('importance_score', { ascending: false })
.limit(50)

const contracts = (data ?? []).map((d) => d.data) as Contract[]

const prezContract = await getContract('ikSUiiNS8MwAI75RwEJf')

const filteredContracts = [prezContract, ...contracts]
.filter(
(c) => c && !c.groupSlugs?.some((slug) => excluded.includes(slug as any))
)
.filter(
(c) => c?.outcomeType !== 'POLL' && c?.outcomeType !== 'BOUNTIED_QUESTION'
) as Contract[]
const filteredContracts = filterDefined([prezContract, ...contracts]).filter(
(c) => !c.groupSlugs?.some((slug) => excluded.includes(slug as any))
)

const hasCommonGroupSlug = (contract: Contract, groupSlugsSet: string[]) =>
some(contract.groupSlugs ?? [], (slug) => groupSlugsSet.includes(slug))
Expand Down Expand Up @@ -77,10 +77,13 @@ export default function LandingPage(props: {

const [isModalOpen, setIsModalOpen] = useState(false)

const abTestVariant = useABTest('landing-page-bet-vs-predict', {
bet: 'bet',
predict: 'predict',
})
const abTestVariant = useABTest('signed out home page variations v0', [
'know the future',
'real-world impact',
'wisdom of the crowds',
'bet',
'bet-typewriter',
])

return (
<Page trackPageView={'signed out home page'} hideSidebar>
Expand Down Expand Up @@ -148,6 +151,50 @@ export default function LandingPage(props: {

<Row className="justify-between rounded-lg p-8">
<Col className="max-w-lg gap-2">
{abTestVariant === 'know the future' && (
<>
<h1 className="mb-4 text-4xl">Know the future</h1>
<h1 className="text-lg">
Harness wisdom of the crowds to predict politics, pandemics,
tech breakthroughs & more with
<span className={'ml-1 underline'}>play money</span>.
</h1>
<h1 className="text-lg">
Forecasting for everything that matters.
</h1>
</>
)}
{abTestVariant === 'real-world impact' && (
<>
<h1 className="mb-4 text-4xl">
Play-money betting.
<br />
Real-world impact.
</h1>
<h1 className="text-lg">
Harness humanity's collective intelligence to make smarter
decisions through forecasting.
</h1>
<h1 className="text-lg">
Join a global community betting on a better world.
</h1>
</>
)}
{abTestVariant === 'wisdom of the crowds' && (
<>
<h1 className="mb-4 text-4xl">
Harness the wisdom of the crowds
</h1>
<h1 className="text-lg">
<span className={'underline'}>Play-money</span> betting.{' '}
<span className={'underline'}>Real-world</span> decisions.
</h1>
<h1 className="text-lg">
Shape the world with accurate forecasts for better
decision-making.
</h1>
</>
)}
{abTestVariant === 'bet' && (
<>
<h1 className="mb-4 text-4xl">Bet on politics & more</h1>
Expand All @@ -160,17 +207,27 @@ export default function LandingPage(props: {
</h1>
</>
)}
{abTestVariant !== 'bet' && (
{abTestVariant === 'bet-typewriter' && (
<>
<h1 className="mb-4 text-4xl">
Predict & win internet points
Bet on the next:{' '}
<Row>
<Typewriter
words={[
'election',
'tech breakthrough',
'game',
'bachelor',
]}
/>
</Row>
</h1>
<h1 className="text-lg">
Trade in markets with real-world accuracy.
Play-money betting. Real-world accuracy.
</h1>
<h1 className="text-lg">
Compete with your friends on politics, tech, sports, and
more.
Forecast events in politics, policy, technology, sports &
beyond.
</h1>
</>
)}
Expand All @@ -180,16 +237,12 @@ export default function LandingPage(props: {
className="mt-8"
onClick={firebaseLogin}
>
Start predicting
{abTestVariant === 'know the future'
? 'See the forecasts'
: abTestVariant === 'real-world impact'
? 'Forecast the future'
: 'Start predicting'}
</Button>
<div className="text-md ml-8 ">
...and get{' '}
<span className="z-10 font-semibold">
{formatMoney(STARTING_BALANCE + MARKET_VISIT_BONUS_TOTAL)}
</span>
{' '}
in play money!
</div>
</Col>
<Col className="hidden sm:flex">
<img
Expand Down

0 comments on commit c91f698

Please sign in to comment.