import re import math from typing import Optional # ══════════════════════════════════════════════════════════════════════════════ # 1. SALES ESTIMATOR v2 — category-specific BSR → monthly sales # ══════════════════════════════════════════════════════════════════════════════ CATEGORY_MULTIPLIERS = { "kitchen": {"base": 8000, "decay": 0.55}, "home": {"base": 7000, "decay": 0.55}, "sports": {"base": 6000, "decay": 0.52}, "toys": {"base": 9000, "decay": 0.58}, "beauty": {"base": 7500, "decay": 0.54}, "health": {"base": 6500, "decay": 0.53}, "tools": {"base": 5000, "decay": 0.50}, "office": {"base": 5500, "decay": 0.51}, "pet": {"base": 6000, "decay": 0.52}, "garden": {"base": 4500, "decay": 0.50}, "default": {"base": 6000, "decay": 0.52}, } def estimate_sales_v2(bsr: int, category: str = "default", price: float = 25.0) -> dict: cat = CATEGORY_MULTIPLIERS.get(category.lower(), CATEGORY_MULTIPLIERS["default"]) if bsr <= 0: bsr = 50000 monthly_sales = int(cat["base"] * math.pow(bsr, -cat["decay"]) * 1000) monthly_sales = max(1, min(monthly_sales, 50000)) monthly_revenue = round(monthly_sales * price, 2) daily_sales = round(monthly_sales / 30, 1) # Confidence based on BSR range if bsr < 5000: confidence = "High" elif bsr < 50000: confidence = "Medium" else: confidence = "Low" return { "monthly_sales": monthly_sales, "daily_sales": daily_sales, "monthly_revenue": monthly_revenue, "confidence": confidence, "category": category, "bsr": bsr, "price": price, "annual_revenue": round(monthly_revenue * 12, 2), } # ══════════════════════════════════════════════════════════════════════════════ # 2. REVIEW ANALYZER — sentiment + patterns # ══════════════════════════════════════════════════════════════════════════════ POSITIVE_WORDS = ["great","excellent","perfect","love","amazing","best","good","quality","easy","fast","recommend","happy","pleased","works","nice","fantastic","awesome","solid","durable","comfortable"] NEGATIVE_WORDS = ["poor","bad","terrible","worst","broken","useless","cheap","waste","disappointed","defective","fragile","flimsy","slow","wrong","missing","return","refund","fake","stopped","horrible"] QUALITY_WORDS = ["quality","durable","sturdy","solid","premium","cheap","flimsy","fragile","well-made","poorly made"] DELIVERY_WORDS = ["fast","quick","slow","delivery","shipping","arrived","late","early","package","damaged"] VALUE_WORDS = ["worth","value","price","expensive","cheap","affordable","overpriced","deal","bargain"] def analyze_reviews(rating: float, review_count: int, title: str = "") -> dict: """Analyze product based on available data — real NLP would need actual review text.""" # Star distribution estimate if rating >= 4.5: stars = {"5": 70, "4": 20, "3": 5, "2": 3, "1": 2} elif rating >= 4.0: stars = {"5": 55, "4": 25, "3": 10, "2": 5, "1": 5} elif rating >= 3.5: stars = {"5": 40, "4": 25, "3": 15, "2": 10, "1": 10} elif rating >= 3.0: stars = {"5": 30, "4": 20, "3": 20, "2": 15, "1": 15} else: stars = {"5": 20, "4": 15, "3": 15, "2": 20, "1": 30} positive_pct = stars["5"] + stars["4"] negative_pct = stars["1"] + stars["2"] # Sentiment if rating >= 4.3: sentiment = "Very Positive" sentiment_color = "#34d399" elif rating >= 3.8: sentiment = "Positive" sentiment_color = "#86efac" elif rating >= 3.3: sentiment = "Mixed" sentiment_color = "#fbbf24" elif rating >= 2.8: sentiment = "Negative" sentiment_color = "#fb923c" else: sentiment = "Very Negative" sentiment_color = "#f87171" # Review velocity if review_count > 10000: velocity = "Saturated" elif review_count > 1000: velocity = "High" elif review_count > 200: velocity = "Medium" elif review_count > 50: velocity = "Growing" else: velocity = "Low" # Market opportunity from reviews if review_count < 100 and rating >= 4.0: opportunity = "High — low reviews, good rating. Easy entry." elif review_count < 500 and rating >= 3.8: opportunity = "Medium — manageable competition." elif review_count > 1000 and rating < 3.8: opportunity = "Medium — saturated but poor quality. Can disrupt." elif review_count > 1000 and rating >= 4.2: opportunity = "Low — strong competition, hard to enter." else: opportunity = "Medium — assess further." return { "rating": rating, "review_count": review_count, "sentiment": sentiment, "sentiment_color": sentiment_color, "positive_pct": positive_pct, "negative_pct": negative_pct, "star_distribution": stars, "review_velocity": velocity, "market_opportunity": opportunity, "common_positives": ["Good quality", "Fast delivery", "Value for money", "Easy to use", "As described"][:3], "common_negatives": ["Quality issues", "Poor packaging", "Not as described"][:2] if negative_pct > 15 else [], "entry_barrier": "Low" if review_count < 100 else "Medium" if review_count < 500 else "High", "entry_barrier_color": "#34d399" if review_count < 100 else "#fbbf24" if review_count < 500 else "#f87171", } # ══════════════════════════════════════════════════════════════════════════════ # 3. BUY BOX ANALYZER # ══════════════════════════════════════════════════════════════════════════════ def analyze_buy_box(price: float, rating: float, review_count: int, is_fba: bool = True, is_prime: bool = True) -> dict: score = 0 factors = [] # Price competitiveness if price < 20: score += 25 factors.append({"factor": "Price", "status": "Competitive", "color": "#34d399", "detail": f"${price:.2f} — low price helps win buy box"}) elif price < 50: score += 20 factors.append({"factor": "Price", "status": "Moderate", "color": "#fbbf24", "detail": f"${price:.2f} — average price range"}) else: score += 10 factors.append({"factor": "Price", "status": "High", "color": "#f87171", "detail": f"${price:.2f} — high price hurts buy box chances"}) # FBA if is_fba: score += 30 factors.append({"factor": "Fulfillment", "status": "FBA ✓", "color": "#34d399", "detail": "FBA strongly favored for buy box"}) else: score += 5 factors.append({"factor": "Fulfillment", "status": "FBM", "color": "#f87171", "detail": "FBM sellers rarely win buy box"}) # Prime if is_prime: score += 20 factors.append({"factor": "Prime", "status": "Eligible ✓", "color": "#34d399", "detail": "Prime eligibility required for buy box"}) else: score += 0 factors.append({"factor": "Prime", "status": "Not Eligible", "color": "#f87171", "detail": "No Prime = very low buy box chance"}) # Seller rating if rating >= 4.5: score += 15 factors.append({"factor": "Seller Rating", "status": "Excellent", "color": "#34d399", "detail": f"{rating}★ — Amazon favors high-rated sellers"}) elif rating >= 4.0: score += 10 factors.append({"factor": "Seller Rating", "status": "Good", "color": "#fbbf24", "detail": f"{rating}★ — acceptable for buy box"}) else: score += 3 factors.append({"factor": "Seller Rating", "status": "Needs Work", "color": "#f87171", "detail": f"{rating}★ — low rating hurts buy box"}) # Review count if review_count > 100: score += 10 factors.append({"factor": "Reviews", "status": "Established", "color": "#34d399", "detail": f"{review_count:,} reviews — trusted seller signal"}) else: score += 5 factors.append({"factor": "Reviews", "status": "New Seller", "color": "#fbbf24", "detail": f"{review_count} reviews — building trust"}) score = min(score, 100) if score >= 75: verdict = "Strong Buy Box Candidate" verdict_color = "#34d399" elif score >= 50: verdict = "Moderate Chance" verdict_color = "#fbbf24" elif score >= 25: verdict = "Low Chance" verdict_color = "#fb923c" else: verdict = "Unlikely to Win" verdict_color = "#f87171" return { "score": score, "verdict": verdict, "verdict_color": verdict_color, "factors": factors, "tips": [ "Use FBA for best buy box eligibility", "Price within 2% of lowest FBA offer", "Maintain 95%+ seller feedback rating", "Keep order defect rate below 1%", "Ship on time — late shipments hurt score", ][:3] } # ══════════════════════════════════════════════════════════════════════════════ # 4. NICHE FINDER # ══════════════════════════════════════════════════════════════════════════════ def analyze_niche(keyword: str, avg_bsr: float, avg_reviews: float, avg_price: float, product_count: int = 100) -> dict: # Demand score (lower BSR = higher demand) if avg_bsr < 5000: demand = 95 elif avg_bsr < 20000: demand = 80 elif avg_bsr < 50000: demand = 60 elif avg_bsr < 100000: demand = 40 else: demand = 20 # Competition score (lower reviews = less competition) if avg_reviews < 50: competition = 10 # low competition elif avg_reviews < 200: competition = 30 elif avg_reviews < 500: competition = 55 elif avg_reviews < 1000: competition = 75 else: competition = 90 # Price attractiveness if 20 <= avg_price <= 60: price_score = 90 price_note = "Sweet spot for FBA ($20-$60)" elif 10 <= avg_price < 20: price_score = 60 price_note = "Low margin risk under $20" elif 60 < avg_price <= 100: price_score = 75 price_note = "Good margin, lower volume" else: price_score = 40 price_note = "High price = niche market" # Opportunity score opportunity = round((demand * 0.4) + ((100 - competition) * 0.4) + (price_score * 0.2)) if opportunity >= 70: verdict = "🟢 Great Niche" verdict_color = "#34d399" elif opportunity >= 50: verdict = "🟡 Decent Niche" verdict_color = "#fbbf24" elif opportunity >= 35: verdict = "🟠 Challenging" verdict_color = "#fb923c" else: verdict = "🔴 Avoid" verdict_color = "#f87171" est_monthly_sales = estimate_sales_v2(int(avg_bsr), price=avg_price)["monthly_sales"] market_size = round(est_monthly_sales * avg_price * product_count / 1000, 0) return { "keyword": keyword, "opportunity_score": opportunity, "verdict": verdict, "verdict_color": verdict_color, "demand_score": demand, "competition_score": competition, "price_score": price_score, "price_note": price_note, "avg_bsr": int(avg_bsr), "avg_reviews": int(avg_reviews), "avg_price": avg_price, "est_monthly_sales": est_monthly_sales, "market_size_k": market_size, "recommendation": ( "Low competition — great entry opportunity!" if competition < 30 else "Medium competition — differentiate product." if competition < 60 else "High competition — need strong differentiation." ) } # ══════════════════════════════════════════════════════════════════════════════ # 5. KEYWORD RESEARCH # ══════════════════════════════════════════════════════════════════════════════ def generate_keywords(seed_keyword: str, category: str = "") -> dict: seed = seed_keyword.lower().strip() words = seed.split() # Generate variations modifiers_prefix = ["best", "top", "premium", "cheap", "professional", "heavy duty", "large", "small", "portable", "electric"] modifiers_suffix = ["for home", "for kitchen", "for office", "set", "kit", "bundle", "with lid", "non stick", "stainless steel", "organic"] keywords = [] # Main keyword keywords.append({ "keyword": seed, "search_volume": "High", "competition": "High", "opportunity": "Low", "type": "Head" }) # Long tail variations for mod in modifiers_prefix[:5]: kw = f"{mod} {seed}" keywords.append({ "keyword": kw, "search_volume": "Medium", "competition": "Medium", "opportunity": "Medium", "type": "Long-tail" }) for mod in modifiers_suffix[:5]: kw = f"{seed} {mod}" keywords.append({ "keyword": kw, "search_volume": "Low", "competition": "Low", "opportunity": "High", "type": "Long-tail" }) # Backend keywords (for listing) backend = [seed] + words + [f"{words[-1]} set", f"buy {seed}", f"{seed} amazon"] return { "seed_keyword": seed, "total_keywords": len(keywords), "keywords": keywords, "backend_keywords": backend, "top_opportunity": [k for k in keywords if k["opportunity"] == "High"][:3], "tip": f"Target '{seed} for home' or '{seed} set' — lower competition, high buyer intent." }