Product Demand Testing · 5-step GO/NO-GO framework · US ecom (Amazon, TikTok, Shopify)
This document describes how each step works, what data is needed, the exact AI prompts used, and how to tune behavior. To change anything — edit the prompt or formula here and ask Claude to update it in the code.
| Step | Weight | Logic |
|---|---|---|
| 1 · Goal Setting | 5% | Raw hypothesis — no market data yet |
| 2 · Market Pre-validation | 30% | Real signals: Keepa, BA, Keywords, TikTok |
| 3 · Survey & Results | 40% | Direct consumer signal — most important |
| 4 · Unit Economics | 20% | Hard financial filter |
| 5 · Final Report | 5% | Synthesis, no new data |
Hard Stop: if Unit Economics margin < 10%, cumulative score is capped at 35/100 regardless of other steps.
Scores the hypothesis as written, before any file is uploaded. Nothing here is market evidence: the model is told in the prompt that it has no figures for this category and must not state any. Two of the six components are computed in the browser and handed to the model as given, so they cannot drift between runs. SWOT was removed from this step — with no data loaded, all four quadrants were the model restating the description back in four boxes.
| Component | Max | How it's calculated |
|---|---|---|
| Fields completeness | 35 | Client-side: (filled fields / 8) × 35. Fill all 8 fields for max. |
| Consumer need | 15 | Model, against a written test: 15 if the description names both a specific problem and who has it · 8 if the problem is vague or the sufferer is "everyone" · 0 if it is a feature list with no problem behind it. |
| Uniqueness / USP | 15 | Model: 15 if the difference is in the product · 8 if it is in positioning or the bundle · 0 if it is only adjectives — anything a competitor could add to their listing tomorrow. |
| Go-to-market | 10 | Model: where it sells, to whom, and why now. 10 for all three · 5 for one or two · 0 for none. |
| Price precision | 10 | Client-side, from the width of the range: exact price = 10 · ≤$3 = 9 · ≤$5 = 8 · ≤$8 = 6 · ≤$12 = 5 · ≤$18 = 3 · wider = 2. No range at all = 0. |
| Expert assessment | 15 | Model: how likely this hypothesis is to survive contact with real data, and what would have to be true for it to. The one component that is judgement alone, so the prompt asks for the reasoning to be visible. |
| Field | Required | Tips for max score |
|---|---|---|
| Product name | ✅ | Include format/variant e.g. "Tubing Mascara 'Cobra'" |
| Hypothesis type | +pts | New product / Design change / Price reposition / New market |
| Target market | +pts | USA for this tool's data sources |
| Category | +pts | Specific subcategory e.g. "Mascara — Eye Makeup" |
| Idea description | ✅ | Must include: problem + USP + any strategy hint |
| Source of idea | +pts | TikTok trend / Trade show / Competitor analysis... |
| Price range | +pts | Narrow range = higher score. Exact price = 10/10 |
Tubing mascara — tubes wrap each lash, slide off with warm water.
No panda eyes. TikTok #tubingmascara 890M views. Gap at $15–18:
Essence $7, Tarte $25+. Target: 25–40 sensitive-eye buyers on Amazon,
DTC launch then TikTok Shop expansion.
Copied out of the code at build time, so it is what actually runs.
You are a senior ecommerce operator who has launched beauty and FMCG products
for twelve years. You are reading a product hypothesis at the very start of a
validation process.
WHAT YOU HAVE: the form below, and nothing else. No market file has been uploaded
yet — that is step 2. You therefore have NO figures for this category, this
product or its competitors.
WHAT THIS MEANS FOR YOU:
· Do not state a market size, a growth rate, a competitor's price, a search volume
or any other number as if you knew it. You do not.
· Where a claim would need such a number, write it as something to verify in step 2
instead of asserting it.
· Your judgement of the hypothesis is welcome and is what you are here for. Invented
evidence for that judgement is not.
PRODUCT HYPOTHESIS
- Name: {name}
- Type: {type} · Market: {market} · Category: {category}
- Where the idea came from: {source}
- Target price: ${price_from}–${price_to}
- Description as written by the team:
{description}
SCORING — 100 points, two of them already computed:
· Completeness of the form: {completeness}/35 — computed, use as given.
· Price-range viability: {price_score}/10 — computed from the width of the range, use as given.
The remaining 55 are yours, and each has a test. Award the points only when the
test is met by the text above; award 0 when it is not. Half marks only where the
scale says so.
· Consumer need — 15 points. Does the description name a specific problem and who
has it? 15 if both are there and the problem is one a person would recognise in
themselves. 8 if a problem is named but vaguely, or the sufferer is "everyone".
0 if the description is a list of features with no problem behind them.
· Uniqueness — 15 points. Is there something here a competitor could not put on
their own listing tomorrow? 15 if the difference is in the product. 8 if it is
in the positioning or the bundle. 0 if the difference is only adjectives.
· Go-to-market — 10 points. Does the text say where this sells, to whom, and why
now? 10 for all three, 5 for one or two, 0 for none.
· Your own assessment — 15 points. Given twelve years of launches: how likely is
this hypothesis to survive contact with real data? Say what would have to be
true, and score how plausible that is. This is the one place your judgement
stands alone, so make the reasoning visible.
OUTPUT — exactly this shape, nothing before or after it:
**SCORE: [X]/100**
_Breakdown: Completeness {completeness}/35 · Need [X]/15 · Uniqueness [X]/15 · Strategy [X]/10 · Price {price_score}/10 · Expert [X]/15_
**Hypothesis Assessment**
2–3 sentences. Lead with the single thing that most determines whether this works.
**What to refine**
Exactly three points, no more. Each names a weakness in the hypothesis as it is
written — not a risk of the market — and each starts with a short bold label of
two or three words, then one or two sentences: what is thin, and what would
settle it. Where a later step settles it, say which (step 2 for market evidence,
step 3 for the survey, step 4 for the economics). Raise nothing the description
above does not already put in doubt.
**What to pull in step 2** — be specific enough that somebody can act on it without asking you:
- Keepa Product Finder: category, price band to filter on (derived from the target
price above), minimum monthly units worth looking at, and why those bounds.
- Helium10: 3–5 seed keywords a buyer of this product would actually type.
- Google Trends: the search terms and the timeframe, and what shape would support
or kill this hypothesis.
- TikTok Shop: the hashtags and the category to look at.
- Reviews: which competitor products to pull reviews for, and the complaint you
most expect to find.
**DECISION: GO to market validation** or **Needs refinement**
One sentence saying which, and what would change it.
s1Verdict()priceScore= formula in run1()tiles array in renderStep1(), and add it to the Breakdown line the prompt asks for — the parser reads the tiles off that lineAnalyzes real market data → budget holder dashboard with score, SWOT, requirements, success probability. Takes 1–2 minutes with full dataset.
| Source | Format | +Accuracy | What it provides |
|---|---|---|---|
| Keepa Product Finder | CSV export | +35 | Revenue, BSR, competitor prices, sales velocity |
| Helium10 Keywords | Cerebro/Magnet CSV | +20 | Search volume, keyword difficulty, trends |
| Brand Analytics | CSV / Excel | +15 | Click share, conversion rate by keyword |
| TikTok Shop | Manual text | +7 | Organic GMV, top products, creator rates |
| Google Trends | CSV | +5 | Macro trend, seasonality curve |
| eMarketer | CSV / Excel | +8 | Market size forecast, channel distribution |
| Top-3 Reviews | TXT / CSV | +12 | Consumer voice, pains, claim ideas |
Rule: missing source → score = 0 for that criterion. The system never guesses.
How to export Keepa: keepa.com → Product Finder → set filters → Export CSV
How to export BA: Seller Central → Brand Analytics → Search Frequency Rank → export
Market Size & Growth ×20
Competition ×18
Search Demand ×17
TikTok Signal ×15
Product Requirements ×15
Entry Barrier ×15
{
"verdict": "GO" | "NO-GO" | "CONDITIONAL GO",
"total_score": 0-100,
"scores": {
"market/comp/search/tiktok/product/barrier": {
"score": 0-100, "note": "1 line", "key_fact": "specific number"
}
},
"requirements": [
{"icon":"⭐","metric":"Min. Rating","value":"≥4.3★","rationale":"..."},
{"icon":"💬","metric":"Min. Reviews","value":"≥500","rationale":"..."},
{"icon":"📦","metric":"Sales Target","value":"≥800/mo","rationale":"..."},
{"icon":"💰","metric":"Price Window","value":"$14–$20","rationale":"..."},
{"icon":"📈","metric":"Growth Rate","value":"≥8%/mo","rationale":"..."},
{"icon":"🏆","metric":"BSR Target","value":"Top 500","rationale":"..."}
],
"success_probability_min": 0-100,
"success_probability_max": 0-100,
"prob_title": "phrase",
"swot": {
"strengths/weaknesses/opportunities/threats": ["point with data", "..."]
},
"consumer_voice": ["buyer insight", "..."],
"next_steps": [{"num":"01","title":"...","desc":"..."}],
"review_insights": null | {
"top_positives": [...], "top_pains": [...],
"claim_suggestions": ["in buyer language"]
}
}
Probability range rule: spread 10–20 pts. Score ≥65 → min ≥50. Score <40 → max ≤45.
const CRITERIA=[...] in code, edit w: values (sum must = 100)Parses QuestionPro / SurveyMonkey XLSX, computes all KPIs client-side, renders visual dashboard. No AI for calculations.
Upload: XLSX export from QuestionPro. Columns detected by keyword search — not fixed positions. Works with any QuestionPro survey structure.
| KPI | Detection keyword in header |
|---|---|
| Purchase Intent (1–5 scale) | "agree with the following" + "consider purchasing" |
| VW Too Expensive | "expensive that you would not" |
| VW Getting Expensive | "starting to get expensive" |
| VW Bargain | "bargain" |
| VW Too Cheap | "quality couldn't" |
| Design preference | "embossing" or "color palette" |
| Open-text responses | "what made you choose" |
4 open-number questions → compute medians:
Optimal Price = (Bargain + Getting Expensive) / 2
Acceptable Range = Bargain .. Getting Expensive
Example (highlighter survey, n=55):
Too cheap $5 · Bargain $15 · Getting expensive $20 · Too expensive $30
→ Optimal: $17.50 · Acceptable range: $15–$20
For each price point ($8, $10, $12, $14, $16, $18, $20, $22, $25, $30):
% acceptable = respondents where (too_expensive >= price) / total
Rendered as SVG bar chart with:
- Green shaded zone = VW acceptable range
- 80% threshold dashed line
- Your price highlighted in blue
base = pi>=60 ? 80 : pi>=40 ? 55 : pi>=20 ? 30 : 20
bonus = price in VW optimal zone ? +10 : 0
final = min(100, base + bonus)
Purchase Intent = (answers 4 or 5 on 1–5 scale) / total × 100%
PASS threshold: PI >= 60%
Analyzes open-text responses ("What made you choose this design?")
Returns JSON: { "likes": [...], "dislikes": [...], "claim_ideas": [...] }
max_tokens: 2000
pi>=60 ? 80 in run5()Instant P&L calculator using real Q4 platform fees. Computed in browser — no API call for basic calc.
AMAZON:
FBA fee — Small $2.68 · Standard $3.09 · Large $3.16 /unit
Referral — price <$10: 8% / price ≥$10: 15% ← not flat!
Storage — ~$0.012/unit
TIKTOK SHOP:
FBT delivery — $4.03/unit (avg Q4)
Referral fee — 3.9% of price
Creator commission — avg 8.8%, range 0–16.5%
SHOPIFY:
Delivery — Economy $3.10 · Standard $6.20 /order
Shopify Payments — 4.5% of price
Example: Amazon, price $16.99, COGS $4.50, Standard, PPC $2.50, Discount $1.00
FBA: $3.09
Referral: $16.99 × 15% = $2.55 ← price ≥$10
Storage: $0.012
PPC: $2.50 (manual)
Discount: $1.00 (manual)
Total cost: $4.50 + $3.09 + $2.55 + $0.01 + $2.50 + $1.00 = $13.65
Profit: $16.99 − $13.65 = $3.34
Margin: 19.7%
Monthly: $3.34 × 2,000 units = $6,680
margin ≥ 25% → ✅ VIABLE
margin 10–24% → ⚠️ MARGINAL
margin < 10% → ❌ NOT VIABLE + Hard Stop (cumulative capped at 35)
Returns JSON with: verdict, verdict_reason, optimal_price, price_floor,
price_ceiling, price_position, cost_wins (3 margin improvements),
volume_needed, timeline_months, key_risk
max_tokens: 4000
const FEE_SCHEDULES={...} in codemargin>=25 in calcUE()margin>=10 (also controls Hard Stop)Synthesizes all steps into a GO/NO-GO decision. Generates downloadable 8-slide PPTX presentation.
weights = {1: 5%, 2: 30%, 3: 40%, 4: 20%, 5: 5%}
cumulative = Σ(score[n] × weight[n]) for all completed steps
Hard stop: step 4 margin <10% → cumulative = min(cumulative, 35)
GO/NO-GO recommendation. Return JSON only (max_tokens: 4000).
INPUT: scores from all steps, PI%, VW optimal price, margin%
OUTPUT JSON:
{
"decision": "GO" | "NO-GO" | "CONDITIONAL GO",
"decision_rationale": "2–3 sentences for leadership",
"pros": ["4 reasons with specific numbers"],
"cons": ["3 risks with specifics"],
"conditions": ["if CONDITIONAL GO, else []"],
"market_summary": "2 sentences",
"survey_summary": "2 sentences",
"ue_summary": "2 sentences",
"next_steps": ["action + owner/deadline × 3"],
"launch_timeline": "e.g. Q3 2026 if GO by May"
}
| Slide | Content |
|---|---|
| 1 · Cover | Image placeholder + Decision + Cumulative Score + Date |
| 2 · Scorecard | 4 step tiles with weights + cumulative banner + rationale |
| 3 · Market Validation | Strengths / Concerns / Bottlenecks — from Step 2 SWOT data |
| 4 · Price Intelligence | VW 5 anchors · Our price vs optimal zone · Margin/Platform/PI% |
| 5 · Product Insights & Elasticity | Consumer Voice · Claim ideas · Price elasticity bar chart |
| 6 · For & Against | Pros (green) / Risks (red) columns + conditions |
| 7 · Next Steps | Decision banner + 3 numbered action items with owners |
| 8 · Data Gaps | Auto-detects missing sources per step · green if complete |
How the download works: click "📥 Download Presentation (.pptx)" → data sent to parent file via postMessage → PptxGenJS generates file → browser downloads it directly. No Claude needed.
Adding product photo to Slide 1: open in PowerPoint → click the gray placeholder → insert your product image.
exportPPTX() in combined file, add var sl9=pres.addSlide()DARK, LIGHT, ACC, GRN, RED, GOLD in exportPPTX()s1.addImage({path:'url',x:0.3,y:5.2,w:1.5,h:0.3})In claude.ai: all AI calls work via the built-in proxy — open the combined file as an artifact and everything works.
On a standalone site: direct requests to api.anthropic.com fail with CORS. Need a Vercel serverless proxy.
export default async function handler(req, res) {
const r = await fetch('https://api.anthropic.com/v1/messages', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': process.env.ANTHROPIC_API_KEY,
'anthropic-version': '2023-06-01'
},
body: JSON.stringify(req.body)
});
res.json(await r.json());
}
Then in bg_new.html: replace all fetch("https://api.anthropic.com/v1/messages" with fetch("/api/claude".
| What | Where in code | How |
|---|---|---|
| Step weights | W={1:0.05,2:0.30,...} in run6() | Must sum to 1.0 |
| Hard stop | if(n===4&&score<25) | 25 = margin% × 2.5 |
| PI threshold (Step 3) | pi>=60?80 in run5() | Change 60 to desired % |
| Scorecard weights | const CRITERIA=[...] | w: values, total = 100 |
| Platform fees | const FEE_SCHEDULES={...} | Update quarterly from platform docs |
| Margin thresholds | margin>=25 in calcUE() | 25 = VIABLE, 10 = MARGINAL |
| AI model | All apiFetch() calls | Change "claude-sonnet-4-6" |
| Step 1 prompt | const p= in run1() | Edit the string literal directly |
| Step 2 prompt | const jsonPrompt= in run2() | Edit — keep JSON structure intact |
| Step 3 prompt | const p= in run5() | Text analysis prompt |
| Step 4 prompt | const prompt= in runUE() | Edit — keep JSON structure intact |
| Step 5 prompt | const prompt= in run6() | Edit — keep JSON structure intact |
| API timeout | 120000 in apiFetch() | Milliseconds — 120s default |
| PPTX slide colors | DARK,LIGHT,ACC,GRN,RED,GOLD in exportPPTX() | 6-char hex, no # prefix |