A/B Testing Implementation Guide
Purpose: Technical implementation details for A/B testing on pre-launch landing pages Repository: juniro-web-launch Tool: Posthog (feature flags + analytics) Last Updated: January 2026
Overview
This document covers the technical implementation of A/B testing for the Juniro pre-launch landing pages. For the strategic testing plan and copy variants, see A/B Testing Plan.
Architecture
┌─────────────────────────────────────────────────────────────┐
│ Posthog Feature Flags │
│ parent_headline_variant | parent_cta_variant │
│ provider_headline_variant | provider_cta_variant │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ useABTest.ts Hooks │
│ useParentVariants() | useProviderVariants() │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Landing Pages │
│ page.tsx (parents) | providers/page.tsx │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ WaitlistForm.tsx │
│ Tracks variants on form submission │
└─────────────────────────────────────────────────────────────┘
│
▼
┌────── ───────────────────────────────────────────────────────┐
│ /api/waitlist → Posthog + Loops │
│ Stores variant info for conversion attribution │
└─────────────────────────────────────────────────────────────┘
File Structure
juniro-web-launch/src/
├── config/
│ └── ab-variants.ts # Copy variants configuration
├── hooks/
│ └── useABTest.ts # React hooks for loading variants
├── components/
│ ├── Analytics.tsx # Posthog initialization + helpers
│ └── WaitlistForm.tsx # Form with variant tracking
├── app/
│ ├── page.tsx # Parent landing page (uses variants)
│ ├── providers/page.tsx # Provider landing page (uses variants)
│ └── api/waitlist/route.ts # API with variant tracking
Posthog Feature Flags Setup
Step 1: Create Feature Flags
In Posthog (app.posthog.com) → Feature Flags → New feature flag:
| Flag Name | Variants | Rollout |
|---|---|---|
parent_headline_variant | A: 50%, B: 50% | 100% of users |
parent_cta_variant | A: 50%, B: 50% | 100% of users |
provider_headline_variant | A: 50%, B: 50% | 100% of users |
provider_cta_variant | A: 50%, B: 50% | 100% of users |
Step 2: Configure Each Flag
- Key: Enter flag name exactly as shown above
- Served value: Select "Multiple variants with rollout percentages (A/B/n test)"
- Variant keys:
- Variant key:
A, Rollout:50% - Variant key:
B, Rollout:50%
- Variant key:
- Release conditions: Roll out to
100%of users - Evaluation runtime: "Both client and server"
- Enable feature flag: ✅ Checked
- Create usage dashboard: ✅ Checked
- Click Save
Step 3: Sequential Testing (Recommended)
Run one test at a time for cleaner data:
- Enable only
parent_headline_variant - Disable the other 3 flags
- After 2 weeks, pick winner (set to 100%), enable next flag
To disable a flag: Uncheck "Enable feature flag" and Save.
Copy Variants Configuration
Located in src/config/ab-variants.ts:
Parent Page Variants
| Element | Variant A (Control) | Variant B (Test) |
|---|---|---|
| Headline | "Stop Searching. Start Booking." | "Finding the right activities for your kids shouldn't be this hard." |
| Subheadline | "Find and book the best classes..." | "Trusted activities, reviewed by parents..." |
| CTA | "Get Early Access" | "Notify Me When We Launch" |
| Form Helper | "Be the first to know when we launch" | "Be the first to know when activities open near you" |
| Interest Label | "What activities interest your child?" | "What are you looking for your child right now?" |
Provider Page Variants
| Element | Variant A (Control) | Variant B (Test) |
|---|---|---|
| Headline | "Fill Your Classes. Grow Your Business." | "Get discovered by parents actively looking for activities." |
| Subheadline | "Reach families actively looking..." | "Reach new families without spending on ads..." |
| Inclusion Copy | "Perfect for studios, schools, camps..." | "Built for businesses and independent instructors alike." |
| CTA | "Join as Provider" | "Apply to Join" |
| Scarcity Copy | "Limited early provider slots per city" | "Onboarding providers in your city now" |
| Provider Type Label | "I am a" | "I run a" |
Event Tracking
Events Implemented
| Event | When Fired | Properties |
|---|---|---|
$pageview | Page loads | Auto-captured by Posthog |
ab_variants_loaded | Variants loaded from Posthog | page, headline_variant, cta_variant |
form_start | User clicks email field (once) | userType, headline_variant, cta_variant |
interest_selected | User selects an interest | interest, userType, headline_variant, cta_variant |
form_error | Form submission fails | error_type, userType, headline_variant, cta_variant |
waitlist_signup | Form submitted successfully | userType, city, ab_headline_variant, ab_cta_variant, + more |
Event Flow
User visits page
│
▼
$pageview (auto)
│
▼
ab_variants_loaded (when Posthog flags load)
│
▼
form_start (user clicks email field)
│
├──▶ interest_selected (optional, per interest clicked)
│
▼
Form Submit
│
├──▶ form_error (if failed)
│
└──▶ waitlist_signup (if success) → Redirect to thank-you
Posthog Dashboards Setup
Create these 3 insights in Posthog:
Dashboard 1: Core Funnel
- Go to Insights → New insight → Funnels
- Add steps:
- Step 1:
$pageview - Step 2:
form_start - Step 3:
waitlist_signup
- Step 1:
- Add breakdown:
userType - Add breakdown:
ab_headline_variant - Save as "Core Funnel"
Dashboard 2: Drop-off Analysis
- Go to Insights → New insight → Funnels
- Add steps:
- Step 1:
form_start - Step 2:
form_error
- Step 1:
- Add breakdown:
error_type - Add breakdown:
ab_headline_variant - Save as "Drop-off Analysis"
Dashboard 3: Motivation Signal
- Go to Insights → New insight → Funnels
- Add steps:
- Step 1:
interest_selected - Step 2:
waitlist_signup
- Step 1:
- Add breakdown:
interest - Add breakdown:
city - Save as "Motivation Signal"
Create Combined Dashboard
- Go to Dashboards → New dashboard
- Name: "A/B Testing Analytics"
- Add all 3 saved insights
How Variant Assignment Works
Posthog uses sticky assignment:
- First visit: User assigned to A or B based on anonymous ID (cookie)
- All future visits: Same user always sees same variant
- 50/50 split: Roughly half of unique visitors get A, half get B
To test both variants yourself:
- Variant A: Your current browser
- Variant B: Incognito window or different browser
Picking a Winner
After running a test for 1-2 weeks (or 100+ conversions):
In Posthog:
- Go to Feature Flags → Click the flag
- Check conversion rates by variant in your dashboard
- Update Variant keys:
- Winning variant:
100% - Losing variant:
0%
- Winning variant:
- Click Save
Decision Criteria:
- If one variant clearly wins (>10% improvement): Pick it
- If results are close: Pick whichever feels more honest
- If B wins but feels manipulative: Consider sticking with A
Code Reference
Using Variants in Pages
// Parent page
import { useParentVariants } from '@/hooks/useABTest'
export default function HomePage() {
const ab = useParentVariants()
return (
<h1>
{ab.headline.main}
<span>{ab.headline.highlight}</span>
</h1>
<p>{ab.subheadline}</p>
<WaitlistForm
userType="parent"
ctaText={ab.cta}
interestLabel={ab.interestLabel}
variants={ab.variants}
/>
)
}
Available Hook Returns
// useParentVariants()
{
isLoaded: boolean,
headline: { main: string, highlight: string },
subheadline: string,
cta: string,
formHelper: string,
interestLabel: string,
variants: { headline: 'A' | 'B', cta: 'A' | 'B' }
}
// useProviderVariants()
{
isLoaded: boolean,
headline: { main: string, highlight: string },
subheadline: string,
inclusionCopy: string,
cta: string,
scarcityCopy: string,
providerTypeLabel: string,
variants: { headline: 'A' | 'B', cta: 'A' | 'B' }
}
Troubleshooting
Variants Not Loading
- Check Posthog key is set:
NEXT_PUBLIC_POSTHOG_KEYin.env.local - Verify flag is enabled in Posthog
- Check browser console for Posthog errors
- Default behavior: Shows variant A if flags fail to load
Events Not Appearing in Posthog
- Wait 1-2 minutes (Posthog has slight delay)
- Check Posthog → Live Events to see real-time events
- Verify
NEXT_PUBLIC_POSTHOG_KEYis correct
Testing Locally
- Posthog works in development
- Use incognito to get a fresh user assignment
- Check Network tab for
posthogrequests
Test Schedule
| Dates | Test | Flag to Enable |
|---|---|---|
| Week 1-2 | Parent Headline | parent_headline_variant |
| Week 3-4 | Parent CTA | parent_cta_variant |
| Week 5-6 | Provider Headline | provider_headline_variant |
| Week 7-8 | Provider CTA | provider_cta_variant |
Related Docs
- A/B Testing Plan — Strategy and copy variants
- Landing Page Strategy — Overall landing page approach
- Pre-Launch Strategy — PLG pre-launch overview