Scenario
Your Segment workspace has behavioral audiences — high-value customers, churning users, recently activated accounts, trial converters. Each audience represents a real behavioral cluster. You pull audience definitions and member counts, map each audience to a Mavera persona, and run Focus Groups where each persona represents a Segment audience. The result is qualitative research anchored to quantitative behavioral segments.Architecture
Code
import os, requests, time
SEG_TOKEN = os.environ["SEGMENT_TOKEN"]
MV = os.environ["MAVERA_API_KEY"]
MB = "https://app.mavera.io/api/v1"
MH = {"Authorization": f"Bearer {MV}", "Content-Type": "application/json"}
SH = {"Authorization": f"Bearer {SEG_TOKEN}", "Content-Type": "application/json"}
SB = "https://api.segmentapis.com"
SPACE_ID = os.environ.get("SEGMENT_SPACE_ID", "spa_xxxxx")
r = requests.get(f"{SB}/spaces/{SPACE_ID}/audiences", headers=SH)
r.raise_for_status()
audiences_data = r.json()
audiences = audiences_data.get("data", {}).get("audiences", [])
if not audiences:
audiences = [
{"id": "aud_001", "name": "High-Value Customers", "description": "Users with >$500 LTV who purchased 3+ times in 90 days", "estimatedSize": 2400},
{"id": "aud_002", "name": "Churning Users", "description": "Active users whose engagement dropped >50% in last 30 days", "estimatedSize": 1800},
{"id": "aud_003", "name": "Trial Converters", "description": "Users who converted from free trial to paid within 14 days", "estimatedSize": 960},
{"id": "aud_004", "name": "Power Users", "description": "Users in top 10% by event volume over last 30 days", "estimatedSize": 500},
]
print(f"Found {len(audiences)} audiences\n")
personas = []
for aud in audiences[:6]:
name = aud.get("name", "Unknown Audience")
desc = aud.get("description", "")
size = aud.get("estimatedSize", aud.get("estimated_size", 0))
persona = requests.post(f"{MB}/personas", headers=MH, json={
"name": f"Segment: {name}",
"description": (
f"Behavioral audience from Segment Engage. {desc}. "
f"Estimated size: {size:,} users. "
f"This persona represents users who match the audience criteria in real product behavior."
),
"demographic": {
"source": "segment_audience",
"audience_id": aud.get("id", ""),
"estimated_size": size,
},
}).json()
personas.append({"audience": name, "persona_id": persona["id"], "size": size})
print(f" {name} → {persona['id']} ({size:,} users)")
time.sleep(0.3)
audience_context = "\n".join(
f"- {p['audience']}: {p['size']:,} users (Persona: {p['persona_id']})"
for p in personas
)
fg = requests.post(f"{MB}/focus-groups", headers=MH, json={
"name": "Segment Audience Research",
"persona_ids": [p["persona_id"] for p in personas],
"questions": [
"Describe your typical week using this product. What do you use it for, and how often?",
"What's the single most valuable thing this product does for you? If that feature disappeared, what would you do?",
"What's your biggest frustration with the product right now? Be specific about what happens and how it affects your work.",
"If you could add one capability, what would it be? How much would you pay extra for it?",
"When was the last time you recommended this product to someone? What did you say? If you haven't recommended it, why not?",
],
"context": f"""Segment audience research study. Each persona represents a behavioral audience from Segment Engage:
{audience_context}
These audiences are defined by real product behavior — purchases, engagement levels, conversion patterns, and usage intensity. The goal is to understand WHY these behavioral patterns exist.""",
"responses_per_persona": 2,
}).json()
for _ in range(30):
time.sleep(5)
data = requests.get(f"{MB}/focus-groups/{fg['id']}", headers=MH).json()
if data.get("status") == "completed":
break
print(f"\nFocus Group: {data.get('id')} — {data.get('status')}\n")
for resp in data.get("responses", []):
print(f"[{resp.get('persona_id','?')}] {resp.get('question','')[:70]}")
print(f" → {resp.get('answer','')[:300]}\n")
const SEG_TOKEN = process.env.SEGMENT_TOKEN;
const MV = process.env.MAVERA_API_KEY;
const MB = "https://app.mavera.io/api/v1";
const MH = { Authorization: `Bearer ${MV}`, "Content-Type": "application/json" };
const SH = { Authorization: `Bearer ${SEG_TOKEN}`, "Content-Type": "application/json" };
const SPACE_ID = process.env.SEGMENT_SPACE_ID || "spa_xxxxx";
const audRes = await fetch(
`https://api.segmentapis.com/spaces/${SPACE_ID}/audiences`,
{ headers: SH }
).then((r) => r.json());
let audiences = audRes.data?.audiences || [];
if (!audiences.length) {
audiences = [
{ id: "aud_001", name: "High-Value Customers", description: "Users with >$500 LTV, 3+ purchases in 90d", estimatedSize: 2400 },
{ id: "aud_002", name: "Churning Users", description: "Engagement dropped >50% in 30d", estimatedSize: 1800 },
{ id: "aud_003", name: "Trial Converters", description: "Free trial → paid within 14d", estimatedSize: 960 },
{ id: "aud_004", name: "Power Users", description: "Top 10% by event volume (30d)", estimatedSize: 500 },
];
}
console.log(`Found ${audiences.length} audiences\n`);
const personas = [];
for (const aud of audiences.slice(0, 6)) {
const size = aud.estimatedSize || aud.estimated_size || 0;
const p = await fetch(`${MB}/personas`, { method: "POST", headers: MH,
body: JSON.stringify({
name: `Segment: ${aud.name}`,
description: `Behavioral audience from Segment. ${aud.description || ""}. Size: ${size.toLocaleString()} users.`,
demographic: { source: "segment_audience", audience_id: aud.id, estimated_size: size },
}),
}).then((r) => r.json());
personas.push({ audience: aud.name, personaId: p.id, size });
console.log(` ${aud.name} → ${p.id} (${size.toLocaleString()} users)`);
await new Promise((r) => setTimeout(r, 300));
}
const audContext = personas
.map((p) => `- ${p.audience}: ${p.size.toLocaleString()} users (${p.personaId})`)
.join("\n");
const fg = await fetch(`${MB}/focus-groups`, { method: "POST", headers: MH,
body: JSON.stringify({
name: "Segment Audience Research",
persona_ids: personas.map((p) => p.personaId),
questions: [
"Describe your typical week using this product. What and how often?",
"Single most valuable feature? If it disappeared, what would you do?",
"Biggest frustration right now? Be specific.",
"One new capability — what and how much extra would you pay?",
"Last time you recommended this product? What did you say?",
],
context: `Segment audience study. Each persona = a behavioral audience:\n\n${audContext}\n\nGoal: understand WHY these behavioral patterns exist.`,
responses_per_persona: 2,
}),
}).then((r) => r.json());
let data;
for (let i = 0; i < 30; i++) {
await new Promise((r) => setTimeout(r, 5000));
data = await fetch(`${MB}/focus-groups/${fg.id}`, { headers: MH }).then((r) => r.json());
if (data.status === "completed") break;
}
console.log(`\nFocus Group: ${data.id} — ${data.status}\n`);
for (const resp of data.responses || []) {
console.log(`[${resp.persona_id}] ${(resp.question || "").slice(0, 70)}`);
console.log(` → ${(resp.answer || "").slice(0, 300)}\n`);
}
Example Output
Found 4 audiences
High-Value Customers → per_seg_hv_1 (2,400 users)
Churning Users → per_seg_ch_2 (1,800 users)
Trial Converters → per_seg_tc_3 (960 users)
Power Users → per_seg_pu_4 (500 users)
Focus Group: fg_seg_aud_7k3m — completed
[High-Value Customers] Single most valuable feature?
→ The automated reporting. I pull weekly metrics for three clients
and this tool builds the report in 2 minutes instead of 45. If
it disappeared, I'd need to hire a part-time analyst or go back
to spreadsheets. That's the feature that justified the price.
[Churning Users] Biggest frustration right now?
→ The dashboard redesign broke my workflow. I had three custom
views that took me a week to set up — after the update, two
were gone. No warning, no migration path. I've been using the
product less because I'd have to rebuild everything.
[Trial Converters] One new capability?
→ Template marketplace. I converted because the templates in the
trial were exactly what I needed, but now I've used them all
and creating from scratch is too time-consuming. I'd pay $10/mo
more for community-contributed templates.
Error Handling
Audiences API requires Engage
Audiences API requires Engage
The
/spaces/{id}/audiences endpoint requires Segment Engage (formerly Personas). If you’re on the free Connections plan, audiences aren’t available. The code includes fallback sample data for testing.Space ID format
Space ID format
Segment Space IDs use the format
spa_xxxxx. Find yours in Segment → Engage → Settings, or via GET /spaces on the Management API.Estimated size vs. exact count
Estimated size vs. exact count
The
estimatedSize field is an approximation. For exact counts, use the Profiles API to query audience membership directly, but this is significantly slower.What’s Next
Segment Integration
Back to Segment integration overview
Profile Traits → Custom Persona Source
Create trait-enriched personas from computed traits
Focus Groups API
Full reference for POST /api/v1/focus-groups
Personas API
Full reference for POST /api/v1/personas