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

# Email A/B Winner → Focus Group Why

> Pull Mailchimp A/B test results and run a Mavera Focus Group to understand the psychological drivers behind why one subject line outperformed another

### Scenario

Mailchimp ran an A/B test on subject lines (or content) and one variant won. You know *which* subject line had a higher open rate, but not *why*. You pull both variants and the performance results, then run a Mavera Focus Group asking personas which subject line they'd open and why — the psychological drivers behind the click.

### Architecture

```mermaid theme={"dark"}
flowchart LR
A["GET /campaigns/{id} A/B results"] --> B["Extract both variants + metrics"] --> C["POST /api/v1/focus-groups"] --> D["Why did one subject line win?"]
```

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

  AB_CAMPAIGN_ID = os.environ.get("MAILCHIMP_AB_CAMPAIGN_ID", "")

  if AB_CAMPAIGN_ID:
      r = requests.get(f"{MC_BASE}/campaigns/{AB_CAMPAIGN_ID}", auth=mc_auth)
      r.raise_for_status()
      campaign = r.json()
      ab_settings = campaign.get("variate_settings", {})
  else:
      ab_settings = {
          "subject_lines": [
              "Your Q1 numbers are in — here's what they mean",
              "We analyzed your Q1 data (3 surprises inside)"
          ],
          "winner_criteria": "open_rate",
      }
      campaign = {
          "report_summary": {"open_rate": 0.32, "click_rate": 0.048},
      }

  subject_a = ab_settings.get("subject_lines", ["Subject A", "Subject B"])[0]
  subject_b = ab_settings.get("subject_lines", ["Subject A", "Subject B"])[1] if len(ab_settings.get("subject_lines", [])) > 1 else "Subject B"

  report_r = requests.get(f"{MC_BASE}/reports/{AB_CAMPAIGN_ID}/ab", auth=mc_auth) if AB_CAMPAIGN_ID else None
  if report_r and report_r.status_code == 200:
      ab_report = report_r.json()
      a_stats = ab_report.get("a", {})
      b_stats = ab_report.get("b", {})
  else:
      a_stats = {"open_rate": 0.28, "click_rate": 0.038, "unique_opens": 1400}
      b_stats = {"open_rate": 0.36, "click_rate": 0.052, "unique_opens": 1800}

  winner = "B" if b_stats.get("open_rate", 0) > a_stats.get("open_rate", 0) else "A"

  PERSONA_IDS = os.environ.get("AB_PERSONA_IDS", "").split(",")
  if not PERSONA_IDS[0]:
      for name, desc in [
          ("Newsletter Regular", "Opens emails 2-3x per week. Skims subject lines quickly. Values clarity over cleverness."),
          ("Busy Executive", "Gets 200+ emails/day. Opens only what seems urgent or directly relevant. Reads on mobile."),
          ("Curious Explorer", "Opens most marketing emails. Enjoys discovering new ideas. Clicks through to articles."),
      ]:
          p = requests.post(f"{MB}/personas", headers=MH, json={"name": name, "description": desc}).json()
          PERSONA_IDS.append(p["id"])
          time.sleep(0.3)

  fg = requests.post(f"{MB}/focus-groups", headers=MH, json={
      "name": "Mailchimp A/B Subject Line Investigation",
      "persona_ids": [pid for pid in PERSONA_IDS if pid],
      "questions": [
          f'You see two emails in your inbox:\n  A: "{subject_a}"\n  B: "{subject_b}"\nWhich would you open first? Why? What about the winning subject line caught your attention?',
          f'Subject A got {a_stats.get("open_rate", 0):.0%} opens and Subject B got {b_stats.get("open_rate", 0):.0%}. Does the winner ({winner}) surprise you? Why do you think it performed better?',
          "What elements in a subject line make you most likely to open: (1) Personalization, (2) Curiosity gap, (3) Urgency, (4) Social proof, (5) Specificity (numbers/data)? Rank and explain your #1.",
          "Write a subject line that would outperform BOTH of these. Explain your strategy.",
      ],
      "context": f"""Mailchimp A/B test results:

  VARIANT A: "{subject_a}"
    Open rate: {a_stats.get('open_rate', 0):.0%} | Clicks: {a_stats.get('click_rate', 0):.0%} | Unique opens: {a_stats.get('unique_opens', 0):,}

  VARIANT B: "{subject_b}"
    Open rate: {b_stats.get('open_rate', 0):.0%} | Clicks: {b_stats.get('click_rate', 0):.0%} | Unique opens: {b_stats.get('unique_opens', 0):,}

  Winner: Variant {winner} (by {ab_settings.get('winner_criteria', 'open_rate')})
  Margin: {abs(a_stats.get('open_rate', 0) - b_stats.get('open_rate', 0)):.0%} difference""",
      "responses_per_persona": 2,
  }).json()

  for _ in range(24):
      time.sleep(5)
      data = requests.get(f"{MB}/focus-groups/{fg['id']}", headers=MH).json()
      if data.get("status") == "completed":
          break

  print(f"Focus 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")
  ```

  ```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 AB_ID = process.env.MAILCHIMP_AB_CAMPAIGN_ID || "";

  let subjectA = "Your Q1 numbers are in — here's what they mean";
  let subjectB = "We analyzed your Q1 data (3 surprises inside)";
  let aStats = { open_rate: 0.28, click_rate: 0.038, unique_opens: 1400 };
  let bStats = { open_rate: 0.36, click_rate: 0.052, unique_opens: 1800 };

  if (AB_ID) {
    const camp = await fetch(`${MC_BASE}/campaigns/${AB_ID}`, { headers: { Authorization: mcAuth } }).then((r) => r.json());
    const subs = camp.variate_settings?.subject_lines || [];
    if (subs[0]) subjectA = subs[0];
    if (subs[1]) subjectB = subs[1];

    const abReport = await fetch(`${MC_BASE}/reports/${AB_ID}/ab`, { headers: { Authorization: mcAuth } }).then((r) => r.json());
    if (abReport.a) aStats = abReport.a;
    if (abReport.b) bStats = abReport.b;
  }

  const winner = bStats.open_rate > aStats.open_rate ? "B" : "A";

  const personaIds = [];
  for (const [name, desc] of [
    ["Newsletter Regular", "Opens 2-3x/week. Skims subjects. Values clarity."],
    ["Busy Executive", "200+ emails/day. Opens only urgent/relevant. Mobile."],
    ["Curious Explorer", "Opens most marketing emails. Enjoys discovering."],
  ]) {
    const p = await fetch(`${MB}/personas`, { method: "POST", headers: MH,
      body: JSON.stringify({ name, description: desc }) }).then((r) => r.json());
    personaIds.push(p.id);
    await new Promise((r) => setTimeout(r, 300));
  }

  const fg = await fetch(`${MB}/focus-groups`, { method: "POST", headers: MH,
    body: JSON.stringify({
      name: "Mailchimp A/B Investigation",
      persona_ids: personaIds,
      questions: [
        `Two emails:\n  A: "${subjectA}"\n  B: "${subjectB}"\nWhich first? Why?`,
        `A: ${(aStats.open_rate * 100).toFixed(0)}% vs B: ${(bStats.open_rate * 100).toFixed(0)}%. Winner ${winner} surprise you?`,
        "Rank: (1) Personalization, (2) Curiosity gap, (3) Urgency, (4) Social proof, (5) Specificity. Explain #1.",
        "Write a subject line that outperforms both. Explain your strategy.",
      ],
      context: `A/B test:\nA: "${subjectA}" — ${(aStats.open_rate * 100).toFixed(0)}% open, ${(aStats.click_rate * 100).toFixed(0)}% click\nB: "${subjectB}" — ${(bStats.open_rate * 100).toFixed(0)}% open, ${(bStats.click_rate * 100).toFixed(0)}% click\nWinner: ${winner}`,
      responses_per_persona: 2,
    }),
  }).then((r) => r.json());

  let data;
  for (let i = 0; i < 24; 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;
  }

  for (const resp of data.responses || []) {
    console.log(`[${resp.persona_id}] ${(resp.question || "").slice(0, 70)}`);
    console.log(`  → ${(resp.answer || "").slice(0, 300)}\n`);
  }
  ```
</CodeGroup>

### Example Output

```text theme={"dark"}
Focus Group: fg_mc_ab_5k8n — completed

[Newsletter Regular] Which would you open first?
  → B: "We analyzed your Q1 data (3 surprises inside)". The number 3
    tells me this is a quick read, and "surprises" creates a curiosity
    gap I can't ignore. Subject A feels like a report I should read —
    Subject B feels like a secret I want to know.

[Busy Executive] Does the winner surprise you?
  → No. B has specificity (3 surprises) and implied exclusivity ("your
    data"). A sounds like a generic newsletter. When I'm scanning 200
    subjects, the one that says "we did work FOR YOU" wins over "here's
    information."

[Curious Explorer] Write a subject line that outperforms both
  → "Your Q1 had 3 anomalies — #2 changes your strategy." It combines
    personalization ("your"), specificity ("3"), curiosity ("#2 changes"),
    and stakes ("your strategy"). The incomplete list (naming #2 but
    not #1 or #3) creates irresistible curiosity.
```

### Error Handling

<AccordionGroup>
  <Accordion title="A/B test campaign structure">Mailchimp stores A/B test variants in `variate_settings.subject_lines` (for subject tests) or `variate_settings.contents` (for content tests). The winning criteria is in `variate_settings.winner_criteria`.</Accordion>
  <Accordion title="A/B report endpoint">The `/reports/{id}/ab` endpoint returns variant-level stats. Not all campaigns have this — only those created as "A/B Test" type. Regular campaigns return 404 on this endpoint.</Accordion>
  <Accordion title="Focus Group timing">3 personas × 4 questions × 2 responses = 24 total. Allow 60–120s. The loop provides \~120s.</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="Interest Content Generation" icon="tags" href="/integrations/mailchimp/interest-content-generation">
    Generate content by audience interest
  </Card>

  <Card title="Focus Groups API" icon="comments" href="/api-reference/focus-groups">
    Full reference for POST /api/v1/focus-groups
  </Card>
</CardGroup>
