/* global React */ /* Spec-Ring Case Study v2 — "Year in Review" timeline scrubber. A 4-milestone horizontal timeline drives a single hero stage: - Left: a leaderboard that animates Spec-Ring's row overtaking competitors - Right: a "revenue receipt" that prints longer with each milestone - Bottom: a quote/highlight tied to that moment in time */ const { useEffect, useState, useRef, useMemo } = React; const MILESTONES = [ { key: 'dec24', label: 'Dec 2024', short: 'Dec ’24', rank: 38, revenueIndex: 1.0, revenueLabel: '1.0×', headline: 'Buried on page 4.', quote: 'Spec-Ring is averaging position 38 — invisible to anyone outside the brand-name search.', chips: ['38th avg position', 'Page 4 of Google', 'Brand-only traffic'], }, { key: 'mar25', label: 'Mar 2025', short: 'Mar ’25', rank: 22, revenueIndex: 1.6, revenueLabel: '1.6×', headline: 'Foundations rebuilt.', quote: 'New site speed, restructured ad spend, schema cleanup. Climbing fast.', chips: ['22nd avg position', 'Page 3 → Page 2', 'CWV: passing'], }, { key: 'aug25', label: 'Aug 2025', short: 'Aug ’25', rank: 12, revenueIndex: 2.7, revenueLabel: '2.7×', headline: 'Climbing the front page.', quote: 'Email engine live. Paid spend tightening. Compounding revenue.', chips: ['12th avg position', 'Page 1 entered', '+170% YoY'], }, { key: 'dec25', label: 'Dec 2025', short: 'Dec ’25', rank: 6, revenueIndex: 3.88, revenueLabel: '3.9×', headline: 'Front row, nearly 4× the sales.', quote: 'Spec-Ring is ranking 6th on average — and outperforming 2024 by 288%.', chips: ['6th avg position', 'Top of page 1', '+288% YoY'], }, ]; // Competitor leaderboard rows (visual flavor — only the 6 visible at the end matter for accuracy) const COMPETITORS = [ { id: 'a', name: 'Auto Parts Hub' }, { id: 'b', name: 'Wheelmart' }, { id: 'c', name: 'PartFinder' }, { id: 'd', name: 'Garage Direct' }, { id: 'e', name: 'Mech Supply' }, { id: 'f', name: 'OEMShop' }, { id: 'g', name: 'TorqueZone' }, { id: 'h', name: 'PistonPro' }, ]; const easeOut = (t) => 1 - Math.pow(1 - t, 3); function useInView(ref, threshold = 0.25) { const [seen, setSeen] = useState(false); useEffect(() => { if (!ref.current) return; const io = new IntersectionObserver((entries) => { entries.forEach((e) => { if (e.isIntersecting) { setSeen(true); io.disconnect(); } }); }, { threshold }); io.observe(ref.current); return () => io.disconnect(); }, []); return seen; } // Smoothly tween a numeric value between milestone steps so charts feel alive. function useSmoothValue(target, duration = 800) { const [val, setVal] = useState(target); const fromRef = useRef(target); const startRef = useRef(0); const targetRef = useRef(target); useEffect(() => { fromRef.current = val; targetRef.current = target; startRef.current = performance.now(); let raf; const tick = (now) => { const t = Math.min(1, (now - startRef.current) / duration); const eased = easeOut(t); setVal(fromRef.current + (targetRef.current - fromRef.current) * eased); if (t < 1) raf = requestAnimationFrame(tick); }; raf = requestAnimationFrame(tick); return () => cancelAnimationFrame(raf); }, [target]); return val; } // ─── Leaderboard panel ───────────────────────────────────────────── function Leaderboard({ rank }) { const smoothRank = useSmoothValue(rank, 1100); const live = Math.round(smoothRank); // Build the visible window: rows around current rank. // Show ranks 1–10 always; if current rank > 10, show a clipped indicator. const visibleCount = 8; const windowTop = live <= 10 ? 1 : Math.max(1, live - 3); const rows = []; for (let r = windowTop; r < windowTop + visibleCount; r++) { rows.push(r); } // Make sure rank 1 is always visible if window doesn't include it const includesUs = rows.includes(live); return (
Google · "automotive parts" {live} {live === 1 ? 'st' : live === 2 ? 'nd' : live === 3 ? 'rd' : 'th'}
{!includesUs && (
··· position {live} · page {Math.ceil(live / 10)}
)}
); } // ─── Receipt panel ─────────────────────────────────────────────── function Receipt({ idx, milestone }) { const smoothMult = useSmoothValue(milestone.revenueIndex, 900); // The receipt has line items added per milestone — earlier states show fewer lines. const allLines = [ // dec24 baseline { label: 'Brand-name traffic', amount: 28.4 }, { label: 'Direct & referral', amount: 22.1 }, { label: 'Existing campaigns', amount: 38.5 }, // mar25 adds { label: 'Site speed lift', amount: 18.0, milestone: 1 }, { label: 'New SEO clusters', amount: 14.6, milestone: 1 }, // aug25 adds { label: 'Email automation', amount: 38.2, milestone: 2 }, { label: 'Refined paid funnels', amount: 47.0, milestone: 2 }, { label: 'Cart recovery', amount: 12.4, milestone: 2 }, // dec25 adds { label: 'Authority backlinks', amount: 36.5, milestone: 3 }, { label: 'Loyalty + win-back', amount: 28.2, milestone: 3 }, { label: 'Black Friday surge', amount: 56.1, milestone: 3 }, ]; const visible = allLines.filter((l) => (l.milestone ?? 0) <= idx); const total = visible.reduce((s, l) => s + l.amount, 0); return (
SPEC-RING Annual Revenue · Indexed {milestone.label}
    {visible.map((l, i) => (
  • {l.label} {'.'.repeat(40)} ${l.amount.toFixed(1)}K
  • ))}
YOY MULTIPLIER {smoothMult.toFixed(1)} ×
thank you for choosing spec-ring.com
); } // ─── Main component ───────────────────────────────────────────── function SpecRingCase() { const ref = useRef(null); const seen = useInView(ref); const [idx, setIdx] = useState(0); const [autoPlaying, setAutoPlaying] = useState(true); const userTouchedRef = useRef(false); // Autoplay until user interacts; once seen, advance every ~3.4s useEffect(() => { if (!seen || !autoPlaying || userTouchedRef.current) return; const t = setTimeout(() => { setIdx((i) => { if (i >= MILESTONES.length - 1) { setAutoPlaying(false); return i; } return i + 1; }); }, idx === 0 ? 700 : 3400); return () => clearTimeout(t); }, [seen, idx, autoPlaying]); const milestone = MILESTONES[idx]; const trackProgress = idx / (MILESTONES.length - 1); function jumpTo(i) { userTouchedRef.current = true; setAutoPlaying(false); setIdx(i); } return (
E-commerce · SEO + Paid + Web + Email Spec-Ring

From page 4 of Google to the front row — and +288% in revenue in a single year.

{/* Timeline scrubber */}
{MILESTONES.map((m, i) => ( ))}
{/* Stage */}
{/* Caption row */}
{milestone.label}

{milestone.headline}

"{milestone.quote}"

{milestone.chips.map((c) => ( {c} ))}
{/* Summary footer */}
); } window.SpecRingCase = SpecRingCase;