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

# Campaign Performance → Content Optimization

> Pull top-performing Mailchimp campaign data and extract winning content patterns into a Mavera Brand Voice trained on your actual email performance

### Scenario

Your Mailchimp account has months of campaign data — open rates, click rates, bounce rates, and the actual content that drove those numbers. You pull performance reports for your top-performing campaigns, extract the subject lines, preview text, and content patterns, then feed them into Mavera's Brand Voice to capture what works. The result is a brand voice trained on your actual winning email content.

### Architecture

```mermaid theme={"dark"}
flowchart LR
A["GET /campaigns"] --> B["GET /reports/{id}"] --> C["Extract winning content patterns"] --> D["POST /api/v1/brand-voices"] --> E["Brand voice from winning emails"]
```

### Code

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

  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)

  r = requests.get(
      f"{MC_BASE}/campaigns",
      auth=mc_auth,
      params={
          "count": 50,
          "sort_field": "send_time",
          "sort_dir": "DESC",
          "status": "sent",
          "fields": "campaigns.id,campaigns.settings,campaigns.report_summary,campaigns.send_time",
      },
  )
  r.raise_for_status()
  campaigns = r.json().get("campaigns", [])

  scored = []
  for c in campaigns:
      report = c.get("report_summary", {})
      opens = report.get("open_rate", 0)
      clicks = report.get("click_rate", 0)
      settings = c.get("settings", {})

      if opens > 0:
          scored.append({
              "id": c["id"],
              "subject": settings.get("subject_line", ""),
              "preview": settings.get("preview_text", ""),
              "from_name": settings.get("from_name", ""),
              "open_rate": opens,
              "click_rate": clicks,
              "send_time": c.get("send_time", ""),
          })

  scored.sort(key=lambda x: x["open_rate"] * 0.6 + x["click_rate"] * 0.4, reverse=True)
  top = scored[:15]
  bottom = scored[-5:]

  winning_content = []
  for camp in top[:10]:
      report_r = requests.get(f"{MC_BASE}/reports/{camp['id']}", auth=mc_auth)
      if report_r.status_code == 200:
          detail = report_r.json()
          camp["unique_opens"] = detail.get("opens", {}).get("unique_opens", 0)
          camp["unique_clicks"] = detail.get("clicks", {}).get("unique_clicks", 0)
          camp["bounces"] = detail.get("bounces", {}).get("hard_bounces", 0)

      winning_content.append(
          f"Subject: {camp['subject']}\n"
          f"Preview: {camp['preview']}\n"
          f"From: {camp['from_name']}\n"
          f"Open: {camp['open_rate']:.0%} | Click: {camp['click_rate']:.0%}"
      )
      time.sleep(0.3)

  samples_text = "\n\n---\n\n".join(winning_content)

  voice = requests.post(f"{MB}/brand-voices", headers=MH, json={
      "name": "Mailchimp: Winning Email Voice",
      "description": (
          "Brand voice extracted from top-performing Mailchimp campaigns. "
          f"Based on {len(top)} campaigns with avg open rate "
          f"{sum(c['open_rate'] for c in top)/len(top):.0%} and avg click rate "
          f"{sum(c['click_rate'] for c in top)/len(top):.0%}."
      ),
      "samples": [c["subject"] + " — " + c["preview"] for c in top],
      "guidelines": (
          f"Top-performing subject lines average {sum(len(c['subject']) for c in top)//len(top)} characters. "
          f"Common patterns: "
          + ("personalization, " if any("{" in c["subject"] or "you" in c["subject"].lower() for c in top) else "")
          + ("urgency, " if any(w in " ".join(c["subject"].lower() for c in top) for w in ["today", "now", "last", "ending"]) else "")
          + ("questions, " if any("?" in c["subject"] for c in top) else "")
          + ("numbers/lists." if any(c["subject"][0].isdigit() for c in top) else "clarity.")
      ),
  }).json()

  print(f"Brand Voice created: {voice.get('id')}")
  print(f"Based on {len(top)} top campaigns")
  print(f"Avg open: {sum(c['open_rate'] for c in top)/len(top):.0%}")
  print(f"Avg click: {sum(c['click_rate'] for c in top)/len(top):.0%}")
  print(f"\nTop 3 subjects:")
  for c in top[:3]:
      print(f"  {c['open_rate']:.0%} open | {c['subject']}")
  ```

  ```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 campRes = await fetch(
    `${MC_BASE}/campaigns?count=50&sort_field=send_time&sort_dir=DESC&status=sent`,
    { headers: { Authorization: mcAuth } }
  ).then((r) => r.json());

  const scored = (campRes.campaigns || [])
    .filter((c) => (c.report_summary?.open_rate || 0) > 0)
    .map((c) => ({
      id: c.id,
      subject: c.settings?.subject_line || "",
      preview: c.settings?.preview_text || "",
      fromName: c.settings?.from_name || "",
      openRate: c.report_summary?.open_rate || 0,
      clickRate: c.report_summary?.click_rate || 0,
    }))
    .sort((a, b) => (b.openRate * 0.6 + b.clickRate * 0.4) - (a.openRate * 0.6 + a.clickRate * 0.4));

  const top = scored.slice(0, 15);

  for (const camp of top.slice(0, 10)) {
    const detail = await fetch(`${MC_BASE}/reports/${camp.id}`, {
      headers: { Authorization: mcAuth },
    }).then((r) => r.json());
    camp.uniqueOpens = detail.opens?.unique_opens || 0;
    camp.uniqueClicks = detail.clicks?.unique_clicks || 0;
    await new Promise((r) => setTimeout(r, 300));
  }

  const avgOpen = top.reduce((s, c) => s + c.openRate, 0) / top.length;
  const avgClick = top.reduce((s, c) => s + c.clickRate, 0) / top.length;
  const avgLen = Math.round(top.reduce((s, c) => s + c.subject.length, 0) / top.length);

  const voice = await fetch(`${MB}/brand-voices`, { method: "POST", headers: MH,
    body: JSON.stringify({
      name: "Mailchimp: Winning Email Voice",
      description: `Voice from top ${top.length} campaigns. Avg open: ${(avgOpen * 100).toFixed(0)}%. Avg click: ${(avgClick * 100).toFixed(0)}%.`,
      samples: top.map((c) => `${c.subject} — ${c.preview}`),
      guidelines: `Top subjects avg ${avgLen} chars. Focus on clarity and reader benefit.`,
    }),
  }).then((r) => r.json());

  console.log(`Brand Voice: ${voice.id}`);
  console.log(`Based on ${top.length} campaigns | Open: ${(avgOpen * 100).toFixed(0)}% | Click: ${(avgClick * 100).toFixed(0)}%`);
  top.slice(0, 3).forEach((c) => console.log(`  ${(c.openRate * 100).toFixed(0)}% | ${c.subject}`));
  ```
</CodeGroup>

### Example Output

```text theme={"dark"}
Brand Voice created: bv_mc_email_1
Based on 15 top campaigns
Avg open: 34%
Avg click: 5.2%

Top 3 subjects:
  48% open | Your competitor just launched this — here's your move
  44% open | 3 things your dashboard isn't telling you
  41% open | We rebuilt the feature you asked for
```

### Error Handling

<AccordionGroup>
  <Accordion title="Campaign report_summary is optional">The `report_summary` field is included in campaign list responses only for sent campaigns. Draft and scheduled campaigns won't have it. Filter by `status=sent`.</Accordion>
  <Accordion title="Rate limit: 10 connections">Each API call occupies a connection slot. The detailed report fetch for 10 campaigns uses 10 sequential calls with 300ms delays. Avoid parallel fetches exceeding 10.</Accordion>
  <Accordion title="Brand Voice sample limits">Mavera's Brand Voice endpoint may have limits on the number of samples. If 15 samples exceeds the limit, reduce to 10 — quality of top performers matters more than quantity.</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="Subscriber Persona Creation" icon="users" href="/integrations/mailchimp/subscriber-persona-creation">
    Build personas from audience segments
  </Card>

  <Card title="A/B Focus Group" icon="flask-vial" href="/integrations/mailchimp/ab-focus-group">
    Understand why A/B variants win
  </Card>

  <Card title="Brand Voice API" icon="microphone" href="/api-reference/brand-voices">
    Full reference for POST /api/v1/brand-voices
  </Card>
</CardGroup>
