> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mavera.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Persona Debate

> Create opposing personas — Budget-Conscious Buyer vs Premium Buyer — and run a Focus Group where both evaluate the same product at different price points

## The Scenario

Pricing is one of the hardest go-to-market decisions. Ask a budget buyer and they'll say it's too expensive. Ask a premium buyer and they'll say it's reasonable. The truth lives in the tension between them. This playbook creates two opposing personas and runs them through the same Focus Group evaluating your product at multiple price points. The output is a structured price-sensitivity analysis from opposing perspectives.

<Info>
  **Mavera-only workflow.** No conjoint analysis software, no survey panels, no incentive budgets. Just Mavera's Personas, Focus Groups, and Chat surfaces.
</Info>

***

## When to Use This

* Pre-launch pricing decisions — find the range that maximizes both WTP and adoption.
* Tier structure design — which features justify premium vs standard pricing?
* Price increase planning — simulate reactions from loyal customers and price-sensitive prospects.
* Competitive pricing — test your price against a competitor's with opposing buyer mindsets.
* Freemium vs paid debates — let opposing personas argue for and against free tiers.

***

## Architecture

```mermaid theme={"dark"}
flowchart LR
    A["Create Opposing Personas"] --> B["Run Debate Focus Group"]
    B --> C["Parse by Type"]
    C --> D["Pricing Recommendation"]
```

| Mavera Surface                          | Role in Pipeline                                     |
| --------------------------------------- | ---------------------------------------------------- |
| **Personas** (`POST /personas`)         | Create opposing buyer archetypes                     |
| **Focus Groups** (`POST /focus-groups`) | Both personas evaluate the product at 4 price points |
| **Chat** (OpenAI-compatible)            | Synthesize opposing viewpoints into a recommendation |

***

## What You Need

| Requirement                        | Details                                                                                              |
| ---------------------------------- | ---------------------------------------------------------------------------------------------------- |
| **Mavera API key**                 | Starts with `mvra_live_`. Get one at [Developer Settings](https://app.mavera.io/settings/developer). |
| **Python 3.8+** or **Node.js 18+** | `requests` for Python; native `fetch` for Node.                                                      |
| **Credits**                        | \~85–205 total. See [Credits Estimate](#credits-estimate).                                           |

```
MAVERA_API_KEY=mvra_live_your_key_here
```

***

## Step 1 — Create Opposing Personas

The key is making these genuinely opposed — not just different price preferences, but different value frameworks.

<CodeGroup>
  ```python Python theme={"dark"}
  import os, time, json, requests

  API_KEY = os.environ["MAVERA_API_KEY"]
  BASE = "https://app.mavera.io/api/v1"
  HEADERS = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}

  OPPOSING = [
      {"name": "Dana — Budget-Conscious Buyer",
       "role": "Operations Manager at a bootstrapped 30-person startup",
       "description": (
           "Every purchase goes through a personal ROI calculator. Uses free tiers and open-source "
           "before paying. Negotiates every contract. Measures value in dollars saved per hour. "
           "Trusts usage-based pricing over flat fees. Will cancel the moment usage drops below cost."),
       "traits": ["price-sensitive", "ROI-calculator mentality", "free-tier-first",
                  "negotiation-driven", "churn-prone if value drops"]},
      {"name": "Victoria — Premium Buyer",
       "role": "VP of Marketing at a Series C company ($30M raised)",
       "description": (
           "Pays significantly more for reliability, support, and time savings. Believes 'you get what you pay for.' "
           "Values white-glove onboarding, dedicated support, and SLAs. Sees price as a quality signal — "
           "if it's too cheap, something must be wrong. Happy to sign annual contracts."),
       "traits": ["quality-over-cost", "time-is-money mentality", "enterprise-expectation",
                  "annual-contract-comfortable", "brand-as-signal buyer"]},
  ]

  def create_persona(p):
      resp = requests.post(f"{BASE}/personas", headers=HEADERS, json={
          "name": p["name"], "role": p["role"], "description": p["description"], "traits": p["traits"]})
      resp.raise_for_status()
      data = resp.json()
      print(f"  Created: {data['name']} → {data['id']}")
      return data["id"]

  budget_id = create_persona(OPPOSING[0])
  premium_id = create_persona(OPPOSING[1])
  ```

  ```javascript JavaScript theme={"dark"}
  const API_KEY = process.env.MAVERA_API_KEY;
  const BASE = "https://app.mavera.io/api/v1";
  const HEADERS = { Authorization: `Bearer ${API_KEY}`, "Content-Type": "application/json" };

  const OPPOSING = [
    { name: "Dana — Budget-Conscious Buyer", role: "Ops Manager, bootstrapped 30-person startup",
      description: "ROI calculator for every purchase. Free tiers first. Negotiates everything. " +
        "Usage-based pricing preferred. Will cancel when value drops below cost.",
      traits: ["price-sensitive", "ROI-calculator mentality", "free-tier-first", "negotiation-driven"] },
    { name: "Victoria — Premium Buyer", role: "VP Marketing, Series C ($30M raised)",
      description: "Pays more for reliability and time savings. 'You get what you pay for.' " +
        "Wants white-glove onboarding and SLAs. Price = quality signal. Annual contracts fine.",
      traits: ["quality-over-cost", "time-is-money", "enterprise-expectation", "brand-as-signal buyer"] },
  ];

  async function createPersona(p) {
    const resp = await fetch(`${BASE}/personas`, { method: "POST", headers: HEADERS,
      body: JSON.stringify({ name: p.name, role: p.role, description: p.description, traits: p.traits }) });
    const data = await resp.json();
    if (data.error) throw new Error(data.error.message);
    return data.id;
  }

  const budgetId = await createPersona(OPPOSING[0]);
  const premiumId = await createPersona(OPPOSING[1]);
  ```
</CodeGroup>

***

## Step 2 — Define Product and Price Points

<CodeGroup>
  ```python Python theme={"dark"}
  PRODUCT = {
      "name": "Mavera Pro",
      "description": "AI-powered audience research. Focus Groups (unlimited), Video Analysis (50/mo), "
                     "Brand Voice, Chat API, Generate, Speak, dedicated Slack support. 5 seats.",
      "features": ["Unlimited Focus Groups", "50 Video Analyses/mo", "Brand Voice extraction",
                   "Chat API", "Generate (all apps)", "Speak conversations", "Dedicated support", "5 seats"],
  }

  PRICES = [
      {"label": "Starter", "price": "$199/month", "annual": "$1,990/year"},
      {"label": "Growth", "price": "$499/month", "annual": "$4,990/year"},
      {"label": "Scale", "price": "$999/month", "annual": "$9,990/year"},
      {"label": "Enterprise", "price": "$2,499/month", "annual": "$24,990/year"},
  ]
  ```

  ```javascript JavaScript theme={"dark"}
  const PRODUCT = {
    name: "Mavera Pro",
    description: "AI-powered audience research. Focus Groups, Video Analysis, Brand Voice, Chat API, Generate, Speak, support. 5 seats.",
    features: ["Unlimited Focus Groups", "50 Video Analyses/mo", "Brand Voice", "Chat API", "Generate", "Speak", "Support", "5 seats"],
  };

  const PRICES = [
    { label: "Starter", price: "$199/month", annual: "$1,990/year" },
    { label: "Growth", price: "$499/month", annual: "$4,990/year" },
    { label: "Scale", price: "$999/month", annual: "$9,990/year" },
    { label: "Enterprise", price: "$2,499/month", annual: "$24,990/year" },
  ];
  ```
</CodeGroup>

***

## Step 3 — Run the Debate Focus Group

Both personas participate in the same group. Questions surface the tension between their opposing value frameworks.

<CodeGroup>
  ```python Python theme={"dark"}
  def build_debate_questions():
      product_block = f"**{PRODUCT['name']}**\n{PRODUCT['description']}\n\n" + "\n".join(f"- {f}" for f in PRODUCT["features"])
      price_block = "\n".join(f"- **{p['label']}**: {p['price']} (annual: {p['annual']})" for p in PRICES)
      return [
          {"question": f"Share your impression of value:\n\n{product_block}", "type": "OPEN_ENDED", "order": 1},
          {"question": f"Which tier would you choose?\n\n{price_block}", "type": "MULTIPLE_CHOICE",
           "options": [f"{p['label']} ({p['price']})" for p in PRICES] + ["None — would not purchase"], "order": 2},
          {"question": "At which price is this 'too expensive' — you'd look for alternatives?", "type": "MULTIPLE_CHOICE",
           "options": [f"{p['label']} ({p['price']})" for p in PRICES] + ["All acceptable"], "order": 3},
          {"question": "At which price is this 'too cheap' — you'd question quality?", "type": "MULTIPLE_CHOICE",
           "options": [f"{p['label']} ({p['price']})" for p in PRICES] + ["None too cheap"], "order": 4},
          {"question": "What features justify the Enterprise tier?", "type": "OPEN_ENDED", "order": 5},
          {"question": "What could be removed to make Starter a fair deal?", "type": "OPEN_ENDED", "order": 6},
          {"question": "If a competitor offered 40% less, would you switch? What prevents it?", "type": "OPEN_ENDED", "order": 7},
          {"question": "Rate overall value at Growth ($499/mo). (0-10)", "type": "NPS", "order": 8},
      ]

  def poll_fg(fg_id, timeout_min=10):
      for i in range(timeout_min * 6):
          resp = requests.get(f"{BASE}/focus-groups/{fg_id}", headers=HEADERS).json()
          if "error" in resp: raise Exception(resp["error"]["message"])
          if resp["status"] == "COMPLETED": return resp
          time.sleep(10)
      raise TimeoutError(f"Focus Group {fg_id} timed out")

  fg = requests.post(f"{BASE}/focus-groups", headers=HEADERS, json={
      "name": "Persona Debate — Price Positioning",
      "persona_ids": [budget_id, premium_id], "sample_size": 10,
      "questions": build_debate_questions(),
  }).json()
  print(f"Debate Focus Group: {fg['id']}")
  results = poll_fg(fg["id"])
  ```

  ```javascript JavaScript theme={"dark"}
  function buildDebateQuestions() {
    const productBlock = `**${PRODUCT.name}**\n${PRODUCT.description}\n\n` + PRODUCT.features.map((f) => `- ${f}`).join("\n");
    const priceBlock = PRICES.map((p) => `- **${p.label}**: ${p.price} (annual: ${p.annual})`).join("\n");
    return [
      { question: `Share your impression:\n\n${productBlock}`, type: "OPEN_ENDED", order: 1 },
      { question: `Which tier?\n\n${priceBlock}`, type: "MULTIPLE_CHOICE",
        options: [...PRICES.map((p) => `${p.label} (${p.price})`), "None — would not purchase"], order: 2 },
      { question: "At which price is this 'too expensive'?", type: "MULTIPLE_CHOICE",
        options: [...PRICES.map((p) => `${p.label} (${p.price})`), "All acceptable"], order: 3 },
      { question: "At which price is this 'too cheap'?", type: "MULTIPLE_CHOICE",
        options: [...PRICES.map((p) => `${p.label} (${p.price})`), "None too cheap"], order: 4 },
      { question: "What features justify Enterprise tier?", type: "OPEN_ENDED", order: 5 },
      { question: "What could be removed for Starter?", type: "OPEN_ENDED", order: 6 },
      { question: "Competitor at 40% less — switch?", type: "OPEN_ENDED", order: 7 },
      { question: "Rate value at Growth ($499/mo). (0-10)", type: "NPS", order: 8 },
    ];
  }

  async function pollFG(fgId, timeoutMin = 10) {
    for (let i = 0; i < timeoutMin * 6; i++) {
      const resp = await fetch(`${BASE}/focus-groups/${fgId}`, { headers: HEADERS }).then((r) => r.json());
      if (resp.error) throw new Error(resp.error.message);
      if (resp.status === "COMPLETED") return resp;
      await new Promise((r) => setTimeout(r, 10000));
    }
    throw new Error("Timed out");
  }

  const fg = await fetch(`${BASE}/focus-groups`, { method: "POST", headers: HEADERS,
    body: JSON.stringify({ name: "Persona Debate", persona_ids: [budgetId, premiumId],
      sample_size: 10, questions: buildDebateQuestions() }) }).then((r) => r.json());
  const results = await pollFG(fg.id);
  ```
</CodeGroup>

***

## Step 4 — Parse the Debate

Separate responses by persona type and display side by side.

<CodeGroup>
  ```python Python theme={"dark"}
  def print_debate_report(fg_results):
      print("\n" + "=" * 70)
      print("PERSONA DEBATE — PRICING ANALYSIS")
      print("=" * 70)

      for qr in fg_results.get("results", []):
          print(f"\n{'─' * 60}\nQ: {qr['question'][:75]}\n{'─' * 60}")

          if qr["type"] == "MULTIPLE_CHOICE":
              for opt, cnt in sorted(qr.get("option_counts", {}).items(), key=lambda x: -x[1]):
                  print(f"    {opt:45s} {'█' * cnt} ({cnt})")
              budget = [r for r in qr.get("responses", []) if "Budget" in r.get("persona_name", "")]
              premium = [r for r in qr.get("responses", []) if "Premium" in r.get("persona_name", "")]
              if budget:
                  choices = [r.get("value", "") for r in budget]
                  print(f"\n  Budget tendency: {max(set(choices), key=choices.count)}")
              if premium:
                  choices = [r.get("value", "") for r in premium]
                  print(f"  Premium tendency: {max(set(choices), key=choices.count)}")

          elif qr["type"] == "NPS":
              print(f"  Overall NPS: {qr.get('nps_score', 'N/A')}")
              for label, keyword in [("Budget", "Budget"), ("Premium", "Premium")]:
                  scores = [int(r["value"]) for r in qr.get("responses", [])
                            if keyword in r.get("persona_name", "") and r.get("value") is not None]
                  if scores:
                      print(f"  {label} avg: {sum(scores)/len(scores):.1f}/10")

          elif qr["type"] == "OPEN_ENDED":
              print(f"  Summary: {qr.get('summary', 'N/A')}")
              for keyword, label in [("Budget", "Budget"), ("Premium", "Premium")]:
                  resps = [r for r in qr.get("responses", []) if keyword in r.get("persona_name", "")]
                  if resps:
                      print(f"\n  {label} perspective:")
                      print(f"    \"{resps[0].get('value', '')[:140]}\"")

  print_debate_report(results)
  ```

  ```javascript JavaScript theme={"dark"}
  function printDebateReport(fgResults) {
    console.log("\n" + "=".repeat(70));
    console.log("PERSONA DEBATE — PRICING ANALYSIS");
    console.log("=".repeat(70));
    for (const qr of fgResults.results || []) {
      console.log(`\n${"─".repeat(60)}\nQ: ${(qr.question || "").slice(0, 75)}\n${"─".repeat(60)}`);
      if (qr.type === "MULTIPLE_CHOICE") {
        for (const [opt, cnt] of Object.entries(qr.option_counts || {}).sort((a, b) => b[1] - a[1]))
          console.log(`    ${opt.padEnd(45)} ${"█".repeat(cnt)} (${cnt})`);
      } else if (qr.type === "NPS") {
        console.log(`  Overall NPS: ${qr.nps_score ?? "N/A"}`);
        for (const kw of ["Budget", "Premium"]) {
          const scores = (qr.responses || []).filter((r) => (r.persona_name || "").includes(kw) && r.value != null);
          if (scores.length) console.log(`  ${kw} avg: ${(scores.reduce((s, r) => s + Number(r.value), 0) / scores.length).toFixed(1)}/10`);
        }
      } else {
        console.log(`  Summary: ${qr.summary || "N/A"}`);
      }
    }
  }
  printDebateReport(results);
  ```
</CodeGroup>

***

## Step 5 — Generate Pricing Recommendation

<CodeGroup>
  ```python Python theme={"dark"}
  from openai import OpenAI

  mavera = OpenAI(api_key=API_KEY, base_url="https://app.mavera.io/api/v1")

  def generate_recommendation(fg_results):
      summary = [{"question": qr["question"][:60], "type": qr["type"],
                  "summary": qr.get("summary", ""),
                  **({"nps": qr.get("nps_score")} if qr["type"] == "NPS" else {}),
                  **({"counts": qr.get("option_counts")} if qr["type"] == "MULTIPLE_CHOICE" else {})}
                 for qr in fg_results.get("results", [])]

      prices = ", ".join(f"{p['label']}={p['price']}" for p in PRICES)
      resp = mavera.responses.create(model="mavera-1", input=[{"role": "user", "content":
          f"Two opposing buyer personas evaluated this product at these prices: {prices}\n\n"
          f"Results:\n{json.dumps(summary, indent=2)}\n\n"
          "Produce: 1) Van Westendorp interpretation 2) Recommended price point "
          "3) Tier strategy (keep 4 or collapse?) 4) Feature allocation per tier "
          "5) Competitive moat 6) Risk assessment"}])
      return resp.output[0].content[0].text

  rec = generate_recommendation(results)
  print("\n=== PRICING RECOMMENDATION ===\n")
  print(rec)
  with open("pricing_debate_report.md", "w") as f:
      f.write(f"# Persona Debate — Pricing Analysis\n\n{rec}")
  ```

  ```javascript JavaScript theme={"dark"}
  const OpenAI = require("openai").default;
  const mavera = new OpenAI({ apiKey: API_KEY, baseURL: "https://app.mavera.io/api/v1" });

  async function generateRecommendation(fgResults) {
    const summary = (fgResults.results || []).map((qr) => ({
      question: (qr.question || "").slice(0, 60), type: qr.type, summary: qr.summary || "",
      ...(qr.type === "NPS" && { nps: qr.nps_score }),
      ...(qr.type === "MULTIPLE_CHOICE" && { counts: qr.option_counts }),
    }));
    const prices = PRICES.map((p) => `${p.label}=${p.price}`).join(", ");
    const resp = await mavera.responses.create({ model: "mavera-1", input: [{ role: "user",
      content: `Two opposing buyers evaluated at: ${prices}\n\n${JSON.stringify(summary, null, 2)}\n\n` +
        "Produce: 1) Van Westendorp 2) Recommended price 3) Tier strategy 4) Feature allocation 5) Moat 6) Risks" }] });
    return resp.output[0].content[0].text;
  }
  const rec = await generateRecommendation(results);
  console.log(rec);
  const fs = require("fs");
  fs.writeFileSync("pricing_debate_report.md", `# Persona Debate\n\n${rec}`);
  ```
</CodeGroup>

***

## Example Output

```
Tier Selection:
  Starter ($199/month)                          ████ (4)
  Growth ($499/month)                           ███ (3)
  Scale ($999/month)                            ██ (2)
  None — would not purchase                     █ (1)

  Budget tendency: Starter ($199/month)
  Premium tendency: Scale ($999/month)

"Too Expensive" Threshold:
  Budget tendency: Scale ($999/month)
  Premium tendency: All acceptable

"Too Cheap" Threshold:
  Budget tendency: None too cheap
  Premium tendency: Starter ($199/month)

Value NPS at Growth ($499/mo):
  Overall NPS: 35
  Budget avg: 4.2/10
  Premium avg: 7.8/10
```

***

## Variations

<AccordionGroup>
  <Accordion title="Add a 'Pragmatic Middle' persona">
    ```python theme={"dark"}
    middle = {"name": "Sam — Pragmatic Evaluator", "role": "Director of Marketing, 150 people",
     "description": "Compares 3 vendors, picks best value/risk ratio. Reads G2 reviews. Wants a pilot.",
     "traits": ["comparison-shopper", "risk-balanced", "pilot-oriented"]}
    middle_id = create_persona(middle)
    # Add middle_id to persona_ids list
    ```
  </Accordion>

  <Accordion title="Test specific feature bundles per tier">
    ```python theme={"dark"}
    TIERS = {
        "Starter": {"features": ["Chat API", "5 Focus Groups/mo"], "price": "$199/mo"},
        "Growth": {"features": ["Chat", "Unlimited FGs", "Brand Voice"], "price": "$499/mo"},
        "Scale": {"features": ["Everything + Video + Speak"], "price": "$999/mo"},
    }
    ```
  </Accordion>

  <Accordion title="Iterate with refined price points">
    After the first debate narrows the range, test smaller increments:

    ```python theme={"dark"}
    REFINED = [{"label": f"Tier {c}", "price": f"${p}/mo"} for c, p in
               zip("ABCD", [349, 449, 549, 649])]
    ```
  </Accordion>

  <Accordion title="Use Mave for competitive benchmarking first">
    ```python theme={"dark"}
    mave = requests.post(f"{BASE}/mave/chat", headers=HEADERS, json={
        "message": "Research pricing of UserTesting, Wynter, Poll the People, Remesh. "
                   "Compare models, tiers, and what's included."}).json()
    print(mave.get("content", ""))
    ```
  </Accordion>

  <Accordion title="Industry-specific opposing personas">
    ```python theme={"dark"}
    healthcare_budget = {"name": "Community Clinic Director",
     "description": "Tiny budget, grant-funded, high compliance needs..."}
    healthcare_premium = {"name": "Hospital System CMO",
     "description": "$50M marketing budget, demands SLAs and HIPAA compliance..."}
    ```
  </Accordion>
</AccordionGroup>

***

## Credits Estimate

| Operation                                             | Typical Cost | Notes                       |
| ----------------------------------------------------- | ------------ | --------------------------- |
| Persona creation (×2)                                 | 0–10         | One-time; reuse across runs |
| Focus Group (2 personas, 10 respondents, 8 questions) | 80–180       | Primary cost driver         |
| Chat recommendation                                   | 5–15         | Single synthesis call       |
| **Total**                                             | **\~85–205** |                             |

<Tip>
  The debate format is highly efficient — opposing perspectives from a single Focus Group rather than two separate studies. Roughly half the cost of running each persona independently.
</Tip>

***

## What's Next

<CardGroup cols={2}>
  <Card title="Industry Panel Simulation" icon="users" href="/playbooks/industry-panel-simulation">
    Expand from 2 opposing personas to 10 buying-committee members
  </Card>

  <Card title="Message Testing Matrix" icon="table-cells" href="/playbooks/message-testing-matrix">
    Test which messaging angle works best at each price point
  </Card>

  <Card title="Pricing Research" icon="tags" href="/playbooks/pricing-research">
    Full Van Westendorp analysis with persona segments
  </Card>

  <Card title="Generational Content Testing" icon="people-group" href="/playbooks/generational-content-testing">
    How pricing perception varies across age demographics
  </Card>

  <Card title="Persona Selection Guide" icon="user" href="/cookbooks/persona-selection">
    Choose the right persona types for your research goal
  </Card>

  <Card title="Credits & Budget" icon="coins" href="/cookbooks/credits-budget-alerts">
    Pre-flight checks and usage tracking
  </Card>
</CardGroup>
