Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
31 changes: 6 additions & 25 deletions components/HeroHeadline.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,17 @@
'use client';

import { getVariant } from '@/lib/ab-test';

const HERO_VARIANTS = {
A: {
headline: 'Turn Marketing Into a Machine.',
subline:
'Custom digital systems that capture leads, nurture prospects, and measure what matters.',
},
B: {
headline: 'Your Marketing, on Autopilot.',
subline:
'Digital marketing systems that run while you run your business.',
},
};

/**
* Renders hero headline and subline with the correct A/B variant.
* Must be loaded with dynamic(ssr: false) so getVariant() runs during
* first client render (before paint), avoiding content flash and CLS.
* Static hero headline. Engineering-first positioning, May 2026 reposition.
* (Previous A/B test on marketing-firm framing was retired alongside the
* positioning shift — there wasn't enough traffic for an A/B to reach
* significance, and the direction was already decided.)
*/
export default function HeroHeadline() {
const { variant } = getVariant('hero_headline_v1');
const copy = HERO_VARIANTS[variant];

return (
<>
<h1 className="text-3xl md:text-5xl font-bold mb-4 text-[#00ff00]">
{copy.headline}
Founders ship MVPs. We ship them to production.
</h1>
<p className="text-lg md:text-xl text-[#00ff00]/70 mb-8 max-w-2xl mx-auto">
{copy.subline}
Senior engineering for AWS, Next.js, Python, and AI agent systems — the work that actually has to last.
</p>
</>
);
Expand Down
16 changes: 1 addition & 15 deletions components/HeroSection.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,12 @@
'use client';

import { useState, useCallback } from 'react';
import dynamic from 'next/dynamic';
import Image from 'next/image';
import { ArrowRight } from 'lucide-react';
import { trackEvent } from '@/lib/tracking';
import TurnstileField from './TurnstileField';
import ReviewStrip from './ReviewStrip';

const HeroHeadline = dynamic(() => import('./HeroHeadline'), {
ssr: false,
loading: () => (
<div>
<h1 className="text-3xl md:text-5xl font-bold mb-4 text-[#00ff00]">
Turn Marketing Into a Machine.
</h1>
<p className="text-lg md:text-xl text-[#00ff00]/70 mb-8 max-w-2xl mx-auto">
Custom digital systems that capture leads, nurture prospects, and measure what matters.
</p>
</div>
),
});
import HeroHeadline from './HeroHeadline';

export default function HeroSection() {
const [email, setEmail] = useState('');
Expand Down
4 changes: 1 addition & 3 deletions lib/tracking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
* so it persists across soft navigations but resets on new tabs.
*/

import { getVariant, type ExperimentResult } from './ab-test';
import { type ExperimentResult } from './ab-test';

// ---------------------------------------------------------------------------
// Types
Expand Down Expand Up @@ -89,7 +89,6 @@ export function initSession(): SessionContext {
}

const utms = parseUTMs();
const experiment = getVariant('hero_headline_v1');

const ctx: SessionContext = {
session_id: generateSessionId(),
Expand All @@ -99,7 +98,6 @@ export function initSession(): SessionContext {
...(utms.utm_campaign && { utm_campaign: utms.utm_campaign }),
...(utms.utm_term && { utm_term: utms.utm_term }),
...(utms.utm_content && { utm_content: utms.utm_content }),
experiment,
};

try {
Expand Down
Loading