Реализация NPS-опроса (Net Promoter Score) на сайте

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.
Разработка и обслуживание любых видов сайтов:
Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Реализация NPS-опроса (Net Promoter Score) на сайте
Средняя
от 1 рабочего дня до 3 рабочих дней
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1214
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    852
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1041
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    823
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    815

Реализация NPS-опроса на сайте

NPS (Net Promoter Score) — стандарт измерения лояльности: «Насколько вероятно, что вы порекомендуете нас друзьям?» по шкале 0–10. Промоутеры (9–10), нейтральные (7–8), критики (0–6). NPS = % промоутеров − % критиков.

Когда и кому показывать

Время показа влияет на качество данных:

  • После ключевого события: завершение заказа, окончание пробного периода, первое успешное использование фичи
  • По времени: через 14–30 дней после регистрации, не чаще раза в 90 дней на пользователя
  • Сегментирование: не показывать новым пользователям (< 7 дней), исключить пользователей с открытыми тикетами поддержки

Backend: модель и API

// database/migrations/create_nps_responses_table.php
Schema::create('nps_responses', function (Blueprint $table) {
    $table->id();
    $table->foreignId('user_id')->nullable()->constrained()->nullOnDelete();
    $table->string('session_id')->nullable();
    $table->tinyInteger('score')->unsigned();          // 0-10
    $table->text('comment')->nullable();
    $table->string('trigger_event')->nullable();       // 'order_completed', 'trial_ended'
    $table->string('page_url')->nullable();
    $table->ipAddress('ip')->nullable();
    $table->timestamps();
});

// NpsController
public function store(Request $request): JsonResponse
{
    $validated = $request->validate([
        'score'         => 'required|integer|min:0|max:10',
        'comment'       => 'nullable|string|max:1000',
        'trigger_event' => 'nullable|string|max:100',
    ]);

    $response = NpsResponse::create([
        ...$validated,
        'user_id'    => auth()->id(),
        'session_id' => $request->session()->getId(),
        'page_url'   => $request->input('page_url'),
        'ip'         => $request->ip(),
    ]);

    // Сохраняем в сессии чтобы не показывать снова
    $request->session()->put('nps_submitted_at', now()->timestamp);

    // Алерт в Slack если критик оставил комментарий
    if ($validated['score'] <= 6 && !empty($validated['comment'])) {
        SlackNotification::send('#feedback', "NPS {$validated['score']}: {$validated['comment']}");
    }

    return response()->json(['success' => true]);
}

Условие показа виджета

// Middleware или хелпер для проверки
public function shouldShowNps(Request $request): bool
{
    $user = auth()->user();
    if (!$user) return false;

    // Не показывать чаще раза в 90 дней
    $lastShown = $request->session()->get('nps_shown_at');
    if ($lastShown && now()->timestamp - $lastShown < 90 * 86400) {
        return false;
    }

    // Уже ответил
    if ($request->session()->has('nps_submitted_at')) return false;

    // Пользователь зарегистрирован > 14 дней
    return $user->created_at->diffInDays(now()) >= 14;
}

Frontend: виджет

// NpsWidget.tsx
export function NpsWidget({ triggerEvent }: { triggerEvent: string }) {
  const [score, setScore] = useState<number | null>(null);
  const [comment, setComment] = useState('');
  const [step, setStep] = useState<'score' | 'comment' | 'done'>('score');

  const submit = async () => {
    await fetch('/api/nps', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ score, comment, trigger_event: triggerEvent }),
    });
    setStep('done');
  };

  const label = score === null ? '' : score <= 6 ? 'Критик' : score <= 8 ? 'Нейтральный' : 'Промоутер';

  return (
    <div className="fixed bottom-6 right-6 w-80 rounded-xl bg-white shadow-xl p-5">
      {step === 'score' && (
        <>
          <p className="font-semibold mb-3">Насколько вероятно, что вы порекомендуете нас?</p>
          <div className="flex gap-1 justify-between mb-2">
            {Array.from({ length: 11 }, (_, i) => (
              <button key={i} onClick={() => { setScore(i); setStep('comment'); }}
                className={`w-7 h-7 rounded text-sm ${i <= 6 ? 'bg-red-100' : i <= 8 ? 'bg-yellow-100' : 'bg-green-100'}`}>
                {i}
              </button>
            ))}
          </div>
          <div className="flex justify-between text-xs text-gray-400">
            <span>Маловероятно</span><span>Очень вероятно</span>
          </div>
        </>
      )}
      {step === 'comment' && (
        <>
          <p className="font-semibold mb-2">Оценка: {score} ({label}). Что повлияло на вашу оценку?</p>
          <textarea value={comment} onChange={e => setComment(e.target.value)}
            className="w-full border rounded p-2 text-sm h-20 resize-none" placeholder="Необязательно..." />
          <button onClick={submit} className="mt-2 w-full bg-blue-600 text-white rounded py-1.5 text-sm">
            Отправить
          </button>
        </>
      )}
      {step === 'done' && <p className="text-center text-green-600 font-medium">Спасибо за обратную связь!</p>}
    </div>
  );
}

Аналитика NPS

-- Расчёт NPS за период
SELECT
  COUNT(*) FILTER (WHERE score >= 9)::float / COUNT(*) * 100 AS promoters_pct,
  COUNT(*) FILTER (WHERE score <= 6)::float / COUNT(*) * 100 AS detractors_pct,
  (COUNT(*) FILTER (WHERE score >= 9) - COUNT(*) FILTER (WHERE score <= 6))::float
    / COUNT(*) * 100 AS nps_score
FROM nps_responses
WHERE created_at >= now() - interval '90 days';

Сроки

Виджет NPS с условиями показа, API и базовой аналитикой: 3–4 рабочих дня.