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 preparing a campaign that needs to land across age groups. A single message rarely resonates the same way with a 22-year-old and a 62-year-old. Instead of guessing, you run the same Focus Group questions through Mavera’s generational personas and compare responses side by side. The output is a generation-specific content playbook built from structured audience data.
Mavera-only workflow. No survey tools, no panel recruitment, no incentive budgets. Just Mavera’s Personas and Focus Groups surfaces.

When to Use This

  • Campaign planning where the audience spans multiple age demographics.
  • Content strategy reviews — which generation does your messaging over-index for?
  • Product launches targeting “everyone” — find which generation is the best beachhead.
  • Social media strategy — match message to the generational skew of each platform.

Architecture

Mavera SurfaceRole in Pipeline
Personas (POST /personas)Create 4 generational archetypes
Focus Groups (POST /focus-groups)Run identical questions with each generation
Chat (OpenAI-compatible)Synthesize comparison into per-generation recommendations

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~85–190 total. See Credits Estimate.
MAVERA_API_KEY=mvra_live_your_key_here

Step 1 — Create Generational Personas

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

GENERATIONS = [
    {"name": "Jordan — Gen Z Consumer", "role": "Gen Z (born 1997–2012)",
     "description": "Digital native, 24 years old, lives on TikTok and Instagram. Values authenticity and social proof. Skeptical of corporate messaging, responds to creator-style content. Short attention span for traditional ads.",
     "traits": ["digitally native", "authenticity-driven", "socially conscious", "short-form preference"], "gen": "gen_z"},
    {"name": "Morgan — Millennial Professional", "role": "Millennial (born 1981–1996)",
     "description": "35, mid-career professional. Responds to experiences over things, purpose-driven brands, and data-backed claims. Active on Instagram, LinkedIn, and podcasts. Willing to pay premium for convenience.",
     "traits": ["experience-oriented", "purpose-driven", "research-heavy", "subscription-comfortable"], "gen": "millennial"},
    {"name": "Casey — Gen X Decision-Maker", "role": "Gen X (born 1965–1980)",
     "description": "48, peak earning years. Pragmatic and self-reliant. Responds to straightforward value propositions without hype. Brand-loyal when value is consistent. Email and web-first.",
     "traits": ["pragmatic", "self-reliant", "brand-loyal", "hype-resistant"], "gen": "gen_x"},
    {"name": "Pat — Boomer Evaluator", "role": "Baby Boomer (born 1946–1964)",
     "description": "65, retired or senior advisory role. Values trust, credentials, and track record over novelty. Prefers longer-form content — articles, whitepapers, webinars. Active on Facebook and email.",
     "traits": ["trust-driven", "detail-oriented", "authority-responsive", "long-form preference"], "gen": "boomer"},
]

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

gen_personas = {}
for g in GENERATIONS:
    gen_personas[g["gen"]] = {"id": create_persona(g), "name": g["name"]}

Step 2 — Define Campaign and Run Focus Groups

One campaign concept, identical questions, one Focus Group per generation.
CAMPAIGN = """
Campaign: "Own Your Future"
Product: Personal finance app for investing, budgeting, and retirement planning.
Tagline: "Smart money moves start here."
Visual: Split-screen — stressed about finances vs. confident and relaxed.
CTA: "Start your free plan today."
Channels: Instagram Reels, YouTube pre-roll, email nurture, LinkedIn ads.
"""

QUESTIONS = [
    {"question": f"Share your honest first impression:\n\n{CAMPAIGN}", "type": "OPEN_ENDED", "order": 1},
    {"question": "How compelling is the tagline 'Smart money moves start here'? (0-10)", "type": "NPS", "order": 2},
    {"question": "Which channel would most effectively reach you?", "type": "MULTIPLE_CHOICE",
     "options": ["Instagram Reels", "YouTube pre-roll", "Email nurture", "LinkedIn ads", "None"], "order": 3},
    {"question": "What emotion does the split-screen visual evoke?", "type": "OPEN_ENDED", "order": 4},
    {"question": "Would you click 'Start your free plan today'?", "type": "MULTIPLE_CHOICE",
     "options": ["Yes — immediately", "Maybe — need more info", "No — not relevant", "No — CTA too generic"], "order": 5},
    {"question": "What one change would make this more appealing to you?", "type": "OPEN_ENDED", "order": 6},
]

def run_gen_fg(gen_key, persona_id):
    resp = requests.post(f"{BASE}/focus-groups", headers=HEADERS, json={
        "name": f"Generational Test — {gen_key}", "persona_ids": [persona_id],
        "sample_size": 10, "questions": QUESTIONS,
    })
    resp.raise_for_status()
    return resp.json()

def poll_fg(fg_id, timeout_min=10):
    for _ 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")

# Create all FGs before polling — they run concurrently
fg_jobs = {}
for gen_key, info in gen_personas.items():
    fg = run_gen_fg(gen_key, info["id"])
    fg_jobs[gen_key] = fg["id"]

gen_results = {gk: poll_fg(fid) for gk, fid in fg_jobs.items()}
print("All 4 Focus Groups complete.")
All four Focus Groups are created before polling. Mavera processes them concurrently, so total wait time is roughly the same as a single group.

Step 3 — Compare Results Across Generations

def compare_generations(results_by_gen):
    print("\n" + "=" * 70)
    print("GENERATIONAL COMPARISON REPORT")
    print("=" * 70)

    labels = {"gen_z": "Gen Z", "millennial": "Millennial", "gen_x": "Gen X", "boomer": "Boomer"}
    order = ["gen_z", "millennial", "gen_x", "boomer"]

    for q_idx, q in enumerate(QUESTIONS):
        print(f"\n{'─' * 60}\nQ{q_idx+1}: {q['question'].split(chr(10))[0][:70]}\n{'─' * 60}")
        for gk in order:
            qr = results_by_gen[gk]["results"][q_idx]
            lbl = labels[gk]
            if q["type"] == "NPS":
                print(f"  {lbl:12s} NPS: {qr.get('nps_score', 'N/A')}")
            elif q["type"] == "MULTIPLE_CHOICE":
                counts = qr.get("option_counts", {})
                top = max(counts, key=counts.get) if counts else "N/A"
                print(f"  {lbl:12s} Top: {top}")
            else:
                print(f"  {lbl:12s} {(qr.get('summary', 'N/A'))[:90]}")

compare_generations(gen_results)

Step 4 — Generate Recommendations via Chat

from openai import OpenAI

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

def generate_recs(results_by_gen):
    labels = {"gen_z": "Gen Z", "millennial": "Millennial", "gen_x": "Gen X", "boomer": "Boomer"}
    parts = []
    for gk in ["gen_z", "millennial", "gen_x", "boomer"]:
        p = f"## {labels[gk]}\n"
        for qr in results_by_gen[gk].get("results", []):
            q_short = qr["question"][:50]
            if qr["type"] == "NPS": p += f"- {q_short}: NPS {qr.get('nps_score')}\n"
            elif qr["type"] == "MULTIPLE_CHOICE": p += f"- {q_short}: {qr.get('option_counts', {})}\n"
            else: p += f"- {q_short}: {qr.get('summary', 'N/A')}\n"
        parts.append(p)

    resp = mavera.responses.create(model="mavera-1", input=[{"role": "user", "content":
        "Analyze these Focus Group results from 4 generational segments.\n\n" + "\n".join(parts) +
        "\n\nProduce: 1) Generation resonance ranking 2) Per-generation content recs "
        "3) A universal version 4) Channel allocation by generation"}])
    return resp.output[0].content[0].text

recs = generate_recs(gen_results)
print("\n=== RECOMMENDATIONS ===\n")
print(recs)

Example Output

NPS by Generation:
  Gen Z        NPS: 45
  Millennial   NPS: 62
  Gen X        NPS: 38
  Boomer       NPS: 25

Preferred Channel:
  Gen Z        Top: Instagram Reels
  Millennial   Top: YouTube pre-roll
  Gen X        Top: Email nurture
  Boomer       Top: Email nurture

CTA Click Intent:
  Gen Z        Top: Maybe — need more info
  Millennial   Top: Yes — immediately
  Gen X        Top: Maybe — need more info
  Boomer       Top: No — CTA too generic

Variations

Create two personas per generation — one urban, one suburban — for 8 Focus Groups:
for g in GENERATIONS:
    for locale in ["urban", "suburban"]:
        variant = {**g, "name": f"{g['name']} ({locale})",
                   "description": g["description"] + f" Lives in a {locale} area."}
        create_persona(variant)
weights = {"gen_z": 0.20, "millennial": 0.40, "gen_x": 0.30, "boomer": 0.10}
weighted_nps = sum(
    gen_results[gk]["results"][1].get("nps_score", 0) * w for gk, w in weights.items()
)
print(f"Weighted NPS: {weighted_nps:.1f}")
for concept_idx, concept in enumerate([CAMPAIGN_A, CAMPAIGN_B]):
    QUESTIONS[0]["question"] = f"React to this:\n\n{concept}"
    for gk, info in gen_personas.items():
        fg = run_gen_fg(gk, info["id"])
for gk in ["gen_z", "millennial", "gen_x", "boomer"]:
    feedback = gen_results[gk]["results"][5].get("summary", "")
    gen_resp = requests.post(f"{BASE}/generations", headers=HEADERS, json={
        "app": "ad_copy", "inputs": {"audience_feedback": feedback, "generation": gk}
    })
    print(f"{gk}: {gen_resp.json().get('content', '')[:200]}")
resp = requests.get(f"{BASE}/personas", headers=HEADERS).json()
gen_z_id = next(p["id"] for p in resp if "Gen Z" in p.get("name", ""))

Credits Estimate

OperationTypical CostNotes
Persona creation (×4)0–20One-time; reuse across runs
Focus Group (×4, 10 respondents, 6 questions)80–160~20–40 per group
Chat recommendations3–8Single synthesis call
Total~85–190

What’s Next

Industry Panel Simulation

Test with 10 buying-committee personas instead of generational segments

Message Testing Matrix

Combine multiple messages with multiple personas for a full fit matrix

Persona Debate

Pit opposing buyer types against each other for pricing insights

Content Localization

Adapt content across cultural regions, not just generations

Persona Selection Guide

Choose the right persona types for your research goal

Credits & Budget

Pre-flight checks and usage tracking