Hawbeez_Studio / backend /app /analysis.py
sushilideaclan01's picture
Import Hawbeez Creative Studio app
5d54b3c
"""
Deep marketing analysis of product data for ad creative generation.
"""
import json
from app.llm import call_llm, call_llm_vision, extract_json
def analyze_product(product_data: dict, target_audience: list[str] | None = None) -> dict:
"""
Deep marketing analysis of the product.
Returns structured dict for generating highly targeted ad creative.
When target_audience is provided, analysis is tailored to those segments.
"""
price = product_data.get("price", "")
audience_block = ""
if target_audience and len(target_audience) > 0:
audience_list = ", ".join(target_audience)
audience_block = f"""
━━━━━━━━━━━━━━━━━━
TARGET AUDIENCES (PRIORITY — MUST DRIVE THIS ANALYSIS)
━━━━━━━━━━━━━━━━━━
The user has selected these specific audience segments. Your ENTIRE analysis MUST be tailored to these audiences.
- positioning: Reframe for these segments (who they are, what they want, how this product fits).
- ideal_customer: Age of child, lifestyle, platform, and pain_points must align with the selected segments—not generic "parents" or "25-35".
- emotional_triggers: Choose triggers that resonate with these specific segments.
- ad_angles: Each angle must speak directly to one or more of these audiences; hooks and "why it works" must reference them.
- tagline_options: Lines that appeal to these segments.
- price_analysis: Frame value and perception for these buyers (e.g. gifting, combos, first-time parents, festive).
- shooting_angles, color_worlds, copy_direction: Align with how these audiences discover and consume content.
Selected segments (use these, do not substitute generic demographics):
{audience_list}
Do NOT produce a generic analysis. Every section must reflect the selected segments.
"""
prompt = f"""
You are an elite Indian DTC kids' and educational toys performance strategist.
You have scaled multiple 7–8 figure toy and baby product brands
using Meta static ads.
You think ONLY in:
- Scroll stopping power
- Emotional tension
- Identity signaling (parent identity, gifting, learning outcomes)
- Conversion psychology
- Visual hierarchy
Your job:
Perform a DEEP conversion-focused analysis of THIS specific product
that will directly power high-performing STATIC ad creatives for Hawbeez (eco-friendly wooden / Montessori toys).
{audience_block}
━━━━━━━━━━━━━━━━━━
CRITICAL PERFORMANCE RULES
━━━━━━━━━━━━━━━━━━
1. No generic marketing language.
2. No empty phrases like "high quality" or "perfect for any child".
3. Every insight must directly influence:
- Visual direction
- Hook creation
- Or targeting decision.
4. Assume this is being sold via Meta ads to parents and gift buyers in India (unless target audiences specify otherwise).
5. If product data lacks detail, infer logically based on category norms (toys, Montessori, wooden, educational).
6. Think in micro-audiences, not broad demographics (e.g. parents of 2–3 yr, Montessori seekers, eco-conscious, gifting).
7. This analysis must help generate scroll-stopping static creatives.
Return ONLY valid JSON.
No markdown.
No commentary.
No explanations outside JSON.
━━━━━━━━━━━━━━━━━━
PRODUCT DATA
━━━━━━━━━━━━━━━━━━
{json.dumps(product_data, indent=2)}
━━━━━━━━━━━━━━━━━━
OUTPUT REQUIREMENTS
━━━━━━━━━━━━━━━━━━
- Exactly 6 emotional triggers
- Exactly 5 ad angles
- Exactly 4 shooting_angles
- Exactly 3 color_worlds
- Exactly 4 unique_selling_points
- 3 tagline_options
Price rules:
Final price = {product_data.get('price', '')}
Anchor price must not exceed 2.5x final price.
Value framing must feel psychologically believable.
━━━━━━━━━━━━━━━━━━
RETURN THIS EXACT JSON STRUCTURE
━━━━━━━━━━━━━━━━━━
{{
"product_visual_notes": "When product images were provided: 2-3 short paragraphs. (1) How it looks in use: describe how the toy is used in play or learning, styling context, scale next to child/hand, key design elements. (2) Shape, size & proportions: describe shape (e.g. puzzle, wheel, blocks, organizer), scale and proportions, number of pieces if visible, key design details (materials, colors, finish). (3) Material, finish & color: wood type, finish (natural/painted), colors as seen, safety/eco cues. Omit or empty string if no images.",
"positioning": "Clear one-line positioning statement (who + outcome + differentiation)",
"tagline_options": ["Option 1", "Option 2", "Option 3"],
"ideal_customer": {{
"age_range": "age of child (e.g. 2-4 yrs) or parent segment",
"lifestyle": "specific, not generic",
"platform": "primary buying platform",
"pain_points": ["Pain 1", "Pain 2", "Pain 3"]
}},
"emotional_triggers": ["Trigger 1", "Trigger 2", "Trigger 3", "Trigger 4", "Trigger 5", "Trigger 6"],
"price_analysis": {{
"price_point": "{product_data.get('price', '')}",
"perception": "how this price feels emotionally",
"anchor_price": "realistic strikethrough",
"value_framing": "believable comparison framing"
}},
"ad_angles": [
{{ "angle_name": "", "hook": "", "why_it_works": "" }},
{{ "angle_name": "", "hook": "", "why_it_works": "" }},
{{ "angle_name": "", "hook": "", "why_it_works": "" }},
{{ "angle_name": "", "hook": "", "why_it_works": "" }},
{{ "angle_name": "", "hook": "", "why_it_works": "" }}
],
"shooting_angles": ["Angle 1", "Angle 2", "Angle 3", "Angle 4"],
"color_worlds": ["Direction 1", "Direction 2", "Direction 3"],
"copy_direction": {{
"headline_style": "e.g. bold serif uppercase + friendly script",
"tone": "clear tonal direction"
}},
"unique_selling_points": ["USP 1", "USP 2", "USP 3", "USP 4"]
}}
Return ONLY valid JSON. No markdown. No commentary.
"""
# First 3 product image URLs for vision (comma-split, strip, filter valid)
image_urls = [
u.strip()
for u in (product_data.get("product_images") or "").split(",")
if (u and u.strip().startswith("http"))
][:3]
if image_urls:
vision_note = "\n\nYou are also provided with product images in this message. Describe the product in detail: (1) how it looks in use—play or learning context, scale next to child/hand, key design elements; (2) shape, size, and proportions—type of toy (puzzle, blocks, organizer, etc.), scale, number of pieces, colors; (3) material, finish, and color as seen (wood, paint, eco/safety cues). Put this in product_visual_notes as 2-3 short paragraphs. Use these observations to inform your visual direction, shooting_angles, color_worlds, and overall creative recommendations."
content: list[dict] = [{"type": "text", "text": prompt + vision_note}]
for url in image_urls:
content.append({"type": "image_url", "image_url": {"url": url}})
raw = call_llm_vision(
messages=[{"role": "user", "content": content}],
model="gpt-4o-mini",
temperature=0.7,
)
else:
raw = call_llm(prompt, temperature=0.7)
return extract_json(raw)