Engineering Diary, Day 16: From 'Nice Website' to 'Take My Money' — Building a Conversion Funnel in One Day
The Problem: A Beautiful Dead End
Yesterday we shipped analytics, scroll tracking, and speed fixes. But looking at the site with fresh eyes, I realized something embarrassing: we had no conversion funnel.
Every call-to-action on the site — "Explore Fleet," "Get Started," "Contact Us" — either scrolled the page or linked to /contact. That contact page was a generic form with name, email, and message fields. No flight details. No aircraft preference. No date. Just "tell us what you want" — the digital equivalent of walking into a Rolls-Royce dealership and being handed a suggestion box.
For a platform that promises AI-powered instant quotes, we were making users fill out a form and wait for an email. The gap between promise and reality was embarrassing.
What We Built
Eleven new components, one new API route, 1,400+ lines of code, 30+ files changed. Everything shipped in three commits.
1. QuickQuoteModal — The Heart of the Funnel
A global modal component with real functionality:
- Airport autocomplete: Fuse.js search across 7,900+ airports, shows IATA codes
- Date picker and passenger count
- Email capture for lead follow-up
- Submits to
/api/v1/quotes/lead-capture
The key architectural decision: a QuoteModalProvider context wrapping the entire app. Any component anywhere in the tree can call openQuoteModal(). This means we can add quote triggers to any page without prop drilling or state management gymnastics.
// Any component can now trigger the quote flow
const { openQuoteModal } = useQuoteModal();
<button Quote</button>
2. FloatingCTA Upgrade
The floating "Get a Quote" button in the bottom-right corner previously linked to /contact. Now it opens the QuickQuoteModal directly. Same gold accent styling, same scroll-aware visibility — but now it actually captures leads instead of dumping users on a generic form.
3. ExitIntentPopup — Last Chance Conversion
Desktop only (mouseleave detection doesn't work on mobile). Arms after 5 seconds on page to avoid annoying immediate popups. Shows once per session via localStorage. When triggered, offers one last chance to get a quote before leaving.
The implementation is deliberately gentle: a subtle dark overlay, a clean message, and a single CTA that opens the QuickQuoteModal. No aggressive countdown timers. No fake urgency. Just "Before you go — get a personalized quote in 60 seconds."
4. EmptyLegAlertSignup — Real Email Alerts
The empty legs page had "Set Up Alerts" links that went nowhere. Now there's a real signup form:
- Email input with route preference (optional)
- New API route:
/api/v1/empty-legs/alerts - Preferences stored in Vercel KV
- Confirmation email sent via Resend
This is our first real email list building feature. When we have empty leg deals, we can now notify interested users.
5. RelatedCaseStudies — Social Proof on Service Pages
Each of the 9 service pages (charter, membership, concierge, empty legs, corporate, group, event, pet travel, air ambulance) now displays 2-3 relevant case studies with stats and testimonials. The mapping is category-based — corporate charter shows Fortune 500 case studies, pet travel shows animal transport stories.
This is classic conversion optimization: when a potential client reads about charter services, they immediately see proof that real companies use VOLO for exactly that use case.
6. BlogQuoteCTA — Inline Content CTA
A styled CTA card inserted between blog post content and the newsletter signup. Every blog reader now sees a quote prompt. Content marketing → lead capture in one scroll.
Trust Signals Everywhere
7. TrustBadges Component
A reusable component showing three trust signals inline: "200+ Models · 50,000+ Jets Worldwide," "98% On-Time Rate," "24/7 Concierge." Added near CTAs on:
- Homepage hero section
- All service pages
- QuickQuoteModal itself
- CTA sections
Small text, big impact. When someone is deciding whether to click "Get Quote," seeing "98% on-time rate" right below the button reduces hesitation.
8. Hero CTA Optimization
The homepage hero had two buttons: "Explore Fleet" (scrolls down) and "How It Works" (scrolls down). Neither captured leads. Changed the primary button to "Get Instant Quote" → opens QuickQuoteModal. Added a trust micro-line below the buttons. The secondary button remains for users who want to browse first.
AEO: Optimizing for AI Search Engines
9. ServiceFAQ Component with JSON-LD
Google's AI Overviews and ChatGPT search are increasingly pulling structured FAQ data. We built a ServiceFAQ component that renders an accordion UI and injects FAQPage JSON-LD schema into the page head.
Added targeted FAQ sections to four high-traffic service pages:
- Charter: 4 Q&As (booking lead time, cost factors, airports, cancellation)
- Empty Legs: 3 Q&As (what are empty legs, savings, booking)
- Membership: 3 Q&As (tiers, benefits, cost savings)
- Concierge: 3 Q&As (AI capabilities, languages, availability)
13 total Q&As, each written to match the exact queries people ask AI assistants: "How much does it cost to charter a private jet?" "What is an empty leg flight?" These are Answer Engine Optimization (AEO) targets.
The Copy Fix That Matters Most
10–11. "200+ Aircraft" → "200+ Models · 50,000+ Jets"
CEO caught a critical messaging error. Our trust badges and hero text said "200+ Aircraft" — implying we own or operate 200+ planes. That's misleading. What we actually offer is access to 200+ aircraft models covering 50,000+ private jets worldwide through our operator network.
The distinction matters enormously:
- "200+ Aircraft" sounds like a small regional fleet
- "200+ Models · 50,000+ Jets Worldwide" communicates the true scale
Updated across all 4 locales (EN/ZH/FR/ES), TrustBadges component, hero section, and QuickQuoteModal. When you're asking someone to spend $30,000–$500,000 on a flight, every word in your trust signals must be precise and honest.
The Numbers
| Metric | Before | After |
|---|---|---|
| Lead capture points | 1 (contact page) | 7+ (modal, floating CTA, exit intent, blog, service pages, hero, empty leg alerts) |
| CTA → conversion path | 2 clicks (CTA → /contact → submit) | 1 click (CTA → modal → submit) |
| Trust signals near CTAs | 0 | Every CTA |
| FAQ structured data | 0 | 13 Q&As across 4 pages |
| Email list features | Newsletter only | Newsletter + empty leg alerts |
| New components | — | 11 |
| New API routes | — | 1 |
| i18n keys added | — | 38 (×4 locales) |
What's Next
The funnel exists now. Next we need to measure it. Server-side analytics from Day 15 will tell us:
- How many users see the QuickQuoteModal
- What percentage complete the form
- Exit intent trigger rate and conversion
- Empty leg alert signup volume
- Which FAQ questions drive the most search impressions
We also need to wire the admin dashboard to real data — right now it shows mock numbers. And payment processing is still the elephant in the room.
Commits
Three commits today across 30+ files:
9b6a1ae— CRO: 6 new features (QuickQuoteModal, ExitIntent, FloatingCTA, EmptyLegAlerts, RelatedCaseStudies, BlogQuoteCTA)b19a422— Social proof: TrustBadges, Hero CTA optimization, ServiceFAQ with JSON-LDa7af908— Copy fix: "200+ Aircraft" → "200+ Models · 50,000+ Jets Worldwide"
비행 준비가 되셨나요? 몇 초 안에 맞춤 전세 견적을 받으세요.
최신 소식 받기
엠프티 레그 특가, 신규 노선, 항공 인사이트를 이메일로 받아보세요.