Case study
Calm Sheets
Calm Sheets was running Google Ads with no idea what visitors did after the click. We built them the ability to watch every visit — every click, every scroll, every hesitation. They went from seeing their ad spend to seeing their customers.
Brand naming and domain acquisition
Landing page design with multiple iteration rounds
Customer research strategy with Python automation
SEO research and 90-day rebuild playbook
They could see their ad spend but nothing about the people the ads brought in. No way to know which ads actually worked, which pages lost visitors, or which words on the site were pulling their weight. The biggest line item in their business, and they were flying blind.
We built custom tracking at every step of the visitor's journey — from the ad they saw, to the page they landed on, to the moment they hit checkout. Every click, scroll, and hesitation gets captured. We also turned on screen recordings so the team can literally watch people shop: where they pause, where they leave, what catches their eye. Every visit is now visible.
Now they can watch every visitor. For the first time, they can see which ads actually earn customers, which pages lose people, and where shoppers hesitate before buying. They have the evidence they were missing — now the work of testing fixes and proving what works can begin with real data instead of guesses.
Session timeline
The complete record.
Analyzed Google Ads spend, CPC, funnel scroll depth, CTA behavior, and landing-page performance to identify unprofitable traffic patterns. · Tightened live Google Ads targeting with new campaign-level negatives, confirmed Flight Anxiety pause, set Fear of Flying to $20/day, and kept Night-Before Panicker at $50/day.
Rebuilt /flight/, /flight/fear-of-flying/, and /flight/anxiety/ around concise $34 paid-traffic messaging, early kit preview, demo tools, one-price checkout, FAQ, and final CTA. · Fixed landing page UX issues including spacing, misleading hero pills, checkout preservation, and funnel section tracking.
Restored Calm Sheets dashboard live-alert UI with tap-to-enable Web Audio visitor chime · Added active-purchase polling and generated cash-register alert when paid purchases increase
Fixed dashboard Purchases card showing lifetime totals regardless of 7d/30d/90d range toggle — fetchD1Metrics now accepts a 'since' date and applies WHERE created_at >= ? to the 4 purchase/refund queries (active purchases, revoked, refund requests, refunds confirmed). Both call sites updated (full dashboard render + /dashboard/api/metrics endpoint). · Removed redundant webhook_freshness health check that warned whenever the last D1 purchase was >14 days old. The stripe_d1_sync / orphaned_purchases check is the real signal — it queries Stripe directly and compares to D1 records. Cleared 33 stale webhook_freshness rows from production D1.
Audited Google Ads campaign and funnel screenshots; planned a concise paid-traffic rebuild for the highest-spend flight landing pages. · Rebuilt /flight/fear-of-flying/ and /flight/anxiety/ around immediate $34 offer clarity, early kit preview, demos, single checkout card, FAQ, and final CTA.
Rate limit /api/track (60/min) and dashboard login (10/15min brute-force protection)\n- Email format + 254-char length validation on magic link and refund flows\n- Input truncation (500 chars) on all tracking string fields\n- CORS scoped to calmsheets.com on /api/track (was wildcard)\n- Replaced SELECT * with named columns in 8 queries across 5 files\n- Added Strict-Transport-Security header\n- All 178 unit tests passing, deployed to production
Live audio notifications via Web Audio API: warm triangle-wave two-note chime for new visitors (660-880Hz, distinct from Spark's brighter sine-wave), A-C#-E-A arpeggio for purchases · Alert banner UX: tap-to-enable, pulsing indicator, localStorage persistence, preview sound on activation
Dashboard UX port from Spark Academy: center-aligned filter buttons, moved page selector to own section with title/description, friendly date format, renamed tabs Overview→Visitors / Funnel→Page Activity, removed redundant text from Funnel Overview and Page Comparison · Added Visitor Actions section with engagement stats: Button Taps, Started Checkout, Opened an FAQ, Tried Breathing Tool, Started Meditation (all hidden if 0)
Ported all 12 funnel tab UX improvements from Spark Academy: friendly section names, Visited Page/Reached X labels, stacked bar layout, delta inside/count outside, simpler column headers, < 1s display, friendlier descriptions, scroll depth labels, full section depth with PAGE_SECTIONS, All Pages vs Single Page view, tab persistence via URL hash · Added friendly page names to dropdown and comparison table (Night-Before Panicker not /flight/tomorrow/)
Fixed dashboard tab persistence: auto-refresh now preserves active tab via URL hash instead of resetting to Overview\n- Fixed funnel API 500 error: var hoisting bug where _funnelDays was undefined during hash restore, plus hardened days param parsing\n- Sorted funnel page dropdown dynamically by session count from D1\n- Removed pricing from 18 early CTAs across all 6 landing pages (hero + social proof + after What's Inside) to reduce early bounce — visitors now see content before price\n- Added owner exclusion: ?notrack URL sets permanent cookie, tracker skips, API drops beacons server-side\n- Added Chesterfield MO to GA4 city exclusion for both report and realtime queries\n- Improved funnel API error reporting with stack traces and client-side response body\n- Updated funnel-tracker-blueprint.md v1.0 → v1.1 with all lessons learned
Built 3 Google Ads API scripts: keyword report (metrics, search terms, impression share, QS), optimizer (batch pause/negative keywords), scheduler (ad schedules + day-of-week bid mods)\n- Applied live Google Ads changes: 43 negative keywords, paused QS 1 keyword, shifted 4 campaigns to 5pm-midnight, added day-of-week bid modifiers (Thu/Sat +20%, Tue -20%)\n- Built funnel tracking system: client-side JS tracker (Intersection Observer, sendBeacon), /api/track POST endpoint, D1 funnel_sessions schema\n- Built dashboard Funnel tab: funnel chart, section engagement table, drop-off report, page comparison, scroll depth distribution, date range + page filters\n- Edited 5 landing pages: added data-section attributes (10 per page), Microsoft Clarity snippet, tracker script, rebranded Reddit r/fearofflying to Anxious Flyers Community\n- Deep research on US flight traffic by day of week to inform bid strategy\n- Wrote reusable funnel tracker blueprint for other projects\n- Fixed dashboard Funnel tab JS bug (escaped apostrophe in template literal)
Researched anchor/strikethrough pricing UX best practices for digital products (conversion impact, visual patterns, ethical considerations)\n- Implemented ~~$49~~ $34 strikethrough pricing with 'Save 31%' badge across all 6 landing pages (/flight/, /tomorrow/, /prepare/, /understand/, /fear-of-flying/, /anxiety/)\n- Added reusable CSS classes (.price-anchor, .price-save-badge) with dark mode support\n- Updated pricing cards, section headers, all CTA buttons, and FAQ copy\n- Verified rendering at 375px, 768px, 1440px in light + dark mode via Playwright\n- Fixed dark mode contrast for anchor price and badge elements\n- JSON-LD schema and Stripe checkout unchanged — display-only change\n- Committed and deployed to production (calmsheets.com)
API security hardening: rate limiting on 5 public endpoints (checkout, verify-magic-link, confirm-refund, refresh-auth, download-pdf) via shared rate-limit.js helper\n- Fixed SQL injection risk in x-scheduled.js ORDER BY clause (status allowlist)\n- Added input validation allowlists to x-replies.js and x-scheduled.js\n- Hardened ADMIN_TOKEN auth on 3 admin endpoints (fail closed with 503 if not configured)\n- Created global API security rule (~/.claude/rules/common/api-security.md)\n- 41 new unit tests across 4 new + 5 existing test files (178 total, all passing)\n- Full production deployment: Cloudflare Pages + health worker + X reply bot
Diagnosed failing synthetic test: upgrade-rejects-missing-token probe was removed from local code during single-tier consolidation (commit 307c9f6) but health worker was never redeployed\n- Redeployed health worker to remove stale probe\n- Full production health audit: all 5 ad landing pages, checkout validation, auth gating, homepage, health worker — all healthy and stable for ad spend
Consolidated two-tier pricing (Standard $29 / Pro $34) to single-tier product at $34 — 48 files changed, 2,279 lines removed · Updated all 6 landing pages: single pricing card, 16-item feature list with guides/interactive tools separator
Full rewrite of /flight/ landing page for organic/direct/X-bot traffic conversion\n- Strategic debate on page positioning: analyzed traffic sources (X bot 6x/day, organic, returning visitors, direct), mapped all 3 personas, adapted PAS framework (lighter agitation, heavier solution)\n- New H1: 'Flight anxiety doesn't have to win' — broad catch-all vs scenario-specific\n- Added 8 new sections: problem validation, persona self-sort (in-page anchors), light agitation with success stories, solution positioning, methodology proof (4 credibility cards), objection handling (4 objections), price anchoring (therapy/courses comparison), FAQ with FAQPage structured data (8 questions)\n- 6 CTAs throughout page, all pointing to #pricing with 14-day refund signals\n- Preserved all functional code: checkout forms, breathing demo JS, meditation player JS, gclid capture, analytics, dark mode, form-guard\n- Kept free articles section as upsell funnel per Stephen's direction\n- Centered all quote cards for visual alignment\n- Committed and pushed to production
Audited all 6 free SEO articles against paid product — found severe overlap giving away the store (breathing techniques in 4/6 articles, complete packing lists, crew scripts, sound guides, timelines) · Rewrote all 6 articles as What/Why teasers: removed all How content (techniques, scripts, lists, action plans), kept education and validation, added soft CTAs bridging to paid guide
Added 'Reddit' prefix to all bare subreddit references (r/fearofflying, r/flyinganxiety) across 6 hand-authored landing pages and 3 content markdown source files\n- Rebuilt guide HTML from updated markdown via build-content.js\n- Verified no duplicate 'Reddit Reddit' or doubled subreddit names\n- Deployed to production (calmsheets.com)
Full PAS conversion rewrite of /flight/understand/ landing page (Logic Seeker persona)\n- Read & analyzed 11 strategy/context files (copywriting guide, Reddit research, Google Ads campaigns, keywords, ad copy, personas, brand docs)\n- Keyword & audience analysis: 26 keywords across 3 ad groups (Turbulence, Airplane Sounds, Claustrophobia & Control)\n- New sections: Agitate, Solution, Try It Now, Objection Handling, FAQ with FAQPage schema, price anchoring\n- Removed exit ramps: Free Articles (6 cards) and Related Articles (3 cards) sections\n- Extracted interactive demos into dedicated Try It Now section with conversion framing\n- Added Product and FAQPage structured data for SEO\n- 5 CTAs placed at emotional peaks (up from 2)\n- Fixed Reddit attribution (r/ → Reddit r/), centered quote cards, removed redundant login link\n- Deployed to production via Cloudflare Pages
Full /flight/prepare/ landing page rewrite for conversion optimization (Avoidant Traveler campaign)\n- PAS framework: added Problem, Agitate, Solution, Methodology Proof, Objection Handling, FAQ sections\n- Keyword & audience analysis across 28 keywords in 3 ad groups (Preparation, Returning Flyer, Scared but Must Travel)\n- Read 11 strategy/context files to inform copy decisions\n- Added FAQPage + Product structured data, 6 CTAs, price anchoring (-300 therapy vs )\n- Removed 2 article exit ramp sections, updated nav links\n- Copy fix: added Reddit prefix to all subreddit references\n- Style fix: center-aligned quote card content\n- Deployed to production on main branch
Full conversion rewrite of /flight/tomorrow/ landing page for Night-Before Panicker persona\n- Read & synthesized 11 strategy/context docs (copywriting guide, Reddit research, Google Ads, keywords, ad copy, personas, brand, site arch, reference rewrite)\n- Keyword & audience analysis: 33 keywords across 3 ad groups, persona mapping, emotional state assessment\n- PAS framework: Hero, Problem, Solution, Agitate, What's Inside, Try It Now, Methodology Proof, Objection Handling, Pricing, FAQ, Final CTA\n- Added 6 CTAs (was ~2), price anchoring (-300 therapy vs ), 3 inline objection handlers\n- Added mobile hamburger menu, FAQ section with FAQPage schema, Product structured data, Twitter meta tags\n- Removed exit ramps (Related Articles section, standalone permission section)\n- Preserved all functional JS (breathing demo, meditation player, checkout forms, gclid, time-aware label, dark mode)\n- Post-write tweaks: centered quotes, Reddit prefix on attributions, removed duplicate login link\n- Committed and deployed to production via Cloudflare Pages
Full conversion rewrite of /flight/anxiety/ landing page using PAS framework\n- Read 11 context files (strategy, copywriting guide, Reddit research, Google Ads config, personas, reference rewrite)\n- Keyword/audience analysis for Flight Anxiety campaign (22 keywords, 4 ad groups)\n- Added: agitation section, objection handling, price anchoring, FAQ with FAQPage schema, 5 CTAs\n- Removed: exit ramps (articles section, community voices, stat ticker, nav links to non-conversion sections)\n- Preserved all functional code (checkout forms, breathing demo JS, meditation JS, analytics, dark mode)\n- Deployed to production on calmsheets.com
UI polish on /fear-of-flying/ rewrite: fixed interactive tools grid alignment (lg→xl breakpoint), removed duplicate login link from pricing section, stacked price anchoring lines vertically, fixed spacing · Verified price anchoring accuracy: researched real fear-of-flying course prices, updated from $500+ to $295+ (SOAR program reference)
Audited codebase for auth cookie (30d), magic link uses (5x), and magic link expiration (24h) settings across all code paths · Audited all user-facing copy explaining auth system (emails, success page, FAQ, login, privacy, terms)
Conducted full conversion research: analyzed Reddit deep analysis (100+ posts), audited all 6 free articles + article hub, reviewed /fear-of-flying/ landing page, and researched online copywriting best practices (PAS framework, CXL, CopyHackers, Unbounce, MECLABS) · Analyzed Google Ads keyword data for Fear of Flying campaign (3 ad groups, 27 keywords) to map searcher intent to landing page copy
Full Google Ads account audit: analyzed 138 keywords + 195 search terms, identified waste, cannibalization, wrong-intent keywords · Built and deployed /flight/anxiety/ landing page targeting anxiety keyword cluster (validation-first hook, Reddit quotes, full pricing/checkout)
Full-screen mobile nav overlay (Spark Academy style) with hamburger-to-X animation, body scroll lock, ESC/click-outside dismiss, dark mode support across all 4 landing pages\n- Standardized nav links: Free Articles + Already Purchased on all landing pages (desktop + mobile)\n- Added 6-card Free Articles sections to /prepare/ and /understand/ landing pages\n- Fixed dark mode article cards blending into background (lighter bg + subtle border in dark-mode.css)\n- Audited and pushed uncommitted changes: bot relocation to bots/, health worker hardening, Google Ads campaign expansion\n- Redeployed health worker to production (external cron trigger, fewer false alarms, Google Ads API v20)
Analyzed Google Ads keyword 'flight anxiety' across campaigns; recommended /fear-of-flying/ as best landing page for broad head terms · Updated project CLAUDE.md with /fear-of-flying/ in site architecture and What's Built sections
Analyzed Google Ads keyword data (Avoidant Traveler campaign), identified budget drains and recommended pausing broad informational ad groups · Built /flight/fear-of-flying/ landing page: keyword-optimized for 'fear of flying' head terms, Reddit-sourced community quotes, persona routing section, Pro tool demos (breathing timer + meditation player), strategic article links, full pricing section
Fixed synthetic test false failures: removed 5 page-load probes that hit Cloudflare's ~10s Worker-to-Pages subrequest timeout limit · Kept all 12 API probes that test actual server-side logic (auth, checkout, webhooks, refunds, etc.)
Diagnosed health worker cron failure (Cloudflare cron silently stopped after D1 timeout errors) · Migrated health worker scheduling from Cloudflare cron trigger to cron-job.org (external cron, every 5 min)
Auto-hide System Health & Synthetic Tests dashboard cards when all healthy\n- Fix xFollowers undefined crash (null vs undefined check)\n- X follower count tracking: bot records hourly snapshots to D1, dashboard displays count + change\n- Fix OAuth 1.0a signing to include query params in signature base string\n- Deep research: 40+ X accounts to follow across 8 categories (saved to strategy/x-accounts-to-follow.md)\n- Hashtag monitoring bot: searches 10 flight anxiety hashtags, Gemini filters for real people, auto-replies with helpful tips (max 3/hour)\n- D1 migration for x_hashtag_tweets table\n- Social media expansion analysis: evaluated 10 platforms, ranked by fit/effort/ROI (Pinterest #1, TikTok #2)\n- Updated CLAUDE.md with hashtag monitoring docs + social media expansion plan
Analyzed 14 Ahrefs keyword research screenshots and extracted 61 new keywords for Google Ads campaigns\n- Organized new keywords into existing ad groups (B, C, F, H) and 4 new ad groups (J-M)\n- Wrote full RSA ad copy (12 headlines + 4 descriptions each) for Ad Groups J (Fear of Flying Head Terms), K (Flight Anxiety General), L (Coping & Calming Tips), M (First Time & Travel Anxiety)\n- Updated google-ads-keyword-list.md: 56→104 keywords, 9→13 ad groups, with comma-delimited export\n- Updated google-ads-copy.md with all 4 new ad group copy blocks\n- Advised on landing page URL change for Ad Group C (/flight/tomorrow → /flight/)
Created Google Ads keyword list document (56 keywords across 9 ad groups, comma-delimited) · Diagnosed and fixed Google Ads API v19→v20 sunset issue in dashboard and health worker (silently broken for weeks)