Skip to main content

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.

The Scenario

You’re launching a new product and need buy-in from an entire buying committee — CEO, CFO, CMO, VP Engineering, IT Director, Legal, Procurement, End User, Champion, and Detractor. Traditionally this means weeks of scheduling, travel budgets, and NDAs. With Mavera you create all ten personas, run one Focus Group, and have structured committee feedback in minutes.
Mavera-only workflow. No external API, no CRM integration, no calendar links. Just Mavera’s Personas and Focus Groups surfaces.

When to Use This

  • Pre-launch concept testing when you need cross-functional perspective.
  • Board presentations where you want simulated committee data behind your positioning.
  • Enterprise sales enablement — train reps on objections from every seat at the table.
  • Competitive repositioning when you need to pressure-test a pivot across roles.

Architecture

Mavera SurfaceRole in Pipeline
Personas (POST /personas)Create 10 distinct buying-committee members with role-specific priorities
Focus Groups (POST /focus-groups)Run all 10 personas through the same product concept questions

What You Need

RequirementDetails
Mavera API keyStarts with mvra_live_. Get one at Developer Settings.
Python 3.8+ or Node.js 18+requests for Python; native fetch for Node.
Credits~150–300 total. See Credits Estimate.
MAVERA_API_KEY=mvra_live_your_key_here

Step 1 — Define and Create the Buying Committee

Each persona gets a distinct role, seniority, and decision-making priority.
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"}

COMMITTEE = [
    {"name": "Sarah Chen — CEO", "role": "Chief Executive Officer",
     "description": "Strategic decision-maker focused on market positioning and ROI narratives for the board.",
     "traits": ["big-picture thinker", "risk-aware", "time-constrained"]},
    {"name": "Marcus Williams — CFO", "role": "Chief Financial Officer",
     "description": "Owns budget approval. Focused on TCO, payback period, and financial risk. Needs hard numbers.",
     "traits": ["analytical", "cost-conscious", "ROI-driven"]},
    {"name": "Priya Patel — CMO", "role": "Chief Marketing Officer",
     "description": "Evaluates products on differentiation potential, speed to market, and brand alignment.",
     "traits": ["creative", "data-informed", "brand-protective"]},
    {"name": "David Kim — VP Engineering", "role": "VP of Engineering",
     "description": "Technical evaluator concerned with API quality, security posture, and integration complexity.",
     "traits": ["detail-oriented", "security-conscious", "integration-focused"]},
    {"name": "Rachel Torres — IT Director", "role": "IT Director",
     "description": "Manages infrastructure and compliance. Evaluates SSO, data residency, and SLA guarantees.",
     "traits": ["process-driven", "compliance-focused", "vendor-skeptical"]},
    {"name": "James O'Brien — General Counsel", "role": "General Counsel",
     "description": "Reviews contracts, data processing agreements, and liability exposure.",
     "traits": ["cautious", "regulation-aware", "contract-focused"]},
    {"name": "Linda Zhao — Procurement Lead", "role": "Head of Procurement",
     "description": "Negotiates pricing, evaluates vendor stability, compares against existing contracts.",
     "traits": ["negotiation-oriented", "benchmark-driven", "process-rigid"]},
    {"name": "Alex Rivera — End User", "role": "Marketing Manager",
     "description": "Day-to-day user. Evaluates UX, learning curve, and daily workflow impact.",
     "traits": ["practical", "time-pressed", "UX-sensitive"]},
    {"name": "Nina Sorensen — Internal Champion", "role": "Product Marketing Lead",
     "description": "Ran a pilot and advocates internally. Biased positive but needs ammunition for skeptics.",
     "traits": ["enthusiastic", "evidence-seeking", "politically aware"]},
    {"name": "Tom Bradley — Internal Detractor", "role": "Senior Director of Operations",
     "description": "Prefers the incumbent. Worried about switching costs and team retraining.",
     "traits": ["resistant to change", "process-protective", "risk-averse"]},
]

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

print("Creating buying committee personas...")
persona_ids = [create_persona(m) for m in COMMITTEE]
print(f"\n{len(persona_ids)} personas ready.")
Persona creation is idempotent by name. If you’ve already created these personas, fetch them with GET /personas and reuse the IDs.

Step 2 — Run the Focus Group

Create a Focus Group with all 10 persona IDs. Questions cover concept reaction, purchase likelihood, objections, ownership, approval criteria, and pricing perception.
PRODUCT_CONCEPT = """
We're launching an AI-powered audience research platform that replaces traditional
focus groups with synthetic personas. Marketers can test messaging, positioning,
and creative in minutes instead of weeks. Pricing starts at $500/month.
"""

def run_panel_focus_group(pids):
    payload = {
        "name": "Buying Committee — Product Concept Review",
        "persona_ids": pids, "sample_size": len(pids),
        "questions": [
            {"question": f"Share your initial reaction from your role's perspective:\n\n{PRODUCT_CONCEPT}",
             "type": "OPEN_ENDED", "order": 1},
            {"question": "How likely is your organization to purchase this? (0-10)", "type": "NPS", "order": 2},
            {"question": "What is the single biggest objection you'd raise in a buying meeting?",
             "type": "OPEN_ENDED", "order": 3},
            {"question": "Which department should own this tool?", "type": "MULTIPLE_CHOICE",
             "options": ["Marketing", "Product", "Research/Insights", "Engineering", "Shared/Cross-functional"], "order": 4},
            {"question": "What would need to be true for you to approve this purchase?", "type": "OPEN_ENDED", "order": 5},
            {"question": "Rate the pricing ($500/mo) relative to value.", "type": "MULTIPLE_CHOICE",
             "options": ["Strong value", "Fair price", "Slightly expensive — need ROI first", "Too expensive"], "order": 6},
        ],
    }
    resp = requests.post(f"{BASE}/focus-groups", headers=HEADERS, json=payload)
    resp.raise_for_status()
    return resp.json()

def poll_focus_group(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 = run_panel_focus_group(persona_ids)
print(f"Focus Group created: {fg['id']}")
results = poll_focus_group(fg["id"])

Step 3 — Parse and Display the Committee Report

def print_committee_report(fg_results):
    print("\n" + "=" * 70)
    print("BUYING COMMITTEE FEEDBACK REPORT")
    print("=" * 70)

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

        if qr["type"] == "NPS":
            print(f"  NPS Score: {qr.get('nps_score')}")
            for r in qr.get("responses", []):
                print(f"    {r.get('persona_name', ''):40s}{r.get('value', 'N/A')}")
        elif qr["type"] == "MULTIPLE_CHOICE":
            for opt, cnt in sorted(qr.get("option_counts", {}).items(), key=lambda x: -x[1]):
                print(f"    {opt:40s} {'█' * cnt} ({cnt})")
        elif qr["type"] == "OPEN_ENDED":
            print(f"  Summary: {qr.get('summary', 'N/A')}")
            for r in qr.get("responses", [])[:3]:
                print(f"    [{r.get('persona_name', '')}] {r.get('value', '')[:120]}")

print_committee_report(results)
with open("committee_feedback.json", "w") as f:
    json.dump(results, f, indent=2)

Example Output

NPS by Role:
  Sarah Chen — CEO                          → 8
  Marcus Williams — CFO                     → 5
  Priya Patel — CMO                         → 9
  David Kim — VP Engineering                → 7
  Rachel Torres — IT Director               → 6
  James O'Brien — General Counsel           → 4
  Linda Zhao — Procurement Lead             → 5
  Alex Rivera — End User                    → 8
  Nina Sorensen — Internal Champion         → 10
  Tom Bradley — Internal Detractor          → 3

Department Ownership:
  Marketing                                    ████ (4)
  Research/Insights                             ███ (3)
  Shared/Cross-functional                       ██ (2)
  Product                                       █ (1)

Pricing Perception:
  Fair price                                   ███ (3)
  Slightly expensive — need ROI first          ████ (4)
  Strong value                                  █ (1)
  Too expensive                                 ██ (2)

Variations

for m in COMMITTEE:
    m["description"] += " Works in B2B SaaS, 500 employees, $50M ARR."
groups = {"Executive": persona_ids[:3], "Technical": persona_ids[3:5],
          "Gatekeepers": persona_ids[5:7], "Users": persona_ids[7:]}
for label, ids in groups.items():
    fg = run_panel_focus_group(ids)
    print_committee_report(poll_focus_group(fg["id"]))
Run the same committee through two concepts and compare NPS:
for i, concept in enumerate([CONCEPT_A, CONCEPT_B]):
    PRODUCT_CONCEPT = concept
    fg = run_panel_focus_group(persona_ids)
    result = poll_focus_group(fg["id"])
    print(f"\n=== Concept {i + 1} ===")
    print_committee_report(result)
followup = [
    {"question": "If we offered a 90-day pilot with guaranteed ROI metrics, would that address your concerns?",
     "type": "MULTIPLE_CHOICE", "options": ["Yes", "Partially", "No"], "order": 1},
    {"question": "What metric would justify the investment?", "type": "OPEN_ENDED", "order": 2},
]
import csv
with open("committee.csv", "w", newline="") as f:
    w = csv.writer(f)
    w.writerow(["Persona", "Question", "Response"])
    for qr in results.get("results", []):
        for r in qr.get("responses", []):
            w.writerow([r.get("persona_name"), qr["question"][:80], r.get("value", "")])

Credits Estimate

OperationTypical CostNotes
Persona creation (×10)0–50One-time; reuse across runs
Focus Group (10 personas, 6 questions)150–250Primary cost driver
Total~150–300
Personas persist across sessions. Create them once and reuse the IDs — you only pay the creation cost once.

What’s Next

Generational Content Testing

Test the same concept across Gen Z, Millennial, Gen X, and Boomer personas

Message Testing Matrix

5 messages × 5 personas for optimal message-persona fit

Persona Debate

Pit opposing buyer types against each other for pricing insights

Persona Selection Guide

Choose the right persona types for your research goal

Focus Groups Reference

All question types, sample sizes, and configuration options

Credits & Budget

Pre-flight checks and usage tracking