Product Demand Testing
Dashboard
Documentation
v7 · ecom Intelligence

BG Dashboard
Documentation

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.


Scoring Weights & Hard Stop

StepWeightLogic
1 · Goal Setting5%Raw hypothesis — no market data yet
2 · Market Pre-validation30%Real signals: Keepa, BA, Keywords, TikTok
3 · Survey & Results40%Direct consumer signal — most important
4 · Unit Economics20%Hard financial filter
5 · Final Report5%Synthesis, no new data

Hard Stop: if Unit Economics margin < 10%, cumulative score is capped at 35/100 regardless of other steps.


Step 1 — Goal Setting

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.

Score breakdown (100 pts total)

ComponentMaxHow it's calculated
Fields completeness35Client-side: (filled fields / 8) × 35. Fill all 8 fields for max.
Consumer need15Model, 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 / USP15Model: 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-market10Model: where it sells, to whom, and why now. 10 for all three · 5 for one or two · 0 for none.
Price precision10Client-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 assessment15Model: 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.

Inputs

FieldRequiredTips for max score
Product name✅Include format/variant e.g. "Tubing Mascara 'Cobra'"
Hypothesis type+ptsNew product / Design change / Price reposition / New market
Target market+ptsUSA for this tool's data sources
Category+ptsSpecific subcategory e.g. "Mascara — Eye Makeup"
Idea description✅Must include: problem + USP + any strategy hint
Source of idea+ptsTikTok trend / Trade show / Competitor analysis...
Price range+ptsNarrow range = higher score. Exact price = 10/10

Ideal description example

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.

AI Prompt

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.

Output blocks

  • Score ring, product name, and the decision (GO ≥ 65 · REFINE 40–64 · NO-GO < 40) — the words come from the score, so they cannot contradict it
  • Six tiles: points awarded over points available, with a rule showing the share, because 8/10 and 11/15 are not comparable at a glance
  • Hypothesis assessment — one paragraph, the model's judgement
  • What to refine — three weaknesses in the hypothesis, each naming the step that settles it. If the model returns none, the card is built from the breakdown instead, which is arithmetic and not a guess
  • What to pull in step 2 — the filters, keywords and hashtags to collect, one card per source

How to optimize

  • Move the GO / REFINE / NO-GO thresholds: s1Verdict()
  • Change price scoring: the priceScore= formula in run1()
  • Add a component: add its test to the prompt, add it to the tiles array in renderStep1(), and add it to the Breakdown line the prompt asks for — the parser reads the tiles off that line
  • Tighten a criterion: the anchors live in the prompt above. Vague anchors are what make two runs of the same hypothesis land on different scores

Step 2 — Market Pre-validation

Analyzes real market data → budget holder dashboard with score, SWOT, requirements, success probability. Takes 1–2 minutes with full dataset.

Data sources

SourceFormat+AccuracyWhat it provides
Keepa Product FinderCSV export+35Revenue, BSR, competitor prices, sales velocity
Helium10 KeywordsCerebro/Magnet CSV+20Search volume, keyword difficulty, trends
Brand AnalyticsCSV / Excel+15Click share, conversion rate by keyword
TikTok ShopManual text+7Organic GMV, top products, creator rates
Google TrendsCSV+5Macro trend, seasonality curve
eMarketerCSV / Excel+8Market size forecast, channel distribution
Top-3 ReviewsTXT / CSV+12Consumer 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

Scoring criteria (6 dimensions)

Market Size & Growth  ×20
Competition           ×18
Search Demand         ×17
TikTok Signal         ×15
Product Requirements  ×15
Entry Barrier         ×15

JSON Schema

{
  "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.

How to optimize

  • Change criteria weights: find const CRITERIA=[...] in code, edit w: values (sum must = 100)
  • Add a criterion: add entry to CRITERIA array and corresponding field to JSON schema
  • Stricter SWOT: add "Every SWOT point must cite a specific number or source" to prompt
  • Reduce timeout risk: lower trim limits (currently Keepa 30 rows, Keywords 25, BA 20)

Step 3 — Survey & Results

Parses QuestionPro / SurveyMonkey XLSX, computes all KPIs client-side, renders visual dashboard. No AI for calculations.

File format

Upload: XLSX export from QuestionPro. Columns detected by keyword search — not fixed positions. Works with any QuestionPro survey structure.

KPIDetection 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"

Van Westendorp

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

Price Elasticity chart

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

Score formula

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%

AI "Extract Insights" (optional button)

Analyzes open-text responses ("What made you choose this design?")
Returns JSON: { "likes": [...], "dislikes": [...], "claim_ideas": [...] }
max_tokens: 2000

Output blocks

  • Funnel — Total / Completed / Valid respondents
  • Purchase Intent circular gauge — threshold at 60%
  • Van Westendorp — 5 price anchors (too cheap → too expensive)
  • Price Elasticity SVG curve with green optimal zone shading
  • Product Insights — statement agreement bars + ✨ Extract Insights AI button
  • Design Preference — bar chart by option, winner in gold
  • Audience Profile — Gender, Age, Openness to new brands, Top purchase factors

How to optimize

  • Change PI threshold: edit pi>=60 ? 80 in run5()
  • Add NPS: parse column with "likely to recommend" keyword
  • Richer claims: add "Suggest 3 Amazon bullet points" to Extract Insights prompt

Step 4 — Unit Economics

Instant P&L calculator using real Q4 platform fees. Computed in browser — no API call for basic calc.

Fee schedules (Q4 actual data)

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

P&L formula

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

Verdict thresholds

margin ≥ 25%  → ✅ VIABLE
margin 10–24% → ⚠️ MARGINAL
margin < 10%  → ❌ NOT VIABLE + Hard Stop (cumulative capped at 35)

AI analysis prompt (optional)

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

How to optimize

  • Update fees: find const FEE_SCHEDULES={...} in code
  • Change VIABLE threshold: edit margin>=25 in calcUE()
  • Change MARGINAL threshold: edit margin>=10 (also controls Hard Stop)
  • Add CAC field: add "Customer Acquisition Cost" input to Amazon fields section

Step 5 — Final Report

Synthesizes all steps into a GO/NO-GO decision. Generates downloadable 8-slide PPTX presentation.

Cumulative score formula

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)

AI prompt

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"
}

PPTX — 9 slides

SlideContent
1 · CoverImage placeholder + Decision + Cumulative Score + Date
2 · Scorecard4 step tiles with weights + cumulative banner + rationale
3 · Market ValidationStrengths / Concerns / Bottlenecks — from Step 2 SWOT data
4 · Price IntelligenceVW 5 anchors · Our price vs optimal zone · Margin/Platform/PI%
5 · Product Insights & ElasticityConsumer Voice · Claim ideas · Price elasticity bar chart
6 · For & AgainstPros (green) / Risks (red) columns + conditions
7 · Next StepsDecision banner + 3 numbered action items with owners
8 · Data GapsAuto-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.

How to optimize

  • Stricter GO: add "Only GO if cumulative ≥ 65" to prompt
  • Add a slide: find exportPPTX() in combined file, add var sl9=pres.addSlide()
  • Change slide colors: edit DARK, LIGHT, ACC, GRN, RED, GOLD in exportPPTX()
  • Logo on slides: s1.addImage({path:'url',x:0.3,y:5.2,w:1.5,h:0.3})

Deployment

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.

Vercel proxy (api/claude.js)

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 works without deployment (no API key)

  • P&L calculator — instant math, no API
  • Survey XLSX parsing + all charts — no API
  • Price distribution from Keepa — no API
  • PPTX download (9 slides) — PptxGenJS, no API

Quick Reference

WhatWhere in codeHow
Step weightsW={1:0.05,2:0.30,...} in run6()Must sum to 1.0
Hard stopif(n===4&&score<25)25 = margin% × 2.5
PI threshold (Step 3)pi>=60?80 in run5()Change 60 to desired %
Scorecard weightsconst CRITERIA=[...]w: values, total = 100
Platform feesconst FEE_SCHEDULES={...}Update quarterly from platform docs
Margin thresholdsmargin>=25 in calcUE()25 = VIABLE, 10 = MARGINAL
AI modelAll apiFetch() callsChange "claude-sonnet-4-6"
Step 1 promptconst p= in run1()Edit the string literal directly
Step 2 promptconst jsonPrompt= in run2()Edit — keep JSON structure intact
Step 3 promptconst p= in run5()Text analysis prompt
Step 4 promptconst prompt= in runUE()Edit — keep JSON structure intact
Step 5 promptconst prompt= in run6()Edit — keep JSON structure intact
API timeout120000 in apiFetch()Milliseconds — 120s default
PPTX slide colorsDARK,LIGHT,ACC,GRN,RED,GOLD in exportPPTX()6-char hex, no # prefix