> ## 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.

# Subscriber Segment → Persona Creation

> Pull Mailchimp audience segments and member data to create segment-grounded Mavera Custom Personas from real subscriber demographics and engagement patterns

### Scenario

Your Mailchimp audience has segments — VIP customers, newsletter-only subscribers, recent signups, inactive members. Each segment represents a real behavioral group. You pull segment definitions and member data, aggregate demographics and engagement patterns per segment, and create a Mavera Custom Persona for each. The result is a persona library built from your actual email audience, not hypothetical demographics.

### Architecture

```mermaid theme={"dark"}
flowchart LR
A["GET /lists/{id}/segments"] --> B["GET segment members"] --> C["Aggregate demographics + engagement"] --> D["POST /api/v1/personas"] --> E["Segment-grounded persona set"]
```

### Code

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

  MC_KEY = os.environ["MAILCHIMP_API_KEY"]
  MC_DC = os.environ["MAILCHIMP_DC"]
  MV = os.environ["MAVERA_API_KEY"]
  MB = "https://app.mavera.io/api/v1"
  MH = {"Authorization": f"Bearer {MV}", "Content-Type": "application/json"}
  MC_BASE = f"https://{MC_DC}.api.mailchimp.com/3.0"
  mc_auth = ("anystring", MC_KEY)

  lists_r = requests.get(f"{MC_BASE}/lists", auth=mc_auth, params={"count": 5})
  lists_r.raise_for_status()
  lists = lists_r.json().get("lists", [])
  LIST_ID = lists[0]["id"] if lists else os.environ.get("MAILCHIMP_LIST_ID", "")

  segs_r = requests.get(f"{MC_BASE}/lists/{LIST_ID}/segments", auth=mc_auth, params={"count": 20})
  segs_r.raise_for_status()
  segments = segs_r.json().get("segments", [])

  print(f"List: {LIST_ID} | Segments: {len(segments)}\n")

  created = []
  for seg in segments[:8]:
      seg_id = seg["id"]
      seg_name = seg["name"]
      member_count = seg.get("member_count", 0)

      members_r = requests.get(
          f"{MC_BASE}/lists/{LIST_ID}/segments/{seg_id}/members",
          auth=mc_auth,
          params={"count": 100, "fields": "members.email_address,members.merge_fields,members.stats,members.status,members.source"},
      )
      members = members_r.json().get("members", [])

      sources = defaultdict(int)
      statuses = defaultdict(int)
      avg_open = []
      avg_click = []

      for m in members:
          if m.get("source"):
              sources[m["source"]] += 1
          statuses[m.get("status", "unknown")] += 1
          stats = m.get("stats", {})
          avg_open.append(stats.get("avg_open_rate", 0))
          avg_click.append(stats.get("avg_click_rate", 0))

      top_sources = sorted(sources, key=sources.get, reverse=True)[:3]
      seg_avg_open = sum(avg_open) / max(len(avg_open), 1)
      seg_avg_click = sum(avg_click) / max(len(avg_click), 1)

      persona = requests.post(f"{MB}/personas", headers=MH, json={
          "name": f"Mailchimp: {seg_name}",
          "description": (
              f"Email subscriber segment from Mailchimp. {member_count} members. "
              f"Avg open rate: {seg_avg_open:.0%}. Avg click rate: {seg_avg_click:.0%}. "
              f"Top signup sources: {', '.join(top_sources) if top_sources else 'N/A'}. "
              f"Segment type: {seg.get('type', 'saved')}."
          ),
          "demographic": {
              "source": "mailchimp_segment",
              "segment_id": str(seg_id),
              "member_count": member_count,
              "signup_sources": top_sources,
          },
          "psychographic": {
              "avg_open_rate": seg_avg_open,
              "avg_click_rate": seg_avg_click,
              "engagement_level": "high" if seg_avg_open > 0.3 else "medium" if seg_avg_open > 0.15 else "low",
          },
      }).json()

      created.append({"segment": seg_name, "id": persona["id"], "members": member_count})
      print(f"  {seg_name}: {persona['id']} ({member_count} members, {seg_avg_open:.0%} open)")
      time.sleep(0.5)

  print(f"\nCreated {len(created)} subscriber personas")
  ```

  ```javascript JavaScript theme={"dark"}
  const MC_KEY = process.env.MAILCHIMP_API_KEY;
  const MC_DC = process.env.MAILCHIMP_DC;
  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 MC_BASE = `https://${MC_DC}.api.mailchimp.com/3.0`;
  const mcAuth = "Basic " + Buffer.from(`anystring:${MC_KEY}`).toString("base64");

  const listsRes = await fetch(`${MC_BASE}/lists?count=5`, {
    headers: { Authorization: mcAuth },
  }).then((r) => r.json());
  const LIST_ID = listsRes.lists?.[0]?.id || process.env.MAILCHIMP_LIST_ID || "";

  const segsRes = await fetch(`${MC_BASE}/lists/${LIST_ID}/segments?count=20`, {
    headers: { Authorization: mcAuth },
  }).then((r) => r.json());
  const segments = segsRes.segments || [];

  console.log(`List: ${LIST_ID} | Segments: ${segments.length}\n`);

  const created = [];
  for (const seg of segments.slice(0, 8)) {
    const membersRes = await fetch(
      `${MC_BASE}/lists/${LIST_ID}/segments/${seg.id}/members?count=100`,
      { headers: { Authorization: mcAuth } }
    ).then((r) => r.json());
    const members = membersRes.members || [];

    const sources = {}, statuses = {};
    let openSum = 0, clickSum = 0;
    for (const m of members) {
      if (m.source) sources[m.source] = (sources[m.source] || 0) + 1;
      statuses[m.status || "unknown"] = (statuses[m.status] || 0) + 1;
      openSum += m.stats?.avg_open_rate || 0;
      clickSum += m.stats?.avg_click_rate || 0;
    }

    const topSources = Object.keys(sources).sort((a, b) => sources[b] - sources[a]).slice(0, 3);
    const avgOpen = openSum / (members.length || 1);
    const avgClick = clickSum / (members.length || 1);

    const p = await fetch(`${MB}/personas`, { method: "POST", headers: MH,
      body: JSON.stringify({
        name: `Mailchimp: ${seg.name}`,
        description: `Subscriber segment. ${seg.member_count} members. Open: ${(avgOpen * 100).toFixed(0)}%. Click: ${(avgClick * 100).toFixed(0)}%. Sources: ${topSources.join(", ") || "N/A"}.`,
        demographic: { source: "mailchimp_segment", segment_id: String(seg.id), member_count: seg.member_count },
        psychographic: { avg_open_rate: avgOpen, avg_click_rate: avgClick, engagement_level: avgOpen > 0.3 ? "high" : avgOpen > 0.15 ? "medium" : "low" },
      }),
    }).then((r) => r.json());

    created.push({ segment: seg.name, id: p.id, members: seg.member_count });
    console.log(`  ${seg.name}: ${p.id} (${seg.member_count} members, ${(avgOpen * 100).toFixed(0)}% open)`);
    await new Promise((r) => setTimeout(r, 500));
  }

  console.log(`\nCreated ${created.length} subscriber personas`);
  ```
</CodeGroup>

### Example Output

```json theme={"dark"}
{
  "list": "abc123def",
  "personas": [
    { "segment": "VIP Customers", "id": "per_mc_vip_1", "members": 450, "avg_open": "42%" },
    { "segment": "Recent Signups (30d)", "id": "per_mc_new_2", "members": 1200, "avg_open": "38%" },
    { "segment": "Newsletter Only", "id": "per_mc_nl_3", "members": 3400, "avg_open": "18%" },
    { "segment": "Inactive 90d+", "id": "per_mc_in_4", "members": 2100, "avg_open": "4%" }
  ]
}
```

### Error Handling

<AccordionGroup>
  <Accordion title="10 simultaneous connection limit">Mailchimp enforces 10 concurrent connections per API key. The code uses sequential requests with 500ms delays. For parallel processing, use a connection pool limited to 8.</Accordion>
  <Accordion title="Segment member pagination">The `/segments/{id}/members` endpoint returns max 1,000 members per request. Use `offset` for pagination. Each page counts as one connection.</Accordion>
  <Accordion title="Merge fields vary by audience">Member `merge_fields` (FNAME, LNAME, etc.) depend on your audience configuration. The code uses `stats` which are always available regardless of merge field setup.</Accordion>
</AccordionGroup>

***

## What's Next

<CardGroup cols={2}>
  <Card title="Mailchimp Integration" icon="envelope" href="/integrations/mailchimp">
    Back to Mailchimp integration overview
  </Card>

  <Card title="Campaign Content Optimization" icon="chart-line" href="/integrations/mailchimp/campaign-content-optimization">
    Train brand voice from winning campaigns
  </Card>

  <Card title="Personas API" icon="users" href="/api-reference/personas">
    Full reference for POST /api/v1/personas
  </Card>

  <Card title="All Integrations" icon="plug" href="/integrations">
    50+ API integrations with full code
  </Card>
</CardGroup>
