> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getthread.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Analytics & QA

> How a service manager measures the desk in Thread: Magic Analytics dashboards, live View insights, CSAT surveys, and a weekly QA coaching loop.

export const MarkComplete = ({id, signalDone = false}) => {
  const KEY = "thread-onboarding-completed";
  const read = () => {
    try {
      return JSON.parse(localStorage.getItem(KEY) || "[]");
    } catch (e) {
      return [];
    }
  };
  const [localDone, setLocalDone] = useState(false);
  const done = signalDone || localDone;
  useEffect(() => {
    const sync = () => setLocalDone(read().includes(id));
    sync();
    window.addEventListener("thread-onboarding-updated", sync);
    return () => window.removeEventListener("thread-onboarding-updated", sync);
  }, [id]);
  const toggle = () => {
    if (signalDone) return;
    const list = read();
    const next = list.includes(id) ? list.filter(x => x !== id) : [...list, id];
    try {
      localStorage.setItem(KEY, JSON.stringify(next));
    } catch (e) {}
    setLocalDone(next.includes(id));
    window.dispatchEvent(new Event("thread-onboarding-updated"));
  };
  return <button onClick={toggle} style={{
    width: "100%",
    padding: "0.7rem 1rem",
    marginTop: "1.5rem",
    borderRadius: "8px",
    border: "1px solid " + (done ? "#00B398" : "rgba(128,128,128,0.35)"),
    background: done ? "rgba(0,179,152,0.12)" : "transparent",
    color: done ? "#00B398" : "inherit",
    fontWeight: 600,
    fontSize: "0.95rem",
    cursor: "pointer",
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
    gap: "0.5rem"
  }}>
      <span aria-hidden="true">{done ? "✓" : "○"}</span>
      {done ? "Completed" : "Mark as complete"}
    </button>;
};

export const ByRoleProgress = () => {
  useEffect(() => {
    const KEY = "thread-onboarding-completed";
    const TEAL = "#00B398";
    const BASE = "/start-here/roles/";
    const DONE_ICON = '<svg class="thread-rc-doneicon size-4" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#00B398" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">' + '<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/>' + '<polyline points="22 4 12 14.01 9 11.01"/></svg>';
    const COURSES = [{
      slug: "technician",
      steps: ["why-thread", "get-around-inbox", "day-one-setup", "daily-workflows", "ai-toolkit", "notifications-and-customers"]
    }, {
      slug: "dispatcher",
      steps: ["why-dispatch-in-thread", "read-the-board", "assign-and-schedule", "ai-for-dispatch"]
    }, {
      slug: "service-ops-manager",
      steps: ["set-up-the-desk", "sla-and-dispatch", "analytics-and-qa", "roll-out-and-adopt"]
    }, {
      slug: "csm-account-manager",
      steps: ["client-intelligence-and-health", "qbrs-and-reporting", "retention-and-expansion"]
    }, {
      slug: "security-compliance-owner",
      steps: ["security-work-in-thread", "data-and-compliance", "security-runbooks"]
    }, {
      slug: "sales-business-development",
      steps: ["the-ai-service-pitch", "quote-and-handoff"]
    }, {
      slug: "msp-owner-leadership",
      steps: ["the-rollout", "outcomes-and-analytics", "scale-ai-service"]
    }, {
      slug: "automation-engineer",
      steps: ["flows-and-intents", "thread-mcp-and-api", "build-with-super-magic"]
    }];
    const COURSE_SLUGS = new Set(COURSES.map(c => c.slug));
    const readLocal = () => {
      try {
        return JSON.parse(localStorage.getItem(KEY) || "[]");
      } catch (e) {
        return [];
      }
    };
    const isDone = (done, id) => done.includes(id);
    const decorate = () => {
      const done = readLocal();
      const scope = document.getElementById("sidebar-content") || document;
      const links = [...scope.querySelectorAll('a[href*="' + BASE + '"]')].filter(a => !a.closest("main"));
      links.forEach(a => {
        const m = (a.getAttribute("href") || "").match(/\/start-here\/roles\/([^/?#]+)\/([^/?#]+)/);
        if (!m) return;
        if (!COURSE_SLUGS.has(m[1])) return;
        const id = m[1] + "/" + m[2];
        const d = isDone(done, id);
        const has = a.querySelector(".thread-rc-check");
        if (d && !has) {
          const s = document.createElement("span");
          s.className = "thread-rc-check";
          s.textContent = "✓ ";
          s.style.color = TEAL;
          s.style.fontWeight = "700";
          a.insertBefore(s, a.firstChild);
        } else if (!d && has) {
          has.remove();
        }
      });
      COURSES.forEach(course => {
        const li = scope.querySelector('li[id="' + BASE + course.slug + '"]');
        if (!li) return;
        const row = li.querySelector(":scope > button") || li.querySelector(":scope > a") || li.firstElementChild;
        if (!row) return;
        const nameSpan = [...row.querySelectorAll("span")].find(s => s.textContent.trim() && !s.classList.contains("thread-rc-coursecheck"));
        if (!nameSpan) return;
        const allDone = course.steps.length > 0 && course.steps.every(s => isDone(done, course.slug + "/" + s));
        const has = nameSpan.querySelector(".thread-rc-coursecheck");
        if (allDone && !has) {
          const s = document.createElement("span");
          s.className = "thread-rc-coursecheck";
          s.setAttribute("aria-hidden", "true");
          s.style.display = "inline-flex";
          s.style.alignItems = "center";
          s.style.verticalAlign = "-0.2em";
          s.style.marginRight = "0.35em";
          s.innerHTML = DONE_ICON;
          nameSpan.insertBefore(s, nameSpan.firstChild);
        } else if (!allDone && has) {
          has.remove();
        }
      });
    };
    decorate();
    const iv = setInterval(decorate, 600);
    window.addEventListener("thread-onboarding-updated", decorate);
    window.addEventListener("storage", decorate);
    return () => {
      clearInterval(iv);
      window.removeEventListener("thread-onboarding-updated", decorate);
      window.removeEventListener("storage", decorate);
    };
  }, []);
  return null;
};

<ByRoleProgress />

You can't run a desk you can't see. This lesson is about visibility and the loop that acts on it: **Magic Analytics** for the trends, **View insights** for the live picture, **CSAT** for the customer's verdict, and a repeatable **QA pass** that turns all of it into coaching instead of guesswork.

## Read the desk with Magic Analytics

[Magic Analytics](/analytics/getting-started-with-magic-analytics) is your reporting layer — volume, response and resolution times, XLA attainment, sentiment, and AI impact, across the whole desk. It's where you answer "how are we doing?" with a number instead of a hunch.

Spend your first session getting oriented: how dashboards are laid out, how to filter by team and date range, and how to read the trend lines. The [getting-started guide](/analytics/getting-started-with-magic-analytics) walks the fundamentals so you're not guessing at what a metric means.

The questions a service manager brings to it every week:

* **Are we keeping our promises?** XLA response and resolution attainment, and where breaches cluster.
* **Where's the time going?** Volume by client, board, and category — and what's trending up.
* **Who's carrying what?** Load and throughput by team and technician, so you can rebalance before someone burns out.
* **Is AI pulling its weight?** Triage Agent deflection and assistive-AI usage, so you can see automation's real dent in the queue.

<Tip>
  Don't try to watch every metric. Pick three or four that map to your current goals — say XLA attainment, reopen rate, and CSAT — and track those consistently. A few numbers you actually act on beat a dashboard you admire and ignore.
</Tip>

### Explore beyond the defaults

Once the standard dashboards are familiar, [the topics you can explore](/analytics/topics-you-can-explore) shows the fuller range — the dimensions and questions Magic Analytics can answer beyond the out-of-the-box views. Reach for it when a specific question comes up ("which clients drive our after-hours volume?", "what's our first-contact resolution by pod?") that the default dashboards don't answer head-on.

## Watch the live picture with View insights

Magic Analytics is the trend over time; [View insights](/inbox/views-and-insights) are the pulse right now. Every View carries live counts and signals for its slice of the queue, so your operational Views double as a real-time readout.

Use the two together:

| Question                                             | Where to look                                                     |
| ---------------------------------------------------- | ----------------------------------------------------------------- |
| "Is the desk about to fall behind *today*?"          | View insights — unassigned counts, breaching-soon, aging tickets. |
| "Is the desk trending better or worse *this month*?" | Magic Analytics — attainment, volume, and sentiment over time.    |

Keep your **unassigned** and **breaching-soon** Views in front of you during the day; lean on Magic Analytics when you plan the week and prep coaching.

## Close the loop with CSAT

Internal metrics tell you how the desk ran; CSAT tells you how it *felt* to the customer. A [CSAT survey](/inbox/how-to-setup-a-csat-survey) fires after resolution and captures the client's rating and comments, feeding satisfaction trends back into your analytics.

Set it up early — it's low-effort and it's the outcome your clients actually judge you on. Then work it as signal:

* **Watch the trend, not just the average.** A slipping CSAT line is an early warning long before it shows up in churn.
* **Read the low scores individually.** A detractor comment is the most specific coaching material you'll get all week.
* **Tie it to sentiment.** Magic Sentiment flags tone dips mid-ticket; CSAT confirms the outcome. Together they tell you which tickets to review.

<Note>
  CSAT and sentiment are inputs to QA, not a scoreboard to wave at the team. Use a bad score to find the ticket worth reviewing — then coach on what happened in it, not on the number.
</Note>

## Run a repeatable QA loop

Analytics point you at *what* to look at; QA is *how* you improve it. Make it a standing weekly habit rather than a reaction to a blow-up:

<Steps>
  <Step title="Sample the right tickets">
    Don't review at random. Pull from where the signal is — reopened tickets, low CSAT, breached XLAs, and a few standard closures for baseline. The [Weekly QA Digest](/skill-library/qa-and-closure/weekly-qa-digest) assembles this for you.
  </Step>

  <Step title="Score against one rubric">
    Run [Ticket QA Review](/skill-library/qa-and-closure/ticket-qa-review) so every ticket is judged on the same criteria — notes, communication, closure quality — instead of your mood that day. Consistency is what makes QA fair.
  </Step>

  <Step title="Grade the board's hygiene">
    Use [Queue Hygiene Score](/skill-library/qa-and-closure/queue-hygiene-score) to catch the systemic stuff — stale statuses, missing time entries, tickets parked with no next step — that per-ticket review misses.
  </Step>

  <Step title="Coach from the data">
    Bring the QA findings and a [Tech Performance Review](/skill-library/reporting-and-analytics/tech-performance-review) into each one-on-one. Specific, grounded, same rubric for everyone — that's coaching that lands and doesn't feel like gotcha.
  </Step>
</Steps>

<MarkComplete id="service-ops-manager/analytics-and-qa" />

## Next

You can see the desk and you're improving it. Last piece: getting Thread fully adopted across the team so all of this compounds.

<Card title="Roll out & drive adoption" icon="rocket" href="/start-here/roles/service-ops-manager/roll-out-and-adopt">
  Change management, enablement, and the rituals that make adoption stick.
</Card>


## Related topics

- [XLAs & dispatch](/start-here/roles/service-ops-manager/sla-and-dispatch.md)
- [Service & Ops Manager](/start-here/roles/service-ops-manager.md)
- [Ticket QA Review](/skill-library/qa-and-closure/ticket-qa-review.md)
