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.

Scenario

G2 reviewers often describe features they wish your product had. These requests are scattered across hundreds of reviews. You aggregate feature request mentions, create personas representing the requesters, then run a Focus Group where personas rank the features by importance. The output feeds directly into product roadmap prioritization. Flow: G2 reviews → Extract feature requests → Mavera POST /mave/chat (categorize) → POST /focus-groups (Ranking) → Prioritized feature list

Code

import os, requests, time, json

G2 = os.environ["G2_API_KEY"]
MV = os.environ["MAVERA_API_KEY"]
G2_H = {"Authorization": f"Token token={G2}", "Content-Type": "application/vnd.api+json"}
MV_H = {"Authorization": f"Bearer {MV}", "Content-Type": "application/json"}

# 1. Pull reviews
reviews = []
page = 1
while len(reviews) < 200:
    r = requests.get(f"https://data.g2.com/api/v1/survey-responses",
        headers=G2_H, params={"page[size]": 50, "page[number]": page})
    if r.status_code == 429: time.sleep(1); continue
    r.raise_for_status()
    data = r.json().get("data", [])
    if not data: break
    reviews.extend(data)
    page += 1
    time.sleep(0.1)

# 2. Extract "dislike" and "recommendation" text
feature_texts = []
for rev in reviews:
    attrs = rev.get("attributes", {})
    for key, val in attrs.get("comment_answers", {}).items():
        text = val if isinstance(val, str) else val.get("text", "")
        k = key.lower()
        if ("dislike" in k or "wish" in k or "improve" in k or "recommend" in k) and text.strip():
            feature_texts.append(text[:300])

# 3. Use Mave to categorize feature requests
from openai import OpenAI
mavera = OpenAI(api_key=MV, base_url="https://app.mavera.io/api/v1")

feature_block = "\n".join(f"{i+1}. {t}" for i, t in enumerate(feature_texts[:50]))

categorization = mavera.responses.create(model="mavera-1",
    input=[{"role": "user", "content": f"""Categorize these G2 review comments into feature request categories.

{feature_block}

Return JSON with: feature_name, description, mention_count, representative_quotes (2 each).
Group similar requests. Minimum 3 mentions to include."""}],
    extra_body={"response_format": {"type": "json_object"}})

features = json.loads(categorization.output[0].content[0].text)
feature_list = features.get("features", features.get("feature_requests", []))
print(f"Identified {len(feature_list)} feature request categories")

# 4. Create product user personas
PRODUCT_PERSONAS = [
    {"name": "Power User PM", "desc": "Uses product daily. Deeply invested in feature depth."},
    {"name": "Executive Sponsor", "desc": "Bought the product. Cares about ROI and team adoption."},
    {"name": "New User", "desc": "Onboarding. Wants simplicity and quick wins."},
]

persona_ids = []
for pp in PRODUCT_PERSONAS:
    p = requests.post(f"https://app.mavera.io/api/v1/personas", headers=MV_H, json={
        "name": f"G2: {pp['name']}", "description": pp["desc"],
    }).json()
    persona_ids.append(p["id"])
    time.sleep(0.2)

# 5. Focus Group: rank features
feature_options = "\n".join(
    f"({chr(65+i)}) {f.get('feature_name', f.get('name', 'Unknown'))}: {f.get('description','')[:80]}"
    for i, f in enumerate(feature_list[:8])
)

fg = requests.post(f"https://app.mavera.io/api/v1/focus-groups", headers=MV_H, json={
    "name": "G2 Feature Request Prioritization",
    "persona_ids": persona_ids,
    "questions": [
        {"type": "ranking", "text": f"Rank these features by impact on YOUR workflow:\n{feature_options}"},
        "Which feature would make you upgrade to a higher tier?",
        "Which feature, if missing, would make you consider switching products?",
        "Describe a workflow you currently can't do that these features would enable.",
    ],
    "responses_per_persona": 3,
}).json()

for _ in range(20):
    time.sleep(5)
    data = requests.get(f"https://app.mavera.io/api/v1/focus-groups/{fg['id']}", headers=MV_H).json()
    if data.get("status") == "completed": break

print(f"\nFocus Group: {fg['id']}")
for resp in data.get("responses", []):
    print(f"\n{resp.get('question','')[:60]}")
    print(f"  → {resp.get('answer','')[:300]}")

Example Output

{
  "feature_categories": 7,
  "top_ranked": [
    { "feature": "Custom Dashboard Builder", "mentions": 23, "rank_avg": 1.8 },
    { "feature": "API Webhook Support", "mentions": 15, "rank_avg": 2.1 },
    { "feature": "Multi-language Support", "mentions": 12, "rank_avg": 3.4 },
    { "feature": "Slack Integration", "mentions": 11, "rank_avg": 2.9 }
  ],
  "persona_insights": {
    "Power User PM": "Custom dashboards ranked #1. 'I export to Sheets weekly because your reporting doesn't slice by persona × campaign.'",
    "Executive Sponsor": "API webhooks ranked #1. 'Need real-time data flow to our BI tool. Manual exports kill adoption.'",
    "New User": "Slack integration ranked #1. 'I live in Slack. If I can't get notifications there, I'll forget this tool exists.'"
  }
}

Error Handling

Not all ‘dislike’ comments are feature requests — some are complaints. Mave’s categorization filters noise, but verify the output categories manually before sharing with product.
Focus Groups work best with 5-8 ranking options. More than 8 dilutes signal. Merge similar features before ranking.