const { useState, useMemo, useEffect } = React; // Tooltip Modal Component const TooltipModal = ({ isOpen, onClose, title, content }) => { if (!isOpen) return null; return (
e.stopPropagation()}>

{title}

); }; // Tooltip Button Component const TooltipBtn = ({ onClick }) => ( ); // Field Marker Component const FieldMarker = ({ field, completed, onClick }) => ( ); const industries = { ecom_fashion: { name: 'Fashion', y25: { cpc: 0.45, cpm: 8.50, ctr: 1.20, cr: 1.80, aov: 85 }, y26: { cpc: 0.51, cpm: 9.10, ctr: 1.24, cr: 1.92, aov: 88 }, margin: 45, cac: 25, ltv: 255 }, ecom_beauty: { name: 'Beauty', y25: { cpc: 0.60, cpm: 9.20, ctr: 1.40, cr: 2.40, aov: 65 }, y26: { cpc: 0.68, cpm: 9.80, ctr: 1.45, cr: 2.56, aov: 68 }, margin: 55, cac: 25, ltv: 195 }, ecom_home: { name: 'Home & Decor', y25: { cpc: 0.70, cpm: 7.80, ctr: 1.00, cr: 1.50, aov: 120 }, y26: { cpc: 0.79, cpm: 8.40, ctr: 1.04, cr: 1.60, aov: 125 }, margin: 40, cac: 47, ltv: 360 }, ecom_electronics: { name: 'Electronics', y25: { cpc: 0.85, cpm: 10.50, ctr: 0.90, cr: 1.20, aov: 250 }, y26: { cpc: 0.96, cpm: 11.20, ctr: 0.93, cr: 1.28, aov: 260 }, margin: 25, cac: 71, ltv: 500 }, ecom_health: { name: 'Health', y25: { cpc: 0.90, cpm: 9.00, ctr: 1.30, cr: 2.80, aov: 75 }, y26: { cpc: 1.02, cpm: 9.60, ctr: 1.35, cr: 2.99, aov: 78 }, margin: 50, cac: 32, ltv: 225 }, ecom_pets: { name: 'Pet Supplies', y25: { cpc: 0.55, cpm: 7.50, ctr: 1.50, cr: 2.20, aov: 55 }, y26: { cpc: 0.62, cpm: 8.10, ctr: 1.56, cr: 2.35, aov: 58 }, margin: 42, cac: 25, ltv: 165 }, ecom_kids: { name: 'Kids & Toys', y25: { cpc: 0.50, cpm: 8.00, ctr: 1.30, cr: 2.00, aov: 70 }, y26: { cpc: 0.56, cpm: 8.60, ctr: 1.35, cr: 2.14, aov: 74 }, margin: 48, cac: 25, ltv: 210 }, ecom_food: { name: 'Food & Beverage', y25: { cpc: 0.65, cpm: 8.80, ctr: 1.10, cr: 3.20, aov: 45 }, y26: { cpc: 0.73, cpm: 9.40, ctr: 1.14, cr: 3.42, aov: 47 }, margin: 35, cac: 20, ltv: 135 }, svc_education: { name: 'Education', y25: { cpc: 1.20, cpm: 12.00, ctr: 1.80, cr: 4.50, aov: 150 }, y26: { cpc: 1.35, cpm: 12.80, ctr: 1.87, cr: 4.81, aov: 155 }, margin: 60, cac: 27, ltv: 450 }, svc_travel: { name: 'Travel', y25: { cpc: 0.75, cpm: 9.50, ctr: 1.60, cr: 2.00, aov: 350 }, y26: { cpc: 0.85, cpm: 10.20, ctr: 1.66, cr: 2.14, aov: 365 }, margin: 18, cac: 38, ltv: 700 }, fintech: { name: 'Fintech', y25: { cpc: 3.50, cpm: 25.00, ctr: 0.70, cr: 4.50, aov: 180 }, y26: { cpc: 3.95, cpm: 26.80, ctr: 0.73, cr: 4.81, aov: 188 }, margin: 70, cac: 78, ltv: 540 }, gaming: { name: 'Gaming', y25: { cpc: 0.30, cpm: 5.50, ctr: 2.50, cr: 5.00, aov: 35 }, y26: { cpc: 0.34, cpm: 6.00, ctr: 2.59, cr: 5.34, aov: 38 }, margin: 80, cac: 6, ltv: 105 }, saas: { name: 'SaaS B2C', y25: { cpc: 1.80, cpm: 15.00, ctr: 1.00, cr: 3.00, aov: 120 }, y26: { cpc: 2.03, cpm: 16.20, ctr: 1.04, cr: 3.21, aov: 126 }, margin: 75, cac: 60, ltv: 360 }, }; // Monthly growth rate benchmarks (%) const getMonthlyGrowthBenchmark = (ind) => { const industryKey = ind; if (industryKey.startsWith('ecom_')) return 5; // E-commerce: 5% monthly if (industryKey.startsWith('svc_')) return 15; // Services: 15% monthly return 10; // Others (Fintech, Gaming, SaaS): 10% monthly }; // Tooltip Content Data const getTooltipContent = (industry) => { const ind = industries[industry]; return { guide: `

Smart move! Let's get you forecasting like a pro.

Step 1: Choose Your Industry

Pick your industry to load 2026 benchmarks. We have 13 industries with real data.

Step 2: Fill ORANGE Fields

Orange labels = YOUR data. Fill: Traffic, Budget, Orders, AOV, Margin, LTV.

Step 3: Set Your Target

Enter target orders/revenue and NEW budget you can invest.

Step 4: Review Results

Check if you're profitable, see scenarios, and understand your metrics.

๐Ÿ“– Full methodology:

Read our data sources โ†’
`, marketContext: `

Curious about the numbers? Good! Here's the breakdown.

2026 Industry Benchmarks for ${ind.name}

Metric 2025 2026
CPC (Cost Per Click)โ‚ฌ${ind.y25.cpc.toFixed(2)}โ‚ฌ${ind.y26.cpc.toFixed(2)}
CPM (Per 1000 Impressions)โ‚ฌ${ind.y25.cpm.toFixed(2)}โ‚ฌ${ind.y26.cpm.toFixed(2)}
CTR (Click-Through Rate)${ind.y25.ctr.toFixed(2)}%${ind.y26.ctr.toFixed(2)}%
CR (Conversion Rate)${ind.y25.cr.toFixed(2)}%${ind.y26.cr.toFixed(2)}%
AOV (Avg Order Value)โ‚ฌ${ind.y25.aov}โ‚ฌ${ind.y26.aov}

What These Mean:

  • CPC: How much you pay per ad click
  • CPM: Cost per 1,000 ad impressions
  • CTR: % who click after seeing ad
  • CR: % who buy after clicking
  • AOV: Average amount spent per order

Editable Fields:

CPC, CPM, CTR, CR, AOV: These are pre-filled with benchmarks but you can edit them if you have your own data.

Profit Margin: Your net profit % after all costs (COGS, shipping, overhead, returns).

Customer LTV: Total revenue from a customer over their lifetime. Industry average is โ‚ฌ${ind.ltv}.

`, businessNumbers: `

Good! These are YOUR numbers - the core of forecasting.

๐Ÿšฆ Monthly Traffic

What: Visitors to your site/landing page per month

Formula: From your analytics (Google Analytics, etc)

๐Ÿ’ก More traffic = more chances to convert

๐Ÿ’ฐ Marketing Budget

What: Current monthly ad spend

Includes: Facebook Ads, Google Ads, TikTok, etc

โš ๏ธ This is CURRENT budget, not target budget

๐Ÿ“ฆ Actual Orders

What: Orders you're getting NOW per month

Used for: Calculating your actual conversion rate vs expected

๐Ÿ›’ Avg Order Value (AOV)

Formula: Total Revenue รท Number of Orders

Example: โ‚ฌ10,000 revenue / 100 orders = โ‚ฌ100 AOV

๐Ÿ’ก Pre-filled with industry avg (โ‚ฌ${ind.y26.aov}), use YOUR real number!

`, targets: `

Planning for growth? Smart. Here's what each field does.

๐ŸŽฏ Target Orders

What: How many orders you WANT per month

Formula: When you change this, Target Revenue auto-calculates

Formula: Target Orders ร— AOV = Target Revenue

๐Ÿ’ต Target Revenue

What: Revenue you WANT per month

Formula: When you change this, Target Orders auto-calculates

Formula: Target Revenue รท AOV = Target Orders

โšก These two fields sync - change one, other updates!

๐Ÿ’ธ NEW Marketing Budget

What: TOTAL budget you can invest (current + extra)

Not: Just the "extra" - this is the FULL new budget

Calculator shows:

  • โ€ข Budget Needed: To hit target orders
  • โ€ข Difference: Gap between your NEW budget and what's needed
  • โ€ข Achievable?: Can you hit target with this budget?

๐Ÿ“Š The Logic:

Needed Budget = (Target Orders รท CR%) ร— CPC

Example: Want 1000 orders, 2% CR, โ‚ฌ0.50 CPC
= (1000 รท 0.02) ร— 0.50 = โ‚ฌ25,000 needed

` , currentState: `

Want to understand where you are NOW? Here's the breakdown.

๐Ÿ“Š What This Shows:

Your CURRENT performance based on the data you entered (Traffic, Budget, Actual Orders).

๐Ÿ’ฐ Revenue

Formula: Actual Orders ร— AOV

What it means: Total money coming in from sales

๐Ÿ“ฆ Orders

Shows: Your actual orders vs expected orders

Expected Formula: Traffic ร— CTR ร— CR

๐Ÿ’ก If actual > expected, you're beating benchmarks!

๐Ÿ’ธ ROAS (Return on Ad Spend)

Formula: Revenue รท Budget

Example: โ‚ฌ10,000 revenue รท โ‚ฌ2,500 budget = 4x ROAS

โœ… Above 2x is generally good

๐Ÿ’ต CAC (Customer Acquisition Cost)

Formula: Budget รท Actual Orders

What it means: Cost to get one customer

โš ๏ธ Should be less than (AOV ร— Profit Margin)

`, targetState: `

Planning for the future? Let's see what you're aiming for.

๐ŸŽฏ What This Shows:

Where you WANT to be - based on Target Orders/Revenue from "Targets" section.

๐Ÿ’ฐ Target Revenue

Formula: Target Orders ร— AOV

๐Ÿ“Š Est. Orders

Formula: (NEW Budget รท CPC) ร— (CR รท 100)

How many orders with your NEW budget

๐Ÿ’ธ Est. ROAS & CAC

Expected metrics with NEW budget

`, performanceScores: `

Scores show campaign health. Let's decode them.

๐Ÿ“Š Scoring: 0-100

Green (90-100) = Excellent, Yellow (70-89) = Good, Red (0-69) = Needs work

๐ŸŽฏ CAC Score

Compares your CAC to industry benchmark

๐Ÿ’ฐ ROAS Score

4x+ ROAS = Excellent, 2-4x = Good, Below 2x = Needs work

โš–๏ธ Margin Score

50%+ = Excellent, 30-50% = Healthy, Below 30% = Tight

`, cacAnalysis: `

Customer Acquisition Cost deep dive. Critical metric!

๐Ÿ’ต Your CAC

Formula: Ad Spend รท Customers

๐Ÿ’ฐ Max Acceptable CAC

Formula: AOV ร— Profit Margin %

MOST you can spend per customer and break even

โš ๏ธ CAC > Max CAC = losing money!

๐Ÿ“ˆ CAC:LTV Ratio

Formula: CAC รท LTV

Below 30% = Excellent, 30-50% = Healthy, Above 50% = Too expensive

`, breakeven: `

When do you stop losing money? Here's the math.

โš–๏ธ Break-Even Point

Where profit from sales equals ad spend

๐Ÿ“Š Orders to Break-Even

Formula: Budget รท (AOV ร— Margin %)

Example: โ‚ฌ2,500 รท (โ‚ฌ100 ร— 40%) = 62.5 orders needed

๐ŸŽฏ Required ROAS

Formula: 1 รท Profit Margin %

โœ… Any ROAS above this = profit!

`, funnelCosts: `

Every funnel step costs money. Here's the breakdown.

๐Ÿ‘€ CPM (Cost Per 1000 Impressions)

Cost to show ad to 1,000 people

๐Ÿ‘† CPC (Cost Per Click)

Cost each time someone clicks

๐Ÿ›’ Cost Per Conversion

Formula: CPC รท CR%

Same as CAC - cost per sale

`, risk: `

How risky is this campaign? Risk assessment.

๐Ÿ›ก๏ธ Risk Score

Measures likelihood of losing money or missing targets

๐ŸŸข Low Risk: Profitable, healthy metrics

๐ŸŸก Medium Risk: Some concerns, watch closely

๐Ÿ”ด High Risk: Losing money, rethink strategy!

`, goalCalculator: `

Working backwards from goals. Smart planning!

๐ŸŽฏ What This Does

Calculates WHAT YOU NEED to hit target orders/revenue

๐Ÿ“Š Traffic Needed

Formula: (Target Orders รท CR%) รท CTR%

๐Ÿ’ธ Budget Needed

Formula: (Target Orders รท CR%) ร— CPC

โœ… Achievable?

Compares your NEW Budget vs needed budget

`, scenarios: `

Reality changes. Here's best, worst, and normal case.

๐Ÿ˜ฐ Pessimistic (Worst Case)

CPC/CPM +15%, CTR/CR -30%

Crisis, high competition, bad conditions

๐Ÿ˜ Realistic (Normal)

Uses exact 2026 benchmarks

Your PRIMARY planning scenario

๐Ÿฆ„ Optimistic (Best Case)

CPC/CPM -10%, CTR/CR +30%

Viral content, perfect targeting

โœ๏ธ You Can Edit!

Each scenario has editable CTR, CR, CPC, CPM fields

`, timeToTarget: `

Planning your timeline? Let's break down when you'll hit your target.

โฑ๏ธ What This Shows:

How many MONTHS it will take to reach your target revenue, assuming steady monthly growth.

๐Ÿ“Š The Calculation

Formula: Based on compound monthly growth rate

Math: months = log(1 + (budget gap รท current budget)) รท log(1 + growth rate)

๐Ÿ’ก This assumes you reinvest profits back into marketing

๐Ÿ“ˆ Monthly Growth Rate

What it is: Expected % increase in revenue each month

Industry Benchmarks (2025-2026 data):

  • โ€ข E-commerce: 5% monthly (~7-8% annual)
  • โ€ข Services (SaaS, Education): 15% monthly (~20-35% annual for private companies)
  • โ€ข Fintech/Gaming: 10% monthly (~15-25% annual)

โšก You can edit this to match YOUR growth rate!

๐ŸŽฏ How to Use This:

  • Green (0-6 months): Fast! Achievable in under half a year
  • Yellow (6-12 months): Realistic timeframe for most businesses
  • Red (12-24+ months): Long journey - consider adjusting targets or budget
  • โˆž (Infinite): Not achievable with current growth - need more budget or lower targets

โš ๏ธ Reality Check: This assumes consistent growth. Real business has ups and downs. Use as directional guidance, not gospel.

`, whatIsThis: `

Wait, what even IS this thing? Glad you asked!

๐Ÿค– The Smart Marketing Calculator That Does Your Homework

This is an AI-powered forecasting tool that takes the guesswork out of marketing planning. Think of it as your personal marketing analyst who never sleeps (or asks for a raise).

๐Ÿ“Š What It Does (In Plain English):

  • โ€ข Loads Industry Data: Pulls real 2025-2026 advertising benchmarks for 13+ industries (CPC, CTR, conversion rates, etc.)
  • โ€ข Analyzes Your Business: You plug in YOUR numbers (traffic, budget, orders) and it compares you to the market
  • โ€ข Forecasts Your Future: Shows whether your targets are realistic, how much budget you REALLY need, and when you'll hit your goals
  • โ€ข Runs Scenarios: Tests best-case, normal-case, and worst-case outcomes so you're not caught off guard

โœจ Why It's Useful:

  • โ€ข No More Guessing: Stop pulling numbers out of thin air during budget meetings
  • โ€ข Benchmark Yourself: See how you stack up against your industry (spoiler: might be better than you think!)
  • โ€ข Plan Smarter: Know EXACTLY how much budget you need to hit your revenue targets
  • โ€ข Spot Red Flags: Identifies if your CAC is too high, margins too thin, or targets unrealistic

๐ŸŽฏ How to Use It:

  1. 1. Pick your industry
  2. 2. Fill in the ORANGE fields with YOUR real data
  3. 3. Set your targets
  4. 4. Watch the magic happen โœจ

โš ๏ธ Fair Warning: This tool was built for fun using AI and real market data. It's pretty damn smart, but it's NOT a crystal ball. Don't bet your company on it without doing your own homework. Use it as a guide, not gospel. We're not liable if your CMO makes bad decisions (but they probably will anyway ๐Ÿ˜…).

Made with โค๏ธ, โ˜•, and way too much ChatGPT

Built by marketers, for marketers (who hate spreadsheets)

` }; }; const getYoYChange = (ind) => { const y25 = industries[ind].y25; const y26 = industries[ind].y26; return { cpc: ((y26.cpc - y25.cpc) / y25.cpc * 100).toFixed(1), cpm: ((y26.cpm - y25.cpm) / y25.cpm * 100).toFixed(1), ctr: ((y26.ctr - y25.ctr) / y25.ctr * 100).toFixed(1), cr: ((y26.cr - y25.cr) / y25.cr * 100).toFixed(1), aov: ((y26.aov - y25.aov) / y25.aov * 100).toFixed(1), }; }; const getColor = (value, benchmark, lower = false, threshold = 0.5) => { const diff = Math.abs((value - benchmark) / benchmark * 100); if (diff <= threshold) return 'text-amber-500'; const good = lower ? value <= benchmark : value >= benchmark; return good ? 'text-emerald-600' : 'text-red-500'; }; const getBgColor = (value, benchmark, lower = false, threshold = 0.5) => { const diff = Math.abs((value - benchmark) / benchmark * 100); if (diff <= threshold) return 'bg-amber-100 text-amber-700'; const good = lower ? value <= benchmark : value >= benchmark; return good ? 'bg-emerald-100 text-emerald-700' : 'bg-red-100 text-red-700'; }; const ScoreRing = ({ score, label, sublabel, size = 100 }) => { const clampedScore = Math.min(99, Math.max(1, Math.round(score))); const radius = (size - 16) / 2; const circumference = 2 * Math.PI * radius; const strokeDashoffset = circumference - (clampedScore / 100) * circumference; const scoreColor = clampedScore >= 70 ? '#10b981' : clampedScore >= 40 ? '#f59e0b' : '#ef4444'; const textColor = clampedScore >= 70 ? 'text-emerald-600' : clampedScore >= 40 ? 'text-amber-600' : 'text-red-500'; return (
{clampedScore} {label} {sublabel && {sublabel}}
); }; const MiniScoreRing = ({ score, size = 60 }) => { const clampedScore = Math.min(99, Math.max(1, Math.round(score))); const radius = (size - 10) / 2; const circumference = 2 * Math.PI * radius; const strokeDashoffset = circumference - (clampedScore / 100) * circumference; const scoreColor = clampedScore >= 70 ? '#10b981' : clampedScore >= 40 ? '#f59e0b' : '#ef4444'; const textColor = clampedScore >= 70 ? 'text-emerald-600' : clampedScore >= 40 ? 'text-amber-600' : 'text-red-500'; return (
{clampedScore}
); }; const BarChart = ({ actual, estimated, label1 = 'Current', label2 = 'Needed', height = 80 }) => { const max = Math.max(actual, estimated) || 1; const h1 = (actual / max) * height; const h2 = (estimated / max) * height; return (

{label1}

โ‚ฌ{actual.toLocaleString()}

{label2}

โ‚ฌ{estimated.toLocaleString()}

); }; const TimeChart = ({ months, maxMonths = 24 }) => { const displayMonths = months === 999 ? maxMonths : Math.min(months, maxMonths); const pct = (displayMonths / maxMonths) * 100; return (
0 12 mo 24+ mo

{months === 999 ? 'โˆž' : months === 0 ? '๐ŸŽ‰ Done!' : `${months} mo`}

); }; const Input = ({ label, value, onChange, suffix, prefix, note, field, completed, onMarkComplete }) => (
{prefix && {prefix}} { const val = e.target.value === "" ? "" : parseFloat(e.target.value) || 0; onChange(val); }} className={`w-full ${prefix ? 'pl-6' : 'pl-3'} ${suffix ? 'pr-10' : 'pr-3'} py-2 border border-slate-200 rounded-lg text-sm focus:ring-2 focus:ring-emerald-500 focus:border-emerald-500 outline-none`} /> {suffix && {suffix}}
{note &&

{note}

}
); const Progress = ({ value, max }) => { const pct = max > 0 ? Math.min((value / max) * 100, 100) : 0; return (
); }; const Metric = ({ label, value, est, good, neutral }) => (

{label}

{value} {est && ({est})}

); const Compare = ({ label, yours, bench, unit = '', lower = false }) => { const diff = bench > 0 ? ((yours - bench) / bench * 100) : 0; const isNeutral = Math.abs(diff) <= 0.5; const good = lower ? yours <= bench : yours >= bench; const colorClass = isNeutral ? 'text-amber-500' : (good ? 'text-emerald-600' : 'text-red-500'); const bgClass = isNeutral ? 'bg-amber-100 text-amber-700' : (good ? 'bg-emerald-100 text-emerald-700' : 'bg-red-100 text-red-700'); return (
{label}
{yours.toFixed(2)}{unit} vs {bench.toFixed(2)} {diff > 0 ? '+' : ''}{diff.toFixed(0)}%
); }; const getSarcasticComment = (type, isGood) => { const comments = { verdict: { good: [ "๐Ÿš€ Marketing ROI goes brrrrr!", "๐Ÿ’ฐ Your accountant just cracked a smile (that's rare)!", "๐ŸŽฏ You're not just marketing, you're printing money!", "๐Ÿ† Someone call Forbes, we found a winner!", "๐Ÿพ Pop the champagne, this campaign SLAPS!", "โšก Efficiency so good, even your competitors are jealous!" ], bad: [ "๐Ÿ”ฅ Congrats, you're Meta's favorite charity donor!", "๐Ÿ’ธ At this rate, selling lemonade would be MORE profitable!", "๐Ÿ˜ฌ Your CFO just fainted. Again. Call 911.", "๐ŸŽช This ain't marketing, it's a circus without tickets!", "๐Ÿ’€ Even Nigerian princes have better ROI than this...", "๐Ÿดโ€โ˜ ๏ธ Burning money would be more entertaining at this point!" ] }, cac: { good: [ "๐Ÿ‘‘ CAC royalty! Customers basically pay YOU to sell them stuff!", "๐ŸŽช Getting customers cheaper than circus peanuts!", "โœจ Your competitors are stress-eating right now.", "๐Ÿฆ„ This CAC is so good it's almost illegal!", "๐ŸŽฐ Vegas wishes their odds were this good!", "๐Ÿง™ Magic? Nah, just superior marketing wizardry!" ], bad: [ "๐Ÿ’€ Paying more per customer than their lifetime value? Bold strategy, Cotton.", "๐Ÿค‘ Each customer costs more than a Michelin-star dinner. Yikes.", "๐Ÿ“‰ Your CAC is giving 'I should've stayed in bed' energy.", "๐Ÿ”จ Breaking even? More like breaking your budget!", "๐ŸŽข This CAC roller coaster only goes DOWN, baby!", "๐Ÿ’ธ At this rate, you're basically paying people NOT to buy!" ] }, breakeven: { good: [ "โš–๏ธ Above break-even! You can actually pay rent this month!", "๐Ÿ† Making money? In THIS economy?! Absolute legend!", "๐Ÿ’ช Break-even who? You're BREAKING profit records!", "๐ŸŽŠ Your bank account is doing the happy dance!", "๐ŸŒŸ Profitability called, it wants to be your bestie!", "๐Ÿš€ Not just breaking even, you're breaking the SOUND BARRIER!" ], bad: [ "๐Ÿ•ณ๏ธ Below break-even... but hey, at least the vibes are immaculate?", "๐Ÿ˜… Break-even is just a suggestion anyway, right? RIGHT?!", "๐ŸŽข Riding the loss roller coaster. Wheee... *nervous laughter*", "๐Ÿดโ€โ˜ ๏ธ Profitability is playing hard to get. Very hard.", "๐Ÿ’” Break-even ghosted you like a bad Tinder date!", "๐Ÿคก Math says you're losing money. But what does math know, really?" ] }, funnel: { good: [ "๐ŸŽฏ Funnel smoother than fresh peanut butter!", "๐Ÿ’ซ Clicks converting like it's Black Friday every day!", "๐Ÿ”ฅ Gary Vee would literally frame this funnel on his wall.", "๐Ÿ… This funnel is chef's kiss perfection!", "๐ŸŒŠ Conversions flowing like Niagara Falls!", "๐ŸŽฐ Every click is a jackpot. DING DING DING!" ], bad: [ "๐Ÿšฐ More leaks than the Titanic on its last day.", "๐Ÿ˜ต Clicks in, tumbleweeds out. Classic.", "๐Ÿคท Visitors are confused. Customers are... nowhere?", "๐Ÿ•ณ๏ธ Your funnel has more holes than Swiss cheese!", "๐Ÿ‘ป Conversions went ghost mode. Spooky!", "๐ŸŽช People are clicking just for the entertainment value!" ] }, risk: { good: [ "๐Ÿ›ก๏ธ Sleeping like a baby tonight! Zero stress!", "๐Ÿ˜Ž Chill vibes only. Risk is your little cousin.", "๐Ÿ€ Lucky you! Risk is more manageable than a house plant!", "๐Ÿ–๏ธ So low-risk you could run this from a beach!", "๐Ÿฆ˜ Risk hopped away. Australia is jealous!", "โ˜๏ธ Risk level: fluffy cloud. You're good!" ], bad: [ "๐ŸŽฐ Las Vegas casinos would call THIS risky.", "๐Ÿ˜ฐ High risk = high reward... or high regret. Coin flip time!", "โš ๏ธ Your risk assessment needs a risk assessment!", "๐ŸŒ‹ Risk volcano about to erupt! Run!", "๐Ÿ’ฃ This risk is ticking louder than a bomb!", "๐Ÿดโ€โ˜ ๏ธ Arrr, ye be sailing dangerous waters, matey!" ] }, time: { good: [ "โšก Fast track to success! Buckle up!", "๐Ÿƒ Hit your goals before your next coffee break!", "๐Ÿš„ Speed running profitability like a pro gamer!", "๐ŸŽฏ Time to target: Yesterday. Let's GO!", "โฐ So fast, time itself is confused!", "๐Ÿฆ… Flying to your goals at eagle speed!" ], bad: [ "๐ŸŒ Patience, young grasshopper... you'll need LOTS of it.", "๐Ÿ“… Your grandkids will celebrate this achievement. Maybe.", "โณ Time to target: Yes. Just... yes.", "๐Ÿฆ– By the time you hit target, dinosaurs might be back!", "โ˜• Better brew some strong coffee. You'll be here a while.", "๐Ÿง“ Retirement plan? This IS your retirement plan now!" ] }, persona: { good: [ "๐ŸŽฏ Customer persona? *Chef's kiss* Perfetto!", "๐Ÿ‘ฅ You know your audience like your Netflix password!", "๐Ÿ”ฎ Your targeting is straight-up magical!", "๐Ÿง  Mind-reader level targeting. Impressive!", "๐ŸŽญ Persona game so strong, Shakespeare is taking notes!", "๐Ÿ’Ž Diamond-precision targeting. Flawless!" ], bad: [ "๐ŸŽญ Persona as confused as a cat at a dog show.", "๐Ÿ‘ป Your ideal customer is... invisible? Ghosts?", "๐Ÿค” Time to actually MEET your customers. Like, IRL.", "๐ŸŽช Targeting everyone = targeting no one. Circus logic!", "๐ŸŒ€ Persona spinning like a confused weather vane!", "๐Ÿคท Who's your customer? Great question. You tell us!" ] } }; const arr = comments[type]?.[isGood ? 'good' : 'bad'] || ["Keep going! (You got this... probably)"]; return arr[Math.floor(Math.random() * arr.length)]; }; function App() { const saved = typeof localStorage !== 'undefined' ? JSON.parse(localStorage.getItem('mfData4') || 'null') : null; const getIndustryDefaults = (id) => { const ind = industries[id]; const b = ind.y26; const baseOrders = 500; const traffic = Math.round(baseOrders / (b.cr / 100)); const budget = Math.round(baseOrders * ind.cac); return { traffic, budget, orders: baseOrders }; }; const defaultIndustry = 'ecom_fashion'; const defaults = getIndustryDefaults(defaultIndustry); const [industry, setIndustry] = useState(saved?.industry || defaultIndustry); const [margin, setMargin] = useState(saved?.margin || industries[defaultIndustry].margin); const [ltv, setLtv] = useState(saved?.ltv || industries[defaultIndustry].ltv); const [cpc, setCpc] = useState(saved?.cpc || industries[defaultIndustry].y26.cpc); const [cpm, setCpm] = useState(saved?.cpm || industries[defaultIndustry].y26.cpm); const [ctr, setCtr] = useState(saved?.ctr || industries[defaultIndustry].y26.ctr); const [cr, setCr] = useState(saved?.cr || industries[defaultIndustry].y26.cr); const [aov, setAov] = useState(saved?.aov || industries[defaultIndustry].y26.aov); const [traffic, setTraffic] = useState(saved?.traffic || defaults.traffic); const [budget, setBudget] = useState(saved?.budget || defaults.budget); const [actualOrders, setActualOrders] = useState(saved?.actualOrders || defaults.orders); const [targetRev, setTargetRev] = useState(saved?.targetRev || defaults.orders * 2 * industries[defaultIndustry].y26.aov); const [targetOrders, setTargetOrders] = useState(saved?.targetOrders || defaults.orders * 2); const [extraBudget, setExtraBudget] = useState(saved?.extraBudget || defaults.budget); const [monthlyGrowth, setMonthlyGrowth] = useState(saved?.monthlyGrowth || 5); const [scenarioBudgetMode, setScenarioBudgetMode] = useState('needed'); const [fieldCompleted, setFieldCompleted] = useState({}); const markFieldComplete = (field) => { setFieldCompleted(prev => ({ ...prev, [field]: true })); }; // 'needed' or 'new' const [lastTargetEdit, setLastTargetEdit] = useState('orders'); const [scenarios, setScenarios] = useState(saved?.scenarios || { pessimistic: { ctr: 0.87, cr: 1.34, cpc: 0.58, cpm: 10.37 }, realistic: { ctr: 1.24, cr: 1.92, cpc: 0.51, cpm: 9.10 }, optimistic: { ctr: 1.61, cr: 2.50, cpc: 0.46, cpm: 8.19 } }); const [modalOpen, setModalOpen] = useState(null); const handleTargetOrdersChange = (val) => { setTargetOrders(val); setTargetRev(Math.round(val * aov)); setLastTargetEdit('orders'); }; const handleTargetRevChange = (val) => { setTargetRev(val); if (aov > 0) setTargetOrders(Math.round(val / aov)); setLastTargetEdit('revenue'); }; useEffect(() => { if (lastTargetEdit === 'orders' && aov > 0) { setTargetRev(Math.round(targetOrders * aov)); } else if (lastTargetEdit === 'revenue' && aov > 0) { setTargetOrders(Math.round(targetRev / aov)); } }, [aov]); const changeIndustry = (id) => { setIndustry(id); const ind = industries[id]; const b = ind.y26; const defs = getIndustryDefaults(id); setMargin(ind.margin); setLtv(ind.ltv); setAov(b.aov); setCpc(b.cpc); setCpm(b.cpm); setCtr(b.ctr); setCr(b.cr); setTraffic(defs.traffic); setBudget(defs.budget); setActualOrders(defs.orders); setTargetOrders(defs.orders * 2); setTargetRev(defs.orders * 2 * b.aov); setExtraBudget(defs.budget); setMonthlyGrowth(getMonthlyGrowthBenchmark(id)); setScenarios({ pessimistic: { ctr: b.ctr * 0.7, cr: b.cr * 0.7, cpc: b.cpc * 1.15, cpm: b.cpm * 1.15 }, realistic: { ctr: b.ctr, cr: b.cr, cpc: b.cpc, cpm: b.cpm }, optimistic: { ctr: b.ctr * 1.3, cr: b.cr * 1.3, cpc: b.cpc * 0.9, cpm: b.cpm * 0.9 } }); }; const ind = industries[industry]; const yoyChange = getYoYChange(industry); const benchCr = ind.y26.cr; const benchCpc = ind.y26.cpc; const benchCpm = ind.y26.cpm; const benchAov = ind.y26.aov; const benchCac = ind.cac; const benchLtv = ind.ltv; const calc = useMemo(() => { const estOrders = Math.round(traffic * (cr / 100)); const actualCr = traffic > 0 ? (actualOrders / traffic) * 100 : 0; const revenue = actualOrders * aov; const estRevenue = estOrders * aov; const grossProfit = revenue * (margin / 100); const netProfit = grossProfit - budget; const roas = budget > 0 ? revenue / budget : 0; const roi = budget > 0 ? (netProfit / budget) * 100 : 0; const cac = actualOrders > 0 ? budget / actualOrders : 0; const estCac = estOrders > 0 ? budget / estOrders : 0; const maxCac = aov * (margin / 100); const cacLtv = ltv > 0 ? cac / ltv : 0; const payback = maxCac > 0 ? cac / maxCac : 0; const beRoas = margin > 0 ? 100 / margin : 0; const beCpa = maxCac; const beCr = budget > 0 && traffic > 0 && aov > 0 && margin > 0 ? (budget / (traffic * aov * (margin / 100))) * 100 : 0; const visitorValue = traffic > 0 ? revenue / traffic : 0; const estVisitorValue = traffic > 0 ? estRevenue / traffic : 0; const ordersGap = Math.max(0, targetOrders - actualOrders); const revGap = Math.max(0, targetRev - revenue); const actualCrDecimal = actualCr / 100; const extraTrafficNeeded = actualCrDecimal > 0 ? ordersGap / actualCrDecimal : 0; const extraBudgetNeeded = extraTrafficNeeded * cpc; const totalBudgetNeeded = budget + extraBudgetNeeded; const totalAvailableBudget = budget + extraBudget; const extraTrafficWithBudget = cpc > 0 ? extraBudget / cpc : 0; const extraOrdersWithBudget = extraTrafficWithBudget * actualCrDecimal; const revenueWithExtraBudget = (actualOrders + extraOrdersWithBudget) * aov; const grossProfitWithExtra = revenueWithExtraBudget * (margin / 100); const profitWithExtraBudget = grossProfitWithExtra - totalAvailableBudget; const progress = targetRev > 0 ? Math.min(100, (revenue / targetRev) * 100) : 0; const canReach = totalBudgetNeeded <= totalAvailableBudget; const budgetDiff = totalBudgetNeeded - extraBudget; const budgetDiffFromExtra = totalBudgetNeeded - totalAvailableBudget; const months = budgetDiff > 0 ? Math.ceil(Math.log(1 + (budgetDiff / budget)) / Math.log(1 + (monthlyGrowth / 100))) : 0; const cacScore = benchCac > 0 ? Math.min(99, Math.max(1, 100 - ((cac / benchCac) * 50))) : 50; const beScore = beRoas > 0 ? Math.min(99, Math.max(1, (roas / beRoas) * 50)) : 50; const cpcRatio = benchCpc > 0 ? cpc / benchCpc : 1; const crRatio = benchCr > 0 ? actualCr / benchCr : 1; const funnelScore = Math.min(99, Math.max(1, (100 - (cpcRatio - 1) * 50 + (crRatio - 1) * 50))); let risk = 'Low', riskScore = 80; if (roas < beRoas * 0.8 || cacLtv > 0.5) { risk = 'High'; riskScore = 25; } else if (roas < beRoas * 1.2 || cacLtv > 0.33) { risk = 'Medium'; riskScore = 55; } const yoyCacIncrease = parseFloat(yoyChange.cpc); riskScore = Math.max(1, Math.min(99, riskScore - yoyCacIncrease)); const expectedCacNextYear = cac * (1 + yoyCacIncrease / 100); const targetProbability = Math.min(99, Math.max(1, progress * 0.5 + (roas >= beRoas ? 30 : 0) + (cacLtv <= 0.33 ? 20 : 0))); const issues = []; const isOrdersBelowBenchmark = actualOrders < estOrders; const isCrBelowBenchmark = actualCr < benchCr; const isCacAboveBenchmark = cac > benchCac; if (isCrBelowBenchmark) { if (actualCr < benchCr * 0.5) { issues.push({ icon: '๐ŸŽฏ', text: 'Targeting & Persona need work', area: 'targeting' }); issues.push({ icon: '๐Ÿ’ฌ', text: 'Ad messaging not resonating', area: 'messaging' }); } else if (actualCr < benchCr * 0.8) { issues.push({ icon: '๐Ÿ–ฅ๏ธ', text: 'Landing pages need optimization', area: 'landing' }); issues.push({ icon: '๐Ÿ›’', text: 'Checkout has friction', area: 'checkout' }); } } if (isCacAboveBenchmark) { issues.push({ icon: '๐Ÿ’ธ', text: `CAC โ‚ฌ${cac.toFixed(0)} > industry โ‚ฌ${benchCac}`, area: 'cac' }); } const personaGood = !isCrBelowBenchmark && !isCacAboveBenchmark; const personaIssues = []; if (isCrBelowBenchmark) personaIssues.push('Low CR'); if (isCacAboveBenchmark) personaIssues.push('High CAC'); const targetGrossProfit = targetRev * (margin / 100); const targetNetProfit = targetGrossProfit - totalBudgetNeeded; return { actualOrders, estOrders, revenue, estRevenue, grossProfit, netProfit, roas, roi, actualCr, cac, estCac, maxCac, cacLtv, payback, beRoas, beCpa, beCr, visitorValue, estVisitorValue, revGap, ordersGap, extraBudgetNeeded, extraTrafficNeeded, totalBudgetNeeded, progress, canReach, months, risk, riskScore, isProfitable: netProfit > 0, personaGood, personaIssues, targetProbability, targetNetProfit, issues, isOrdersBelowBenchmark, isCrBelowBenchmark, isCacAboveBenchmark, cacScore, beScore, funnelScore, budgetDiff, budgetDiffFromExtra, revenueWithExtraBudget, profitWithExtraBudget, extraOrdersWithBudget, yoyCacIncrease, expectedCacNextYear, totalAvailableBudget }; }, [traffic, budget, aov, cpc, cr, margin, ltv, targetRev, targetOrders, extraBudget, actualOrders, yoyChange, benchCr, benchCpc, benchCac, monthlyGrowth]); const scenarioCalcs = useMemo(() => { const calcS = (s) => { const newBudget = scenarioBudgetMode === 'needed' ? calc.totalBudgetNeeded : extraBudget; const crDecimal = s.cr / 100; const newTraffic = traffic + calc.extraTrafficNeeded; const orders = Math.round(newTraffic * crDecimal); const rev = orders * aov; const gross = rev * (margin / 100); const profit = Math.round(gross - newBudget); const roas = newBudget > 0 ? rev / newBudget : 0; const scenarioCac = orders > 0 ? newBudget / orders : 0; return { revenue: Math.round(rev), profit, roas, orders, budget: Math.round(newBudget), cac: scenarioCac, reachTarget: rev >= targetRev }; }; return { pessimistic: calcS(scenarios.pessimistic), realistic: calcS(scenarios.realistic), optimistic: calcS(scenarios.optimistic) }; }, [scenarios, calc, traffic, aov, margin, scenarioBudgetMode, extraBudget]); const insights = useMemo(() => { const list = [...calc.issues]; if (calc.roas < calc.beRoas) list.push({ icon: '๐Ÿ“‰', text: `ROAS ${calc.roas.toFixed(2)}x < BE ${calc.beRoas.toFixed(2)}x`, type: 'danger' }); if (ltv < aov * 2) list.push({ icon: '๐Ÿ’Ž', text: 'Low LTV = one-time buyers', type: 'info' }); return list; }, [calc, ltv, aov]); const getBudgetComment = () => { const diff = calc.budgetDiff; if (diff <= 0) return { text: "๐ŸŽ‰ Budget surplus! Buy a yacht?", color: 'text-emerald-600' }; if (diff > budget * 2) return { text: "๐Ÿ’ธ Triple budget needed. Rob a bank? ๐Ÿฆ", color: 'text-red-500' }; if (diff > budget) return { text: "๐Ÿ˜ฌ Double budget needed. Sell a kidney?", color: 'text-amber-600' }; if (diff > budget * 0.5) return { text: "๐Ÿค” 50%+ more needed. Sweet-talk the CFO!", color: 'text-amber-500' }; return { text: "โœจ Almost there! Just a bit more juice.", color: 'text-emerald-500' }; }; const budgetComment = getBudgetComment(); const save = () => { localStorage.setItem('mfData4', JSON.stringify({ industry, margin, ltv, cpc, cpm, ctr, cr, aov, traffic, budget, actualOrders, targetRev, targetOrders, extraBudget, scenarios, monthlyGrowth })); alert('๐Ÿ˜… Nah, sorry friend!\n\nThis is a FREE tool made for quick sanity checks, not your enterprise planning solution.\n\nIf you want a REAL marketing plan with actual humans who know what they\'re doing, hit us up at SocialScore.io\n\nNow go forth and conquer! (Or at least try not to burn all your budget in week 1) ๐Ÿš€'); }; const reset = () => { if (confirm('Whoa there, cowboy! ๐Ÿค \n\nYou\'re about to DELETE everything you just did here. Poof! Gone! Like it never happened.\n\nBut here\'s the thing: In real business, there\'s no reset button. Your mistakes stick around like that embarrassing email you sent to "Reply All".\n\nStill want to nuke this and start fresh? Your funeral... ๐Ÿ’€')) { localStorage.removeItem('mfData4'); location.reload(); } }; return (
{/* Header */}
๐Ÿ“Š

Marketing ADS Forecaster Pro

B2C & E-commerce โ€ข 2026 Benchmarks

{/* Market Context */}

๐ŸŽฏ Market Context setModalOpen('marketContext')} />

โ‚ฌ setLtv(e.target.value===""?"":+e.target.value||0)} className="w-full pl-6 pr-3 py-2 border border-slate-200 rounded-lg text-sm focus:ring-2 focus:ring-emerald-500 outline-none" />

Ind. avg: โ‚ฌ{benchLtv}

๐Ÿ“ˆ {ind.name} โ€ข Jan 2025 โ†’ Jan 2026:

CPC
+{yoyChange.cpc}%
CPM
+{yoyChange.cpm}%
CTR
+{yoyChange.ctr}%
CR
+{yoyChange.cr}%
AOV
+{yoyChange.aov}%

โš ๏ธ CAC expected +{yoyChange.cpc}% (โ‚ฌ{benchCac} โ†’ โ‚ฌ{Math.round(benchCac * (1 + parseFloat(yoyChange.cpc)/100))})

2026 Benchmarks (editable):

{ setCpc(e.target.value===""?"":+e.target.value||0); markFieldComplete('cpc'); }} className="w-full px-2 py-1 text-sm border rounded focus:ring-1 focus:ring-emerald-500 outline-none"/>
{ setCpm(e.target.value===""?"":+e.target.value||0); markFieldComplete('cpm'); }} className="w-full px-2 py-1 text-sm border rounded focus:ring-1 focus:ring-emerald-500 outline-none"/>
setCtr(e.target.value===""?"":+e.target.value||0)} className="w-full px-2 py-1 text-sm border rounded focus:ring-1 focus:ring-emerald-500 outline-none"/>
setCr(e.target.value===""?"":+e.target.value||0)} className="w-full px-2 py-1 text-sm border rounded focus:ring-1 focus:ring-emerald-500 outline-none"/>
{ setAov(e.target.value===""?"":+e.target.value||0); markFieldComplete('aov'); }} className="w-full px-2 py-1 text-sm border rounded focus:ring-1 focus:ring-emerald-500 outline-none"/>
{/* Business Numbers */}

๐Ÿ“ˆ Business Numbers setModalOpen('businessNumbers')} />

๐Ÿ‘‰ Fill in YOUR actual business data below โ€” double-check your profit margin matches industry average!

{ setTraffic(val); markFieldComplete('traffic'); }} field="traffic" completed={fieldCompleted.traffic} onMarkComplete={() => markFieldComplete('traffic')} note="Website visitors" /> { setBudget(val); markFieldComplete('budget'); }} field="budget" completed={fieldCompleted.budget} onMarkComplete={() => markFieldComplete('budget')} prefix="โ‚ฌ" note="Monthly ad spend" /> { setActualOrders(val); markFieldComplete('actualOrders'); }} field="actualOrders" completed={fieldCompleted.actualOrders} onMarkComplete={() => markFieldComplete('actualOrders')} note="Your REAL orders" />
{ setAov(val); markFieldComplete('aov'); }} field="aov" completed={fieldCompleted.aov} onMarkComplete={() => markFieldComplete('aov')} prefix="โ‚ฌ" note="Revenue / Orders" /> { setCpc(val); markFieldComplete('cpc'); }} field="cpc" completed={fieldCompleted.cpc} onMarkComplete={() => markFieldComplete('cpc')} prefix="โ‚ฌ" note="Budget / Clicks" /> { setCpm(val); markFieldComplete('cpm'); }} field="cpm" completed={fieldCompleted.cpm} onMarkComplete={() => markFieldComplete('cpm')} prefix="โ‚ฌ" note="Per 1,000 impressions" />

Your Orders

{actualOrders.toLocaleString()} (est. {calc.estOrders.toLocaleString()})

Your CR

{calc.actualCr.toFixed(2)}% (ind. {benchCr}%)

{calc.isOrdersBelowBenchmark ? 'โš ๏ธ Below Est.' : 'โœ… On Track'}

{((actualOrders / calc.estOrders - 1) * 100).toFixed(0)}%

{/* Targets */}

๐Ÿš€ Targets (The Goal) โ€ข 2x your business setModalOpen('targets')} />

โ‚ฌ setExtraBudget(e.target.value===""?"":+e.target.value||0)} className="w-full pl-6 pr-3 py-2 border border-slate-200 rounded-lg text-sm focus:ring-2 focus:ring-emerald-500 outline-none" />

Marketing Budget + Extra available

๐Ÿ’ฐ Budget Needed

โ‚ฌ{Math.round(calc.totalBudgetNeeded).toLocaleString()}

Difference

0 ? 'text-red-500' : 'text-emerald-600'}`}> {calc.budgetDiff > 0 ? '+' : ''}โ‚ฌ{Math.round(calc.budgetDiff).toLocaleString()}

{calc.canReach ? 'โœ… Achievable' : 'โŒ Need more'}

{budgetComment.text}

{/* Quick Preview */}

โšก Quick Preview

{calc.isProfitable ? 'โœ…' : '๐Ÿ’€'}

{calc.isProfitable ? 'Profitable!' : 'Losing!'}

Net: โ‚ฌ{calc.netProfit.toLocaleString()}

Revenueโ‚ฌ{calc.revenue.toLocaleString()}
Orders{actualOrders} ({calc.estOrders})
ROAS{calc.roas.toFixed(2)}x
CACโ‚ฌ{calc.cac.toFixed(2)}
ROI 0 ? 'text-emerald-600' : 'text-red-500'}`}>{calc.roi.toFixed(1)}%

{calc.progress.toFixed(1)}% to goal

Budget Comparison

{/* Dashboard */}
{/* Verdict */}

{calc.isProfitable ? '๐Ÿš€ Money Printer Go Brrr!' : '๐Ÿšจ Houston, We Have a Problem!'}

{getSarcasticComment('verdict', calc.isProfitable)}

{/* Issues */} {insights.length > 0 && (

๐Ÿ’ก Performance Issues

{insights.map((ins, i) => (
{ins.icon} {ins.text}
))}
)} {/* Current & Target State */}

๐Ÿ“Š Current State setModalOpen('currentState')} />

= calc.beRoas} /> = 0} />

๐ŸŽฏ Target State setModalOpen('targetState')} />

= 0} />
{/* Scores */}

๐Ÿ“ˆ Performance Scores setModalOpen('performanceScores')} />

{calc.cacScore >= 70 && calc.beScore >= 70 ? "๐ŸŽ‰ Looking great! Keep crushing!" : calc.cacScore < 40 || calc.beScore < 40 ? "๐Ÿ˜ฌ Needs serious work. Coffee won't fix this." : "๐Ÿค” Room for improvement!"}

{/* Break-even & CAC */}

โš–๏ธ Break-even setModalOpen('breakeven')} />

BE ROAS{calc.beRoas.toFixed(2)}x
BE CPAโ‚ฌ{calc.beCpa.toFixed(2)}
Min CR{calc.beCr.toFixed(2)}%
{calc.roas >= calc.beRoas ? 'โœ… Above BE' : 'โŒ Below BE'}

{getSarcasticComment('breakeven', calc.roas >= calc.beRoas)}

๐Ÿ‘ฅ CAC Analysis setModalOpen('cacAnalysis')} />

Your CACโ‚ฌ{calc.cac.toFixed(2)}
Industryโ‚ฌ{benchCac}
CAC:LTV{(calc.cacLtv*100).toFixed(0)}%
2026 est.โ‚ฌ{calc.expectedCacNextYear.toFixed(2)}

{getSarcasticComment('cac', calc.cac <= benchCac)}

{/* Industry & Funnel */}

๐Ÿ“ˆ vs {ind.name}

๐Ÿ”— Funnel Costs setModalOpen('funnelCosts')} />

CPCโ‚ฌ{cpc.toFixed(2)}
CACโ‚ฌ{calc.cac.toFixed(2)}
CPMโ‚ฌ{cpm.toFixed(2)}
Visitor Valueโ‚ฌ{calc.visitorValue.toFixed(2)}

{getSarcasticComment('funnel', calc.funnelScore >= 50)}

{/* Risk & Time */}

๐Ÿ›ก๏ธ Risk setModalOpen('risk')} />

Target Prob.{calc.targetProbability.toFixed(0)}%
Pessimistic P&L= 0 ? 'text-emerald-600' : 'text-red-500'}`}>โ‚ฌ{scenarioCalcs.pessimistic.profit.toLocaleString()}
โš ๏ธ +{yoyChange.cpc}% CAC increase
๐Ÿ’ฐ Budget Gap 0 ? 'text-red-500' : 'text-emerald-600'}`}> {calc.budgetDiff > 0 ? '+' : ''}โ‚ฌ{Math.abs(Math.round(calc.budgetDiff)).toLocaleString()}

{getSarcasticComment('risk', calc.riskScore >= 50)}

โฑ๏ธ Time to Target setModalOpen('timeToTarget')} />

Growth Rate

{monthlyGrowth}%

monthly

setMonthlyGrowth(e.target.value===""?"":+e.target.value||0)} className="w-full pr-8 pl-3 py-2 border border-slate-200 rounded-lg text-sm focus:ring-2 focus:ring-emerald-500 outline-none" /> %

Benchmark: {getMonthlyGrowthBenchmark(industry)}%

{getSarcasticComment('time', calc.months <= 12)}

{/* Goal Calculator */}

๐ŸŽฏ Goal Calculator setModalOpen('goalCalculator')} />

For {targetOrders.toLocaleString()} orders

โ‚ฌ{Math.round(calc.totalBudgetNeeded).toLocaleString()}

budget

Traffic

{Math.round(traffic + calc.extraTrafficNeeded).toLocaleString()}

visitors

Progress

{calc.progress.toFixed(1)}%

of goal

Gap

โ‚ฌ{Math.round(Math.max(0, calc.budgetDiff)).toLocaleString()}

{calc.budgetDiffFromExtra > 0 ? 'short' : 'โœ… OK'}

Customer Persona

{calc.personaGood ? 'โœ…' : 'โŒ'}

{calc.personaGood ? 'Good' : calc.personaIssues.join(', ')}

{extraBudget > 0 && (

๐Ÿ“Š With +โ‚ฌ{extraBudget.toLocaleString()}:

Extra Orders: +{Math.round(calc.extraOrdersWithBudget).toLocaleString()}
Revenue: โ‚ฌ{Math.round(calc.revenueWithExtraBudget).toLocaleString()}
Profit: = 0 ? 'text-emerald-600' : 'text-red-500'}`}>โ‚ฌ{Math.round(calc.profitWithExtraBudget).toLocaleString()}
)}

{getSarcasticComment('persona', calc.personaGood)}

{/* Scenarios */}

๐ŸŽญ Scenarios setModalOpen('scenarios')} /> โ€ข โ‚ฌ{Math.round(calc.totalBudgetNeeded).toLocaleString()} budget

{[ { key: 'pessimistic', name: 'Pessimistic', emoji: '๐Ÿ˜ฐ', desc: 'War, Covid, Crisis, Trump...', bg: 'bg-amber-50', border: 'border-amber-200', inputBg: 'bg-amber-100' }, { key: 'realistic', name: 'Realistic', emoji: '๐Ÿ˜', desc: 'Business as usual, every day hustle', bg: 'bg-emerald-50', border: 'border-emerald-200', inputBg: 'bg-emerald-100' }, { key: 'optimistic', name: 'Optimistic', emoji: '๐Ÿฆ„', desc: 'Go Viral, pink unicorn, stars aligned, worked harder', bg: 'bg-blue-50', border: 'border-blue-200', inputBg: 'bg-blue-100' } ].map(s => { const sc = scenarioCalcs[s.key]; const data = scenarios[s.key]; return (
{s.emoji}
{s.name}

{s.desc}

Budgetโ‚ฌ{sc.budget.toLocaleString()}
Orders{sc.orders.toLocaleString()}
Revenueโ‚ฌ{sc.revenue.toLocaleString()}
Profit= 0 ? 'text-emerald-600' : 'text-red-500'}`}>โ‚ฌ{sc.profit.toLocaleString()}
ROAS= 1 ? 'text-emerald-600' : 'text-red-500'}`}>{sc.roas.toFixed(2)}x
CACโ‚ฌ{sc.cac.toFixed(2)}
{sc.reachTarget ? 'โœ… Target' : 'โŒ Miss'}
setScenarios(p => ({...p, [s.key]: {...p[s.key], ctr: +e.target.value||0}}))} className="w-full px-1 py-0.5 text-xs border rounded bg-white outline-none"/>
setScenarios(p => ({...p, [s.key]: {...p[s.key], cr: +e.target.value||0}}))} className="w-full px-1 py-0.5 text-xs border rounded bg-white outline-none"/>
setScenarios(p => ({...p, [s.key]: {...p[s.key], cpc: +e.target.value||0}}))} className="w-full px-1 py-0.5 text-xs border rounded bg-white outline-none"/>
setScenarios(p => ({...p, [s.key]: {...p[s.key], cpm: +e.target.value||0}}))} className="w-full px-1 py-0.5 text-xs border rounded bg-white outline-none"/>
); })}
{/* Socialscore CTA Section with Disclaimer */}

Numbers are just half the story. Ready to define the ideal customer persona that actually converts?

Build Your Persona at Socialscore.io โ†’

Disclaimer: All industry benchmark data has been gathered through independent online research, tracking industry averages for 2025 and 2026, as well as statistical projections based on historical data.

Please do not consider this tool as investment advice. A thorough analysis of your specific business is required before proceeding with planning and implementation. This tool is provided for informational and entertainment purposes only. Learn more about our methodology here.

Marketing ADS Forecaster Pro โ€ข Built with โค๏ธ โ€ข 2026 Socialscore.io

{/* Tooltip Modals */} setModalOpen(null)} title="๐Ÿ“– How to Use This Forecaster" content={getTooltipContent(industry).guide} /> setModalOpen(null)} title="๐ŸŽฏ Market Context Explained" content={getTooltipContent(industry).marketContext} /> setModalOpen(null)} title="๐Ÿ“ˆ Business Numbers - Your Input" content={getTooltipContent(industry).businessNumbers} /> setModalOpen(null)} title="๐Ÿš€ Targets (The Goal)" content={getTooltipContent(industry).targets} /> setModalOpen(null)} title="๐Ÿ“Š Current State" content={getTooltipContent(industry).currentState} /> setModalOpen(null)} title="๐ŸŽฏ Target State" content={getTooltipContent(industry).targetState} /> setModalOpen(null)} title="๐Ÿ“ˆ Performance Scores" content={getTooltipContent(industry).performanceScores} /> setModalOpen(null)} title="๐Ÿ‘ฅ CAC Analysis" content={getTooltipContent(industry).cacAnalysis} /> setModalOpen(null)} title="โš–๏ธ Break-even Analysis" content={getTooltipContent(industry).breakeven} /> setModalOpen(null)} title="๐Ÿ”— Funnel Costs" content={getTooltipContent(industry).funnelCosts} /> setModalOpen(null)} title="๐Ÿ›ก๏ธ Risk Assessment" content={getTooltipContent(industry).risk} /> setModalOpen(null)} title="๐ŸŽฏ Goal Calculator" content={getTooltipContent(industry).goalCalculator} /> setModalOpen(null)} title="๐ŸŽญ Scenario Analysis" content={getTooltipContent(industry).scenarios} /> setModalOpen(null)} title="โฑ๏ธ Time to Target" content={getTooltipContent(industry).timeToTarget} /> setModalOpen(null)} title="โ“ What is This Tool?" content={getTooltipContent(industry).whatIsThis} />
); } ReactDOM.createRoot(document.getElementById('root')).render();