NPS Survey Widget — Free HTML CSS JS Snippet
NPS Survey Widget · Cards · Plain HTML, CSS & JS · Live preview
What's included
Features
About this UI Snippet
NPS Survey Widget — 0–10 Score Scale, Contextual Follow-Up & Thank-You State

A Net Promoter Score (NPS) survey widget is one of the most commonly used customer feedback instruments in SaaS and e-commerce — alongside the poll widget and the inline helpful feedback widget. The NPS question — "How likely are you to recommend us to a friend?" — classifies respondents as detractors (0–6), passives (7–8), or promoters (9–10), and the follow-up question is tailored to each group for maximum qualitative insight. This snippet provides a complete, polished three-screen NPS widget: the scoring scale, a contextual follow-up, and a thank-you screen.
The NPS classification model
The industry-standard NPS scale runs from 0 to 10. Scores 0–6 are detractors (dissatisfied customers who may churn or leave negative reviews), 7–8 are passives (satisfied but not enthusiastic), and 9–10 are promoters (loyal advocates). The NPS score itself is computed as (promoters% − detractors%). The widget uses a getType() function to classify any selected score into one of the three groups, which then drives the follow-up question and the colour coding.
Dynamic follow-up questions
Each respondent segment gets a different qualitative follow-up question: detractors are asked what would improve their experience, passives what would make them more likely to recommend, and promoters what they love most. This three-way targeting yields far richer qualitative data than a single fixed question and shows respondents that the product team actually read their segment context.
The colour system
Selected score buttons animate to a segment colour: red for detractors, amber for passives, green for promoters — for a stars-based rating instead of a 0–10 scale, see the star rating. This visual feedback confirms the selection and immediately communicates which zone the score falls in, making the three-group model intuitive for users who have not heard of NPS.
Three-screen flow
The widget uses three display-toggled screens in one card container: the score screen, the comment screen (which shows the score recap and tailored question), and the thank-you screen. A brief timeout after score selection makes the transition feel intentional rather than abrupt. The comment screen shows a recap badge so users are reminded of their score as they write.
Skip option
The comment screen offers a Skip link so users who do not want to write a comment can still complete the survey. Forcing a comment reduces completion rates significantly; the skip respects user time while still collecting the numeric score.
Production integration
The submit() function is the single place to call your feedback API with { score, comment }, making wiring straightforward. In a real product the widget is typically shown once per user per period (tracked in localStorage or a backend flag) and submitted to an analytics or CRM endpoint.
Build with AI
Build, Understand, Optimize, and Extend It With AI
Rather than tracing the classification logic by hand, paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain exactly how getType() and the followUpMap/colorMap objects work together so a single selected score drives three different downstream things (the follow-up question, the highlight color, and the recap label) from one classification call. The same assistant can help optimize it, for instance asking whether rebuilding every button's background inline on each selectScore() call could be replaced with a class-based approach for easier theming, or whether the 350ms setTimeout delay before showing the comment screen is the right pacing for the transition to feel intentional rather than laggy. It's also useful for extending the widget: ask it to add a required-vs-optional comment rule based on the detractor/passive/promoter type, store the numeric score and comment locally so a returning user within the same session doesn't get re-surveyed, or compute and display an aggregate NPS score across multiple stored responses. Treat the code less like a finished artifact and more like a starting point for a conversation.
Prompt to recreate it
Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:
Build an "NPS (Net Promoter Score) survey widget" in plain HTML, CSS, and JavaScript with a three-screen flow — no survey library.
Requirements:
- A first screen showing the classic 0-to-10 recommendation question with eleven equally-sized clickable number buttons in a row, plus low/high scale labels beneath them.
- Classify any clicked score into exactly one of three groups using simple range checks: 0-6 is "detractor", 7-8 is "passive", 9-10 is "promoter" — implement this as one small reusable classification function, not inline conditionals scattered through the code.
- Clicking a number must visually highlight only that button in a color unique to its classified group (a distinct color for detractor, passive, and promoter), lifting it slightly, and after a short delay automatically transition to a second screen.
- The second screen must show a recap of the selected score (the number in its group color) plus a follow-up question whose actual text is different depending on which of the three groups the score fell into — pull the correct question from a lookup keyed by the group name, not a chain of if/else per score.
- The second screen must include a comment textarea plus both a "Submit" button (which reads the textarea's value) and a "Skip" button (which submits with no comment) — both must lead to the same third confirmation screen.
- The third screen is a static thank-you confirmation. Structure the three screens as three sibling containers with only one visible at a time (toggled, not destroyed/recreated), and leave a clear comment showing exactly where a real API call would send the score and comment.Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.
Step by step
How to Use
- 1Click a scoreClick any number from 0 to 10. The selected number highlights in red, amber, or green based on the detractor/passive/promoter classification.
- 2Answer the follow-upThe widget shows a question tailored to your score group: improvement for detractors, likelihood for passives, love for promoters.
- 3Submit or skipType a comment and click Submit, or click Skip to submit just the numeric score. The thank-you screen confirms the response.
- 4Wire to your APIIn the submit() function, POST { score, comment } to your feedback endpoint. Store the score with a userId and timestamp for NPS calculation.
- 5Control when it appearsShow the widget after a trigger (a completed purchase, a milestone, or a time-based rule). Track shown/responded in localStorage or your backend to avoid surveying the same user repeatedly.
- 6Export for your frameworkClick "React" for a component with score state and screen management in useState. Click "Vue" for a Vue 3 SFC with reactive state.
Real-world uses
Common Use Cases
Got questions?
Frequently Asked Questions
NPS = (percentage of promoters) − (percentage of detractors). Passives are excluded from the calculation but tracked separately because they are at risk of moving to either group. To compute it: NPS = (count of 9–10 scores / total responses × 100) − (count of 0–6 scores / total responses × 100). The result is a number between −100 and +100, where anything above 0 is net-positive and above 50 is considered excellent.
A single fixed follow-up question works poorly across all three segments. Detractors have a different problem than promoters — asking a happy promoter "what would improve your experience?" is a misfire that feels tone-deaf. Tailored questions surface the most relevant qualitative data from each group: detractor responses drive the support and retention queue, passive responses inform feature investment, and promoter responses generate testimonial and referral content.
Store a flag in localStorage (e.g., nps_submitted: true and nps_shown_at: timestamp) after the survey is shown or completed. On load, check these values — if the user has already responded, never show it again; if they dismissed it, enforce a cooldown of 30–90 days before showing again. For higher-precision control use a backend flag tied to the user record so the suppression survives device changes.
Store score (number|null) and screen ("score" | "comment" | "thank") in useState. Build the scale as an array .map(), setting score in state on click and transitioning screen after a setTimeout. Derive the NPS type and colours from the score value. The comment screen reads score from state to show the recap and select the follow-up question. submit() posts to your API and sets screen to "thank". For the Tailwind version, click "Tailwind" to get the same markup with utility classes instead of a scoped stylesheet.