# nps-analyzer

Customer-feedback and experience-analytics pack for survey score data: compute Net Promoter Score (NPS) from 0-10 recommend ratings with promoter/passive/detractor breakdown, CSAT (customer...


Customer-feedback & experience-analytics adapter pack. Turns raw survey score arrays into the
metrics a CX / Customer Success team actually reports — NPS, CSAT, CES, distributions, cohort
comparison, industry benchmarking, and verbatim theme mining.

Intelligent microservice: every tool has a deterministic core that runs fully **offline** with no
model. `themes` additionally tries an optional LLM to cluster comments into named themes and
**silently falls back** to the keyword heuristic when no model is reachable (`mode: 'heuristic' | 'llm'`).

## Tools

| Tool | In → Out |
|---|---|
| `nps` | `{ scores }` (0-10) → Net Promoter Score, promoter/passive/detractor counts + %, average, rating band |
| `csat` | `{ scores }` (1-5 or 1-10) → CSAT % (top-box), average, normalized 0-100 |
| `ces` | `{ scores }` (1-5 or 1-7) → Customer Effort Score, ease %, high-effort %, interpretation |
| `distribution` | `{ scores }` → histogram buckets + min/max/mean/median/stdDev + most common range |
| `segment` | `{ segments }` (map or array of cohorts) → NPS per cohort, ranked, spread, weighted overall |
| `benchmark` | `{ score, metric, industry }` → industry-band rating + gap-to-good + percentile hint |
| `themes` | `{ verbatims }` (comments) → keyword themes, mentions, tone, sentiment tally (+ optional LLM `namedThemes`) |

## Usage

```js
import pack from './index.js';

pack.adapters.nps({ scores: [10, 9, 8, 7, 6, 10, 9, 3] });
// → { nps: 25, responses: 8, promoters: 3, passives: 2, detractors: 3, ..., rating: 'good' }

pack.adapters.csat({ scores: [5, 4, 5, 3, 4], options: { scale: 5 } });
// → { csat: 80, scale: 5, averageScore: 4.2, normalizedScore: 84, ... }

pack.adapters.segment({ segments: { enterprise: [10, 9, 9], smb: [7, 6, 5] } });
// → ranked NPS table + spread + weightedOverallNps

await pack.adapters.themes({ verbatims: ['Support was slow and confusing', 'Love the fast UI'] });
// → { mode: 'heuristic', themes: [...], sentiment: {...} }  (mode: 'llm' if a model is reachable)
```

## Input coercion

`scores` accepts an array, a JSON string, or a comma / newline / semicolon separated string. Non-numeric
entries are dropped. `verbatims` accepts an array or a newline-joined block. All tools validate and throw
`TypeError` with a clear message on empty / non-numeric input.

## DRY boundaries

- Survey-**score** analytics only (NPS/CSAT/CES formulae + CX benchmarking). Generic descriptive
  statistics (mean, percentile, z-score, anomaly) belong to `statistics` / `numbers` — not duplicated here.
- The theme miner is a small self-contained CX keyword tally, **not** a general NLP engine; full
  tokenizing / sentiment models live in `nlp`.
- No cross-pack imports except `../_shared/llm.js`. Pure ESM, Node built-ins, zero npm deps.


---
Source: shared/engines/adapters/domain/nps-analyzer/README.md
Canonical: https://docs.leumas.tech/p/adapters/domain/nps-analyzer
