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

# Brand Perception Audit

> Run NPS and open-ended Focus Groups across customer, prospect, and churned-user personas for a 360-degree brand perception report

## Mavera Surfaces Used

| Surface                                          | Role                                                                             |
| ------------------------------------------------ | -------------------------------------------------------------------------------- |
| **Personas** (`POST /personas`, `GET /personas`) | Create 3 persona segments: customers, prospects, and churned users               |
| **Focus Groups** (`POST /focus-groups`)          | Run NPS + Open-Ended questions per segment for quantitative and qualitative data |
| **Chat + `response_format`**                     | Compare segment results and synthesize a 360-degree brand perception report      |

<Info>
  A real brand perception audit interviews existing customers, potential customers, and people who left. This playbook simulates all three segments with Mavera personas, producing quantitative NPS scores and qualitative perception data — side-by-side — in a single session.
</Info>

***

## What Value Does Mavera Add?

| Value                 | How                                                                                                                             |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| **Insurance**         | Catch brand perception gaps before they become retention problems. Compare how customers, prospects, and churned users see you. |
| **Opening new doors** | Run perception audits quarterly instead of annually. Track perception trends over time with consistent methodology.             |
| **Saving time**       | A traditional 3-segment perception study takes 4-6 weeks and \$20K+. This runs in under an hour.                                |

***

## When to Use This

* You suspect a gap between how you see your brand and how the market sees it.
* You're losing deals or customers and want to understand whether brand perception is a factor.
* You're preparing for a rebrand and need a baseline measurement.
* You want to compare perception across segments (customers love you but prospects don't know you).
* You're presenting brand health metrics to leadership and need structured data.

***

## What You Need

| Requirement                        | Details                                                                                              |
| ---------------------------------- | ---------------------------------------------------------------------------------------------------- |
| **Mavera API key**                 | Starts with `mvra_live_`. Get one at [Developer Settings](https://app.mavera.io/settings/developer). |
| **Workspace ID**                   | From your dashboard URL (`ws_...`).                                                                  |
| **Brand context**                  | Your brand name, category, value proposition, and key competitors.                                   |
| **Segment definitions**            | Characteristics of your customers, prospects, and churned users.                                     |
| **Credits**                        | \~300–700 total. See [Credits Estimate](#credits-estimate).                                          |
| **Python 3.8+** or **Node.js 18+** | `requests` / `openai` for Python; native `fetch` for Node.                                           |

```
MAVERA_API_KEY=mvra_live_your_key_here
MAVERA_WORKSPACE_ID=ws_your_workspace_id
BRAND_NAME=Acme
```

***

## The Audit Framework

Three focus groups run in parallel — one per segment. Each uses the same questions for comparability.

```mermaid theme={"dark"}
flowchart TD
    subgraph customers["Customers Path"]
        custData["Customer Segment Data"] --> custPersonas["Personas: 3 Customer Profiles"]
        custPersonas --> custFG["Focus Group: N=25"]
        custFG --> custNPS[("NPS Scores")]
        custFG --> custSemDiff[("Semantic Differential Scores")]
        custFG --> custOpenEnded[("Open-Ended Responses")]
    end

    subgraph prospects["Prospects Path"]
        prospData["Prospect Segment Data"] --> prospPersonas["Personas: 2 Prospect Profiles"]
        prospPersonas --> prospFG["Focus Group: N=25"]
        prospFG --> prospNPS[("NPS Scores")]
        prospFG --> prospSemDiff[("Semantic Differential Scores")]
        prospFG --> prospOpenEnded[("Open-Ended Responses")]
    end

    subgraph churned["Churned Users Path"]
        churnData["Churned User Segment Data"] --> churnPersonas["Personas: 2 Churned Profiles"]
        churnPersonas --> churnFG["Focus Group: N=25"]
        churnFG --> churnNPS[("NPS Scores")]
        churnFG --> churnSemDiff[("Semantic Differential Scores")]
        churnFG --> churnOpenEnded[("Open-Ended Responses")]
    end

    subgraph crossSegment["Cross-Segment Analysis"]
        custNPS --> chatSynth["Chat: response_format"]
        custSemDiff --> chatSynth
        custOpenEnded --> chatSynth
        prospNPS --> chatSynth
        prospSemDiff --> chatSynth
        prospOpenEnded --> chatSynth
        churnNPS --> chatSynth
        churnSemDiff --> chatSynth
        churnOpenEnded --> chatSynth
        chatSynth --> report(("360-Degree Brand Perception Report"))
    end
```

### Question Battery

Every segment answers the same 6 questions:

| # | Question                                                           | Type                      | What It Measures       |
| - | ------------------------------------------------------------------ | ------------------------- | ---------------------- |
| 1 | "How likely are you to recommend \{brand} to a colleague?"         | **NPS**                   | Overall brand advocacy |
| 2 | "What 3 words come to mind when you think of \{brand}?"            | **Open-Ended**            | Brand associations     |
| 3 | "Rate \{brand} on: Untrustworthy ←→ Trustworthy"                   | **Semantic Differential** | Trust perception       |
| 4 | "Rate \{brand} on: Outdated ←→ Innovative"                         | **Semantic Differential** | Innovation perception  |
| 5 | "How well does \{brand} deliver on its promise of \{value prop}?"  | **Likert** (1-10)         | Promise-delivery gap   |
| 6 | "What is the biggest risk of choosing \{brand} over alternatives?" | **Open-Ended**            | Perceived weaknesses   |

***

## The Flow

<Steps>
  <Step title="Define brand context">
    Set your brand name, category, value proposition, and key competitors. This context is included in every focus group.
  </Step>

  <Step title="Create 3 persona segments">
    Build 2-3 personas per segment: satisfied customers, evaluating prospects, and recently churned users. Each persona has unique motivations and context.
  </Step>

  <Step title="Run 3 Focus Groups in parallel">
    Launch one focus group per segment. All use the same 6-question battery for cross-segment comparability.
  </Step>

  <Step title="Poll for completion">
    Monitor all three groups. They run independently and may complete at different times.
  </Step>

  <Step title="Cross-segment comparison">
    Compare NPS, semantic differentials, and open-ended themes across all three segments.
  </Step>

  <Step title="Generate 360-degree report">
    Use Chat with structured output to synthesize a comprehensive brand perception report with gap analysis.
  </Step>
</Steps>

***

## Code: Full Brand Perception Audit

### Setup and Configuration

<CodeGroup>
  ```python Python theme={"dark"}
  import os
  import json
  import time
  import requests
  from openai import OpenAI

  MAVERA_API_KEY = os.environ["MAVERA_API_KEY"]
  WORKSPACE_ID = os.environ["MAVERA_WORKSPACE_ID"]
  BRAND_NAME = os.environ.get("BRAND_NAME", "Acme")
  BASE = "https://app.mavera.io/api/v1"
  HEADERS = {
      "Authorization": f"Bearer {MAVERA_API_KEY}",
      "Content-Type": "application/json",
  }
  mavera = OpenAI(api_key=MAVERA_API_KEY, base_url=BASE)

  BRAND_CONTEXT = {
      "name": BRAND_NAME,
      "category": "AI-powered market research platform",
      "value_prop": "replacing guesswork with persona-validated audience insights",
      "competitors": ["Pollfish", "UserTesting", "Wynter", "SurveyMonkey"],
  }

  SEGMENTS = {
      "customers": {
          "label": "Current Customers",
          "personas": [
              {
                  "name": f"{BRAND_NAME} Power User — Growth Marketer",
                  "description": (
                      f"Active {BRAND_NAME} user for 6+ months. Uses focus groups and chat weekly. "
                      "Growth marketer at a Series B startup. Loves the speed but occasionally "
                      "questions depth compared to real research. NPS likely 7-9."
                  ),
              },
              {
                  "name": f"{BRAND_NAME} Casual User — Content Manager",
                  "description": (
                      f"Uses {BRAND_NAME} 2-3 times a month for content scoring. "
                      "Content manager at a mid-market company. Finds it useful but hasn't "
                      "explored beyond basic chat. Might not renew if price increases. NPS likely 6-7."
                  ),
              },
              {
                  "name": f"{BRAND_NAME} Champion — VP Marketing",
                  "description": (
                      f"Internally champions {BRAND_NAME}. VP Marketing who got the team adopted. "
                      "Uses it for positioning workshops and campaign validation. "
                      "Would recommend to peers. NPS likely 9-10."
                  ),
              },
          ],
      },
      "prospects": {
          "label": "Prospects (Evaluating)",
          "personas": [
              {
                  "name": f"{BRAND_NAME} Prospect — Skeptical PMM",
                  "description": (
                      f"Aware of {BRAND_NAME} but hasn't tried it. Product marketer at an enterprise "
                      "company. Skeptical about synthetic audiences replacing real research. "
                      "Currently uses agencies and UserTesting. Needs proof of accuracy."
                  ),
              },
              {
                  "name": f"{BRAND_NAME} Prospect — Budget-Conscious Founder",
                  "description": (
                      f"Heard about {BRAND_NAME} from a peer. Founder at a seed-stage startup. "
                      "Interested in the concept but worried about cost and whether AI research "
                      "is credible enough for investor presentations."
                  ),
              },
          ],
      },
      "churned": {
          "label": "Churned Users",
          "personas": [
              {
                  "name": f"Former {BRAND_NAME} User — Price Churned",
                  "description": (
                      f"Used {BRAND_NAME} for 3 months, then cancelled citing cost. "
                      "Marketing coordinator at a small company. Found the tool useful but "
                      "couldn't justify the monthly cost for occasional use. Went back to "
                      "Google Forms and informal feedback."
                  ),
              },
              {
                  "name": f"Former {BRAND_NAME} User — Depth Churned",
                  "description": (
                      f"Used {BRAND_NAME} for 6 months at an enterprise company. Cancelled because "
                      "leadership didn't trust synthetic research for high-stakes decisions. "
                      "Felt the personas lacked nuance compared to real interviews. "
                      "Switched to a traditional research agency."
                  ),
              },
          ],
      },
  }
  ```

  ```javascript JavaScript theme={"dark"}
  import OpenAI from "openai";

  const MAVERA_API_KEY = process.env.MAVERA_API_KEY;
  const WORKSPACE_ID = process.env.MAVERA_WORKSPACE_ID;
  const BRAND_NAME = process.env.BRAND_NAME || "Acme";
  const BASE = "https://app.mavera.io/api/v1";
  const HEADERS = {
    Authorization: `Bearer ${MAVERA_API_KEY}`,
    "Content-Type": "application/json",
  };
  const mavera = new OpenAI({ apiKey: MAVERA_API_KEY, baseURL: BASE });

  const BRAND_CONTEXT = {
    name: BRAND_NAME,
    category: "AI-powered market research platform",
    value_prop: "replacing guesswork with persona-validated audience insights",
    competitors: ["Pollfish", "UserTesting", "Wynter", "SurveyMonkey"],
  };

  const SEGMENTS = {
    customers: {
      label: "Current Customers",
      personas: [
        {
          name: `${BRAND_NAME} Power User — Growth Marketer`,
          description:
            `Active ${BRAND_NAME} user for 6+ months. Uses focus groups and chat weekly. ` +
            "Growth marketer at a Series B startup. Loves the speed.",
        },
        {
          name: `${BRAND_NAME} Casual User — Content Manager`,
          description:
            `Uses ${BRAND_NAME} 2-3 times a month for content scoring. ` +
            "Content manager at a mid-market company. Might not renew if price increases.",
        },
        {
          name: `${BRAND_NAME} Champion — VP Marketing`,
          description:
            `Internally champions ${BRAND_NAME}. VP Marketing who got the team adopted. ` +
            "Would recommend to peers. NPS likely 9-10.",
        },
      ],
    },
    prospects: {
      label: "Prospects (Evaluating)",
      personas: [
        {
          name: `${BRAND_NAME} Prospect — Skeptical PMM`,
          description:
            `Aware of ${BRAND_NAME} but hasn't tried it. Product marketer at an enterprise company. ` +
            "Skeptical about synthetic audiences replacing real research.",
        },
        {
          name: `${BRAND_NAME} Prospect — Budget-Conscious Founder`,
          description:
            `Heard about ${BRAND_NAME} from a peer. Founder at a seed-stage startup. ` +
            "Worried about cost and credibility for investor presentations.",
        },
      ],
    },
    churned: {
      label: "Churned Users",
      personas: [
        {
          name: `Former ${BRAND_NAME} User — Price Churned`,
          description:
            `Used ${BRAND_NAME} for 3 months, then cancelled citing cost. ` +
            "Marketing coordinator at a small company. Went back to Google Forms.",
        },
        {
          name: `Former ${BRAND_NAME} User — Depth Churned`,
          description:
            `Used ${BRAND_NAME} for 6 months at an enterprise company. Cancelled because ` +
            "leadership didn't trust synthetic research for high-stakes decisions.",
        },
      ],
    },
  };
  ```
</CodeGroup>

***

### Stage 1 — Create Segment Personas

<CodeGroup>
  ```python Python theme={"dark"}
  def create_segment_personas() -> dict[str, list[str]]:
      """Create personas for all 3 segments. Returns {segment_key: [persona_ids]}."""
      segment_ids = {}

      for segment_key, segment in SEGMENTS.items():
          ids = []
          for persona in segment["personas"]:
              resp = requests.post(
                  f"{BASE}/personas",
                  headers=HEADERS,
                  json={
                      "name": persona["name"],
                      "description": persona["description"],
                      "workspace_id": WORKSPACE_ID,
                  },
              ).json()

              if "error" in resp:
                  raise Exception(f"Failed: {persona['name']}: {resp['error']['message']}")

              ids.append(resp["id"])
              print(f"✓ [{segment['label']}] {persona['name']} ({resp['id']})")

          segment_ids[segment_key] = ids

      total = sum(len(v) for v in segment_ids.values())
      print(f"\nCreated {total} personas across {len(segment_ids)} segments")
      return segment_ids
  ```

  ```javascript JavaScript theme={"dark"}
  async function createSegmentPersonas() {
    const segmentIds = {};

    for (const [segmentKey, segment] of Object.entries(SEGMENTS)) {
      const ids = [];
      for (const persona of segment.personas) {
        const resp = await fetch(`${BASE}/personas`, {
          method: "POST",
          headers: HEADERS,
          body: JSON.stringify({
            name: persona.name,
            description: persona.description,
            workspace_id: WORKSPACE_ID,
          }),
        }).then((r) => r.json());

        if (resp.error) throw new Error(`Failed: ${persona.name}: ${resp.error.message}`);
        ids.push(resp.id);
        console.log(`✓ [${segment.label}] ${persona.name} (${resp.id})`);
      }
      segmentIds[segmentKey] = ids;
    }

    return segmentIds;
  }
  ```
</CodeGroup>

***

### Stage 2 — Run 3 Focus Groups

Each segment gets its own focus group with the same 6-question battery.

<CodeGroup>
  ```python Python theme={"dark"}
  def build_question_battery() -> list[dict]:
      """Build the standard 6-question perception battery."""
      return [
          {
              "question": (
                  f"How likely are you to recommend {BRAND_NAME} to a colleague or peer? "
                  f"(0 = not at all likely, 10 = extremely likely)"
              ),
              "type": "NPS",
              "order": 1,
          },
          {
              "question": (
                  f"What 3 words or phrases come to mind when you think of {BRAND_NAME}? "
                  f"Explain why each word applies."
              ),
              "type": "OPEN_ENDED",
              "order": 2,
          },
          {
              "question": f"Rate {BRAND_NAME} on trustworthiness:",
              "type": "SEMANTIC_DIFFERENTIAL",
              "left_anchor": "Untrustworthy / unreliable",
              "right_anchor": "Trustworthy / dependable",
              "scale": 7,
              "order": 3,
          },
          {
              "question": f"Rate {BRAND_NAME} on innovation:",
              "type": "SEMANTIC_DIFFERENTIAL",
              "left_anchor": "Outdated / behind the curve",
              "right_anchor": "Innovative / cutting-edge",
              "scale": 7,
              "order": 4,
          },
          {
              "question": (
                  f"How well does {BRAND_NAME} deliver on its promise of "
                  f"'{BRAND_CONTEXT['value_prop']}'? Rate 1-10."
              ),
              "type": "LIKERT",
              "scale": 10,
              "order": 5,
          },
          {
              "question": (
                  f"What is the biggest risk of choosing {BRAND_NAME} over alternatives "
                  f"like {', '.join(BRAND_CONTEXT['competitors'][:3])}? "
                  f"What concerns would make you hesitate?"
              ),
              "type": "OPEN_ENDED",
              "order": 6,
          },
      ]


  def run_segment_focus_groups(segment_ids: dict) -> dict:
      """Launch one focus group per segment. Returns {segment_key: fg_response}."""
      questions = build_question_battery()
      focus_groups = {}

      for segment_key, persona_ids in segment_ids.items():
          label = SEGMENTS[segment_key]["label"]

          payload = {
              "name": f"Brand Perception Audit — {label}",
              "sample_size": 25,
              "persona_ids": persona_ids,
              "workspace_id": WORKSPACE_ID,
              "questions": questions,
          }

          resp = requests.post(
              f"{BASE}/focus-groups",
              headers=HEADERS,
              json=payload,
          ).json()

          if "error" in resp:
              raise Exception(f"Failed [{label}]: {resp['error']['message']}")

          focus_groups[segment_key] = resp
          print(f"✓ Focus group launched: {label} ({resp['id']})")

      return focus_groups


  def poll_all_focus_groups(focus_groups: dict, timeout_min: int = 15) -> dict:
      """Poll all focus groups until they complete."""
      results = {}
      pending = dict(focus_groups)

      for attempt in range(timeout_min * 6):
          for segment_key, fg in list(pending.items()):
              resp = requests.get(
                  f"{BASE}/focus-groups/{fg['id']}",
                  headers=HEADERS,
              ).json()

              if "error" in resp:
                  raise Exception(resp["error"]["message"])

              if resp.get("status") == "COMPLETED":
                  results[segment_key] = resp
                  del pending[segment_key]
                  label = SEGMENTS[segment_key]["label"]
                  print(f"✓ {label} completed")

              elif resp.get("status") == "FAILED":
                  raise Exception(f"Focus group {fg['id']} failed")

          if not pending:
              print(f"\nAll {len(results)} focus groups completed")
              return results

          time.sleep(10)

      raise TimeoutError(f"{len(pending)} focus groups did not complete")
  ```

  ```javascript JavaScript theme={"dark"}
  function buildQuestionBattery() {
    return [
      {
        question: `How likely are you to recommend ${BRAND_NAME} to a colleague? (0-10)`,
        type: "NPS", order: 1,
      },
      {
        question: `What 3 words come to mind when you think of ${BRAND_NAME}? Explain.`,
        type: "OPEN_ENDED", order: 2,
      },
      {
        question: `Rate ${BRAND_NAME} on trustworthiness:`,
        type: "SEMANTIC_DIFFERENTIAL",
        left_anchor: "Untrustworthy / unreliable",
        right_anchor: "Trustworthy / dependable",
        scale: 7, order: 3,
      },
      {
        question: `Rate ${BRAND_NAME} on innovation:`,
        type: "SEMANTIC_DIFFERENTIAL",
        left_anchor: "Outdated / behind the curve",
        right_anchor: "Innovative / cutting-edge",
        scale: 7, order: 4,
      },
      {
        question:
          `How well does ${BRAND_NAME} deliver on its promise of ` +
          `'${BRAND_CONTEXT.value_prop}'? Rate 1-10.`,
        type: "LIKERT", scale: 10, order: 5,
      },
      {
        question:
          `What is the biggest risk of choosing ${BRAND_NAME} over ` +
          `${BRAND_CONTEXT.competitors.slice(0, 3).join(", ")}?`,
        type: "OPEN_ENDED", order: 6,
      },
    ];
  }

  async function runSegmentFocusGroups(segmentIds) {
    const questions = buildQuestionBattery();
    const focusGroups = {};

    for (const [segmentKey, personaIds] of Object.entries(segmentIds)) {
      const label = SEGMENTS[segmentKey].label;
      const resp = await fetch(`${BASE}/focus-groups`, {
        method: "POST", headers: HEADERS,
        body: JSON.stringify({
          name: `Brand Perception Audit — ${label}`,
          sample_size: 25, persona_ids: personaIds,
          workspace_id: WORKSPACE_ID, questions,
        }),
      }).then((r) => r.json());

      if (resp.error) throw new Error(`Failed [${label}]: ${resp.error.message}`);
      focusGroups[segmentKey] = resp;
      console.log(`✓ Focus group launched: ${label} (${resp.id})`);
    }
    return focusGroups;
  }

  async function pollAllFocusGroups(focusGroups, timeoutMin = 15) {
    const results = {};
    const pending = { ...focusGroups };

    for (let i = 0; i < timeoutMin * 6; i++) {
      for (const [key, fg] of Object.entries(pending)) {
        const resp = await fetch(`${BASE}/focus-groups/${fg.id}`, {
          headers: HEADERS,
        }).then((r) => r.json());

        if (resp.error) throw new Error(resp.error.message);
        if (resp.status === "COMPLETED") {
          results[key] = resp;
          delete pending[key];
          console.log(`✓ ${SEGMENTS[key].label} completed`);
        }
      }
      if (Object.keys(pending).length === 0) return results;
      await new Promise((r) => setTimeout(r, 10000));
    }
    throw new Error("Focus groups timed out");
  }
  ```
</CodeGroup>

***

### Stage 3 — Cross-Segment Comparison

<CodeGroup>
  ```python Python theme={"dark"}
  def compare_segments(all_results: dict) -> dict:
      """Extract and compare key metrics across segments."""
      comparison = {}

      for segment_key, fg_results in all_results.items():
          label = SEGMENTS[segment_key]["label"]
          segment_data = {"label": label, "nps": None, "trust": None, "innovation": None, "promise_delivery": None, "word_associations": [], "perceived_risks": []}

          for result in fg_results.get("results", []):
              q_type = result.get("type")

              if q_type == "NPS":
                  segment_data["nps"] = {
                      "score": result.get("nps_score"),
                      "promoters": result.get("promoter_count", 0),
                      "passives": result.get("passive_count", 0),
                      "detractors": result.get("detractor_count", 0),
                      "summary": result.get("summary", ""),
                  }

              elif q_type == "SEMANTIC_DIFFERENTIAL":
                  question = result.get("question", "")
                  if "trustworthiness" in question.lower():
                      segment_data["trust"] = result.get("mean_score", 0)
                  elif "innovation" in question.lower():
                      segment_data["innovation"] = result.get("mean_score", 0)

              elif q_type == "LIKERT":
                  segment_data["promise_delivery"] = result.get("mean_score", 0)

              elif q_type == "OPEN_ENDED":
                  question = result.get("question", "")
                  if "3 words" in question.lower():
                      segment_data["word_associations"] = result.get("themes", [])
                  elif "risk" in question.lower():
                      segment_data["perceived_risks"] = result.get("themes", [])

          comparison[segment_key] = segment_data

      return comparison


  def print_comparison(comparison: dict):
      """Print a comparison table."""
      print("\n" + "=" * 70)
      print("CROSS-SEGMENT BRAND PERCEPTION COMPARISON")
      print("=" * 70)

      header = f"{'Metric':<25}"
      for data in comparison.values():
          header += f"{data['label']:<20}"
      print(header)
      print("-" * 70)

      # NPS
      row = f"{'NPS Score':<25}"
      for data in comparison.values():
          nps = data["nps"]["score"] if data["nps"] else "N/A"
          row += f"{nps:<20}"
      print(row)

      # Trust
      row = f"{'Trust (1-7)':<25}"
      for data in comparison.values():
          row += f"{data['trust'] or 'N/A':<20}"
      print(row)

      # Innovation
      row = f"{'Innovation (1-7)':<25}"
      for data in comparison.values():
          row += f"{data['innovation'] or 'N/A':<20}"
      print(row)

      # Promise delivery
      row = f"{'Promise Delivery (1-10)':<25}"
      for data in comparison.values():
          row += f"{data['promise_delivery'] or 'N/A':<20}"
      print(row)

      # Word associations
      print(f"\n{'Word Associations:':<25}")
      for data in comparison.values():
          words = ", ".join(data["word_associations"][:5]) if data["word_associations"] else "N/A"
          print(f"  {data['label']}: {words}")

      # Perceived risks
      print(f"\n{'Perceived Risks:':<25}")
      for data in comparison.values():
          risks = data["perceived_risks"][:3] if data["perceived_risks"] else ["N/A"]
          print(f"  {data['label']}:")
          for risk in risks:
              print(f"    • {risk}")
  ```

  ```javascript JavaScript theme={"dark"}
  function compareSegments(allResults) {
    const comparison = {};

    for (const [segmentKey, fgResults] of Object.entries(allResults)) {
      const label = SEGMENTS[segmentKey].label;
      const data = {
        label, nps: null, trust: null, innovation: null,
        promise_delivery: null, word_associations: [], perceived_risks: [],
      };

      for (const result of fgResults.results || []) {
        if (result.type === "NPS") {
          data.nps = {
            score: result.nps_score,
            promoters: result.promoter_count || 0,
            passives: result.passive_count || 0,
            detractors: result.detractor_count || 0,
          };
        } else if (result.type === "SEMANTIC_DIFFERENTIAL") {
          if (result.question?.toLowerCase().includes("trustworthiness"))
            data.trust = result.mean_score || 0;
          else if (result.question?.toLowerCase().includes("innovation"))
            data.innovation = result.mean_score || 0;
        } else if (result.type === "LIKERT") {
          data.promise_delivery = result.mean_score || 0;
        } else if (result.type === "OPEN_ENDED") {
          if (result.question?.toLowerCase().includes("3 words"))
            data.word_associations = result.themes || [];
          else if (result.question?.toLowerCase().includes("risk"))
            data.perceived_risks = result.themes || [];
        }
      }
      comparison[segmentKey] = data;
    }
    return comparison;
  }

  function printComparison(comparison) {
    console.log("\nCROSS-SEGMENT BRAND PERCEPTION COMPARISON");
    for (const [key, data] of Object.entries(comparison)) {
      console.log(`\n${data.label}:`);
      console.log(`  NPS: ${data.nps?.score ?? "N/A"}`);
      console.log(`  Trust: ${data.trust ?? "N/A"}/7`);
      console.log(`  Innovation: ${data.innovation ?? "N/A"}/7`);
      console.log(`  Promise Delivery: ${data.promise_delivery ?? "N/A"}/10`);
    }
  }
  ```
</CodeGroup>

***

### Stage 4 — Generate 360-Degree Report

<CodeGroup>
  ```python Python theme={"dark"}
  REPORT_SCHEMA = {"type": "json_schema", "json_schema": {
      "name": "brand_perception_report", "strict": True,
      "schema": {
          "type": "object",
          "properties": {
              "executive_summary": {"type": "string"},
              "overall_brand_health": {"type": "string", "description": "Strong, Moderate, Weak, or Critical"},
              "nps_comparison": {
                  "type": "object",
                  "properties": {
                      "customers": {"type": "number"},
                      "prospects": {"type": "number"},
                      "churned": {"type": "number"},
                      "gap_analysis": {"type": "string"},
                  },
                  "required": ["customers", "prospects", "churned", "gap_analysis"],
              },
              "perception_gaps": {
                  "type": "array",
                  "items": {
                      "type": "object",
                      "properties": {
                          "dimension": {"type": "string"},
                          "gap_description": {"type": "string"},
                          "severity": {"type": "string"},
                          "recommendation": {"type": "string"},
                      },
                      "required": ["dimension", "gap_description", "severity", "recommendation"],
                  },
              },
              "brand_strengths": {"type": "array", "items": {"type": "string"}},
              "brand_weaknesses": {"type": "array", "items": {"type": "string"}},
              "churn_drivers": {"type": "array", "items": {"type": "string"}},
              "prospect_barriers": {"type": "array", "items": {"type": "string"}},
              "priority_actions": {
                  "type": "array",
                  "items": {
                      "type": "object",
                      "properties": {
                          "action": {"type": "string"},
                          "impact": {"type": "string"},
                          "effort": {"type": "string"},
                          "timeline": {"type": "string"},
                      },
                      "required": ["action", "impact", "effort", "timeline"],
                  },
              },
          },
          "required": [
              "executive_summary", "overall_brand_health", "nps_comparison",
              "perception_gaps", "brand_strengths", "brand_weaknesses",
              "churn_drivers", "prospect_barriers", "priority_actions",
          ],
      },
  }}


  def generate_perception_report(comparison: dict) -> dict:
      """Synthesize a 360-degree brand perception report."""
      prompt = (
          f"You are a brand strategist. Analyze this 360-degree brand perception data "
          f"for {BRAND_NAME} ({BRAND_CONTEXT['category']}) and produce a comprehensive report.\n\n"
          f"Value proposition: '{BRAND_CONTEXT['value_prop']}'\n"
          f"Competitors: {', '.join(BRAND_CONTEXT['competitors'])}\n\n"
          f"## Cross-Segment Data\n{json.dumps(comparison, indent=2)}\n\n"
          "Focus on:\n"
          "1. How perception differs across customers, prospects, and churned users\n"
          "2. The biggest perception gaps and their business impact\n"
          "3. What's driving churn from a brand perception standpoint\n"
          "4. What's blocking prospect conversion\n"
          "5. Prioritized actions to improve brand health"
      )

      resp = mavera.responses.create(
          model="mavera-1",
          input=[{"role": "user", "content": prompt}],
          extra_body={"response_format": REPORT_SCHEMA},
      )

      return json.loads(resp.output[0].content[0].text)
  ```

  ```javascript JavaScript theme={"dark"}
  const REPORT_SCHEMA = { type: "json_schema", json_schema: {
    name: "brand_perception_report", strict: true,
    schema: {
      type: "object",
      properties: {
        executive_summary: { type: "string" },
        overall_brand_health: { type: "string" },
        nps_comparison: {
          type: "object",
          properties: {
            customers: { type: "number" }, prospects: { type: "number" },
            churned: { type: "number" }, gap_analysis: { type: "string" },
          },
          required: ["customers", "prospects", "churned", "gap_analysis"],
        },
        perception_gaps: {
          type: "array",
          items: {
            type: "object",
            properties: {
              dimension: { type: "string" }, gap_description: { type: "string" },
              severity: { type: "string" }, recommendation: { type: "string" },
            },
            required: ["dimension", "gap_description", "severity", "recommendation"],
          },
        },
        brand_strengths: { type: "array", items: { type: "string" } },
        brand_weaknesses: { type: "array", items: { type: "string" } },
        churn_drivers: { type: "array", items: { type: "string" } },
        prospect_barriers: { type: "array", items: { type: "string" } },
        priority_actions: {
          type: "array",
          items: {
            type: "object",
            properties: {
              action: { type: "string" }, impact: { type: "string" },
              effort: { type: "string" }, timeline: { type: "string" },
            },
            required: ["action", "impact", "effort", "timeline"],
          },
        },
      },
      required: [
        "executive_summary", "overall_brand_health", "nps_comparison",
        "perception_gaps", "brand_strengths", "brand_weaknesses",
        "churn_drivers", "prospect_barriers", "priority_actions",
      ],
    },
  }};

  async function generatePerceptionReport(comparison) {
    const prompt =
      `You are a brand strategist. Analyze this 360-degree brand perception data ` +
      `for ${BRAND_NAME} (${BRAND_CONTEXT.category}).\n\n` +
      `Value proposition: '${BRAND_CONTEXT.value_prop}'\n\n` +
      `## Cross-Segment Data\n${JSON.stringify(comparison, null, 2)}\n\n` +
      "Focus on perception gaps, churn drivers, prospect barriers, and prioritized actions.";

    const resp = await mavera.responses.create({
      model: "mavera-1",
      input: [{ role: "user", content: prompt }],
      response_format: REPORT_SCHEMA,
    });

    return JSON.parse(resp.output[0].content[0].text);
  }
  ```
</CodeGroup>

***

### Running the Full Audit

<CodeGroup>
  ```python Python theme={"dark"}
  def run_brand_audit():
      print("=" * 60)
      print(f"BRAND PERCEPTION AUDIT — {BRAND_NAME}")
      print("=" * 60)

      # Stage 1: Create personas
      print("\n--- Stage 1: Creating Segment Personas ---")
      segment_ids = create_segment_personas()

      # Stage 2: Run focus groups
      print("\n--- Stage 2: Running 3 Focus Groups ---")
      focus_groups = run_segment_focus_groups(segment_ids)
      all_results = poll_all_focus_groups(focus_groups)

      # Stage 3: Compare
      print("\n--- Stage 3: Cross-Segment Comparison ---")
      comparison = compare_segments(all_results)
      print_comparison(comparison)

      # Stage 4: Report
      print("\n--- Stage 4: Generating 360° Report ---")
      report = generate_perception_report(comparison)

      print(f"\nBrand Health: {report['overall_brand_health']}")
      print(f"NPS — Customers: {report['nps_comparison']['customers']}, "
            f"Prospects: {report['nps_comparison']['prospects']}, "
            f"Churned: {report['nps_comparison']['churned']}")

      print(f"\nStrengths:")
      for s in report["brand_strengths"]:
          print(f"  + {s}")
      print(f"\nWeaknesses:")
      for w in report["brand_weaknesses"]:
          print(f"  - {w}")

      print(f"\nPriority Actions:")
      for action in report["priority_actions"]:
          print(f"  [{action['impact']} impact, {action['effort']} effort] {action['action']}")

      # Save
      output = {"comparison": comparison, "report": report}
      with open("brand_perception_audit.json", "w") as f:
          json.dump(output, f, indent=2)

      print("\n✓ Saved brand_perception_audit.json")
      return report


  if __name__ == "__main__":
      run_brand_audit()
  ```

  ```javascript JavaScript theme={"dark"}
  import fs from "fs";

  async function runBrandAudit() {
    console.log(`BRAND PERCEPTION AUDIT — ${BRAND_NAME}`);

    const segmentIds = await createSegmentPersonas();
    const focusGroups = await runSegmentFocusGroups(segmentIds);
    const allResults = await pollAllFocusGroups(focusGroups);

    const comparison = compareSegments(allResults);
    printComparison(comparison);

    const report = await generatePerceptionReport(comparison);

    console.log(`\nBrand Health: ${report.overall_brand_health}`);
    console.log(`NPS — Customers: ${report.nps_comparison.customers}, ` +
      `Prospects: ${report.nps_comparison.prospects}, Churned: ${report.nps_comparison.churned}`);

    fs.writeFileSync("brand_perception_audit.json", JSON.stringify({ comparison, report }, null, 2));
    console.log("\n✓ Saved brand_perception_audit.json");
    return report;
  }

  runBrandAudit();
  ```
</CodeGroup>

***

## Example Output

```json theme={"dark"}
{
  "executive_summary": "Acme has strong brand health among active customers (NPS +42) but significant perception gaps with prospects (NPS -5) and churned users (NPS -28). Trust and innovation scores are high with customers but drop sharply in the churned segment. The primary churn driver is perceived lack of depth for high-stakes decisions. The primary prospect barrier is skepticism about synthetic vs. real research.",
  "overall_brand_health": "Moderate",
  "nps_comparison": {
    "customers": 42,
    "prospects": -5,
    "churned": -28,
    "gap_analysis": "A 70-point spread between customers and churned users signals a post-purchase experience problem, not an acquisition problem. Prospects are nearly neutral — they need proof, not persuasion."
  },
  "perception_gaps": [
    {
      "dimension": "Research Credibility",
      "gap_description": "Customers rate trust at 5.8/7, but churned users rate it at 2.9/7. Churned users question whether synthetic research is rigorous enough for executive decisions.",
      "severity": "High",
      "recommendation": "Publish validation studies comparing Mavera results to traditional research outcomes. Add confidence intervals to focus group outputs."
    }
  ],
  "brand_strengths": [
    "Speed — all segments acknowledge faster time-to-insight",
    "Innovation — perceived as cutting-edge by customers and prospects",
    "Ease of use — customers cite low learning curve"
  ],
  "brand_weaknesses": [
    "Research depth questioned for high-stakes decisions",
    "Price-value perception weak for occasional users",
    "Limited brand awareness among prospects"
  ],
  "churn_drivers": [
    "Leadership doesn't trust synthetic research for board-level decisions",
    "Cost not justified for teams using it less than weekly",
    "Missing integrations with existing research workflows"
  ],
  "prospect_barriers": [
    "Skepticism about AI-generated audience data accuracy",
    "No peer case studies or social proof from their industry",
    "Unclear how results compare to real focus groups"
  ],
  "priority_actions": [
    {
      "action": "Create 3 case studies showing Mavera vs traditional research correlation",
      "impact": "High",
      "effort": "Medium",
      "timeline": "6 weeks"
    },
    {
      "action": "Launch a free tier or trial to reduce prospect risk perception",
      "impact": "High",
      "effort": "Low",
      "timeline": "2 weeks"
    }
  ]
}
```

***

## Variations

<AccordionGroup>
  <Accordion title="Track perception over time">
    Run the same audit quarterly. Store results and diff:

    ```python theme={"dark"}
    q1 = json.load(open("audits/q1.json"))
    q2 = json.load(open("audits/q2.json"))

    for segment in ["customers", "prospects", "churned"]:
        delta_nps = q2["comparison"][segment]["nps"]["score"] - q1["comparison"][segment]["nps"]["score"]
        print(f"{segment}: NPS {'+' if delta_nps > 0 else ''}{delta_nps}")
    ```
  </Accordion>

  <Accordion title="Add competitor perception">
    Run the same battery for a competitor's brand using your personas:

    ```python theme={"dark"}
    COMPETITOR_NAME = "CompetitorX"
    # Replace BRAND_NAME in question battery
    competitor_questions = build_question_battery()
    for q in competitor_questions:
        q["question"] = q["question"].replace(BRAND_NAME, COMPETITOR_NAME)
    ```
  </Accordion>

  <Accordion title="Segment by industry vertical">
    Instead of customer/prospect/churned, segment by industry:

    ```python theme={"dark"}
    SEGMENTS = {
        "saas": {"label": "SaaS Companies", "personas": [...]},
        "agency": {"label": "Marketing Agencies", "personas": [...]},
        "enterprise": {"label": "Enterprise", "personas": [...]},
    }
    ```
  </Accordion>

  <Accordion title="Include employee perception">
    Add an internal segment to see if employees and customers are aligned:

    ```python theme={"dark"}
    SEGMENTS["employees"] = {
        "label": "Internal Team",
        "personas": [
            {"name": "Sales Rep", "description": "Frontline seller..."},
            {"name": "Customer Success", "description": "Manages renewals..."},
            {"name": "Product Manager", "description": "Builds the roadmap..."},
        ],
    }
    ```
  </Accordion>
</AccordionGroup>

***

## Credits Estimate

| Stage                                | Typical Cost          | Notes                    |
| ------------------------------------ | --------------------- | ------------------------ |
| Create 7 personas                    | 0                     | Persona creation is free |
| Focus Group — Customers (N=25, 6 Qs) | 100–200 credits       |                          |
| Focus Group — Prospects (N=25, 6 Qs) | 100–200 credits       |                          |
| Focus Group — Churned (N=25, 6 Qs)   | 100–200 credits       |                          |
| Perception report (1 chat call)      | 5–15 credits          | Single structured output |
| **Total**                            | **\~305–615 credits** |                          |

<Tip>
  The three focus groups run in parallel on the server — total wall-clock time is the longest single group, not the sum. Expect 5-10 minutes for all three.
</Tip>

***

## See Also

<CardGroup cols={2}>
  <Card title="Focus Groups" icon="users" href="/features/focus-groups">
    NPS, Semantic Differential, and all question types
  </Card>

  <Card title="Positioning Workshop" icon="bullseye" href="/playbooks/positioning-workshop">
    Validate positioning after measuring current perception
  </Card>

  <Card title="Pricing Research" icon="tags" href="/playbooks/pricing-research">
    Test pricing alongside perception
  </Card>

  <Card title="News-Triggered Research" icon="bolt" href="/playbooks/news-triggered-research">
    Monitor how external events shift brand perception
  </Card>

  <Card title="Generational Content Testing" icon="people-group" href="/playbooks/generational-content-testing">
    Test perception across age cohorts
  </Card>

  <Card title="Annual Planning Kickoff" icon="calendar" href="/playbooks/annual-planning-kickoff">
    Feed perception data into annual planning
  </Card>
</CardGroup>
