Система отзывов: доверие, интерфейс и фичи

Четыре ступени системы отзывов: лайк или дизлайк, звёзды, несколько свойств и карточка товара с текстом и шкалами

Не так давно я проектировал систему отзывов и основная идея у них: сайт должен стать более заслуживающим доверия за счёт слов реальных людей. Не за счёт красивого описания от копирайтера. За счёт пользовательского контента - того, что написал человек, который уже купил, поел, нанял, попробовал.

Отзывы выглядят как двухдневная задача: таблица, звёздочки, форма. Я так и думал, пока не сел проектировать их всерьёз. Почти вся сложность лежит не в «нарисовать звёзды», а в трёх местах: кому вообще можно писать, как выглядит карточка на экране, и кто решает, что текст можно показывать людям.

Ниже - разбор с инженерной стороны. Я пишу его так, чтобы он читался про любую систему отзывов: товары в магазине, рестораны, курьеры, подрядчики, сотрудники. Меняются слова, не структура. По ходу сравню с чужими экранами: Euronics (товар), Amazon (огромный каталог), Airbnb (жильё), Glassdoor (работодатель) и Google (выдача). Объект другой, список вопросов почти тот же.

Зачем это бизнесу (и почему это влияет на схему)

Три цели. У каждой есть эмоция для покупателя и жёсткое требование для базы.

🤝

Доверие

Человек покупает у незнакомца, если видит опыт других. Значит отзыв обязан ссылаться на настоящую покупку, бронь или смену - не на «анонима из интернета».

🔎

Поиск

Звёзды в выдаче Google - бесплатный клик. Поисковик берёт не картинку, а два числа: среднюю оценку и сколько отзывов. Эти числа должны считаться дёшево на каждой карточке.

↩️

Меньше возвратов

«Собрал за час» или «порция холодная» описывает объект точнее карточки производителя. Значит текст важнее голых звёзд, и текст надо проверять глазами.

Доверие требует доказательства. Поиск требует агрегата (среднее + счётчик). Меньше возвратов требует живого текста и модерации.

Главный очевидность: отзыв нельзя написать «из воздуха»

Самое дешёвое решение, которое отсекает 90% будущих проблем: отзыв создаётся только из подтверждённого факта. Оплаченный заказ. Состоявшаяся бронь. Закрытая смена. Принятый проект.

Почему это решение в базе, а не «антифрод потом». Если колонка «заказ» обязательна и ссылается на настоящий заказ, накрутка становится невозможной по построению. Мне не нужны капча, лимиты по IP и эвристики «подозрительный аккаунт». Мне нужен запрет хранить отзыв без заказа.

Цена тоже реальная: отзывов будет мало. Публичной кнопки «оставить отзыв» для всех подряд нет. Писать могут только те, кто уже взаимодействовал. Это обмен количества на доверие, и его надо проговорить с бизнесом до старта.

Схема данных

В каком таблице лежит отзыв, и на какие другие таблицы он обязан ссылаться. Базовая версия - таблица отзывов, таблица переводов и два числа на объекте, про который пишут.

Две мысли, без которых схема разваливается.

Два уровня объекта. Есть конкретный опыт («я купил 💻 MacBook Pro 14" на 512 ГБ») и есть сущность, у которой копится репутация («💻 MacBook Pro 14" вообще»). В магазине это артикул и карточка товара. В ресторане - 🍝 блюдо и заведение. У подрядчика - конкретная задача и человек. Если слить уровни, вы либо потеряете точность («отзыв про какой именно салат?»), либо не накопите статистику.

Авторство на почту, не на аккаунт. Гость оформляет заказ без регистрации. Аккаунта нет, почта есть всегда. Если завязать отзыв на user_id, половина людей просто не сможет написать.

ПолеЗачем оно новичку
order_idДоказательство. Из заказа берём имя, страну и плашку «проверенная покупка».
item_idПро что именно был опыт. Не про абстрактную карточку.
product_idКопия ссылки на карточку, чтобы показывать отзыв на всех вариантах и считать среднее без лишнего join.
ratingЦелое 1..5. Половинки звёзд - это картинка среднего, человек ставит целую.
bodyМожно пустым. Оценка без текста - полноценный голос. Её не надо модерировать и переводить, поэтому люди чаще дожимают форму.
source_langЯзык оригинала. Нужен, чтобы не показывать кнопку перевода, если витрина уже на этом языке, и чтобы не писать вторую копию текста в таблицу переводов.
stateНе галочка «опубликовано», а комната, в которой отзыв сейчас живёт. Почему - следующий раздел.
review_translationsОтдельные строки, не колонки body_et / body_en. Ключ (review_id, locale). Оригинал сюда не кладём: он уже в reviews.body. Рейтинг не переводится.

Среднее и счётчик лежат прямо на товаре. Считать их на лету на одной странице нормально. На витрине из 48 карточек - уже дорого ради двух чисел, которые меняются раз в неделю. Пересчитываем, когда отзыв опубликовали, скрыли, поправили или удалили.

Мягкое удаление. Строку не стираем насовсем: GDPR-запрос и удаление спама - разные истории, и в обоих случаях полезно понимать, что запись была. Уникальность «один человек - один артикул» должна игнорировать удалённые строки, иначе человек не сможет написать заново.

Состояние - это граф, а не флаг

Соблазн большой: колонка «опубликовано: да/нет». Уже на второй неделе появляются вопросы, на которые флаг не отвечает. Отзыв отклонили навсегда или он ждёт решения? Можно ли автору править опубликованный текст? Куда девается текст после правки?

Поэтому состояние - это карта комнат и дверей. Комната говорит, где отзыв сейчас. Дверь говорит, кто имеет право перевести его в другую комнату.

форма с текстом held ждёт человека, на витрине нет rejected скрыт, админ может вернуть published виден всем, в среднем рейтинге админ: Reject админ: Approve автор правил текст снова held админ: Approve без текста форма сразу попадает в published, комнату held минует

Два неочевидных перехода, из-за которых флага мало.

Правка опубликованного текста возвращает отзыв в held. Иначе модерация обходится в два шага: написал безобидное, дождался одобрения, переписал на что угодно. Смена только звёзд состояние не меняет - в цифре проверять нечего.

Отзыв без текста публикуется сразу. Человеческая проверка нужна там, где есть свободный текст. Оценка - это голос, не высказывание.

Потыкайте переходы сами

heldсохранён, на витрине нет
publishedвиден всем, входит в среднее
rejectedскрыт, но обратимо
Отзыв с текстом создан → held
Про имена состояний. Я начал с pending («принят, автоматика ещё думает»). Пока автоматики нет, в этом состоянии никто никогда не находится. Мёртвое состояние в списке дороже, чем миграция, которая его добавит позже.

Как это выглядит на экране

Схема отвечает на вопрос «что можно хранить». Экран отвечает на вопрос «что человек успеет понять за три секунды». Для отзывов это важнее, чем кажется: покупатель не читает документацию, он сканирует блок глазами.

Три ширины - три раскладки

Один и тот же набор данных. Три разных способа его разложить, потому что глаз работает по-разному на телефоне, планшете и мониторе.

Переключите ширину

4.6
23 отзыва
5
16 4
5 3
2 1
0

Ризотто горячее, грибы отличные. На двоих как раз.

✓ проверенная покупка
J James S. · Великобритания · 2 месяца назад

На узком экране звёзды отдельной колонкой слева съедают ширину текста. Поэтому звёзды сверху одной строкой, итог по центру, текст на всю ширину.

В каталоге звёзды стоят сразу под названием, до описания. Если отзывов нет - серых звёзд и «0.0» тоже нет. Строка просто отсутствует. Иначе витрина выглядит как кладбище пустых рейтингов.

Три карточки наушников JBL в каталоге Euronics: под названием звёзды и число отзывов
Euronics кладёт среднее и счётчик сразу под названием в сетке. Это ровно те два числа с карточки товара: без предрасчёта в каталоге из десятков карточек нечего рисовать.

Порядок внутри карточки - по важности

Человек сканирует, а не читает. Значит самое важное должно быть выше.

Анатомия карточки

1
Звёзды. За одну долю секунды: хорошо или плохо. На телефоне по центру под агрегатом, на планшете слева линейкой.
2
Текст, если он есть. Это и есть опыт. Пустую заглушку «без комментария» не рисуем: блока просто нет, карточка короче.
3
Плашки доверия. «Проверенная покупка», «именно этот артикул». Доказательства после цитаты, чтобы не спорить с ней за внимание.
4
Кто и когда. Имя, страна, относительное время. Автор внизу: сначала опыт, потом человек.

Длинный текст режем примерно до пяти строк. Клик раскрывает. Иначе одна простыня ломает сетку карточек на мониторе.

Гистограмма: зачем пять полосок, если уже есть 4.6

Среднее - это одно число. Оно врёт. Товар с одной пятёркой и товар с двадцатью тройками и пятёрками могут дать похожее среднее. Полоски показывают форму распределения.

Люди интуитивно ждут «J-кривую»: много пятёрок, немного четвёрок, почти нет единиц. Если полоски плоские или перевёрнутые, средний 4.6 уже не успокаивает. Сомневающийся покупатель всё равно ищет негатив. Вопрос только в том, найдёт он его у вас за один клик или уйдёт на другой сайт.

Страница товара Euronics: среднее 5,0 из трёх отзывов, гистограмма только из пятёрок, карточка без текста с лайками
Три отзыва, все пятёрки, среднее 5,0. Полоски 1-4 пустые, фильтровать нечего, картинка «идеально» только укрепляется. Зато инвариант написан вслух: оценить может только купивший. Лайки на отзыве без текста - шум: голосовать не за что.

Кликните по строке распределения. Итог 4.6 не меняется

4.6
23 отзыва
5
16 4
5 3
2 2
0 1
0

Полоски с нулём не кликаются: пустой список выглядит как сломанный сайт. При пяти отзывах фильтры только шумят. Разумный порог показа блока - штук от десяти.

Сортировка

Три режима, которые реально нужны с первого дня. Каждый отвечает на разный вопрос читателя.

СортировкаВопрос читателяПочему не по умолчанию всегда
Сначала новые«Что говорят сейчас?»Хороший дефолт. Свежесть важнее, чем идеальный порядок.
Сначала критические«Где подвох?»Идеальный рейтинг подозрителен. Один клик до единиц повышает доверие ко всему блоку.
Сначала с текстом«Хочу опыт, не голос»Оценка без текста полезна для среднего, но в списке это пустая карточка. Её лучше не прятать, а отодвинуть вниз.

Сортировка «сначала полезные» появится только вместе с кнопкой «Полезно». Фильтр каталога по звёздам - тоже отдельная фича, и это уже не список отзывов на карточке, а сами результаты поиска.

Фильтр каталога по звёздам

На карточке товара человек кликает по полоске, чтобы увидеть единицы. В каталоге он хочет другое: «покажи товары от 4 звёзд» или «сначала с лучшими отзывами». Это разные фильтры. Один режет отзывы внутри одного объекта. Второй режет сами объекты в длинной выдаче.

Звёзды уже лежат на карточке товара. Вопрос не «откуда взять число», а «как искать по нему быстро» и «что делать с тысячами позиций без отзывов».

Сайдбар Alibaba: фильтр Store reviews с вариантами 4.0 и выше, 4.5 и выше и ровно 5.0, ниже 4.0 пунктов нет
Alibaba в поиске режет магазины, не отзывы внутри карточки: 4.0 и выше, 4.5 и выше, ровно 5.0. Двоек и троек в сайдбаре нет. Человек отсекает слабое, а не коллекционирует среднее.
Выдача AliExpress по esp32: активный фильтр Quality and trust 4 stars and up, двоек в сайдбаре нет
AliExpress ещё короче: один чекбокс «4 stars & up» и чип над сеткой. Тот же жест. Никто не приходит в каталог с запросом «хочу именно двойки».

Что реально ставят в сайдбар

Люди выбирают
  • 4.0 и выше
  • 4.5 и выше
  • ровно 5.0
  • есть отзывы
В сайдбар не кладут
  • именно 2 звезды
  • именно 3 звезды
  • Полоски 1-5 на карточке товара - это прочитать негатив. В каталоге это другой вопрос.

Цена отдельной фичи. Рейтинг надо класть в поисковый индекс, и каждый Approve или Reject начнёт переиндексировать товар. Товары без отзывов: в конец, спрятать при пороге, или отдельный чип «есть отзывы». Ловушка маленькой выборки: одна пятёрка обгонит 4.6 из 23 отзывов, если сортировку «Highest rated» не поправить минимумом N или байесовским средним.

Подгрузка, а не простыня

На телефоне сначала 3 отзыва. На мониторе можно открыть больше. Кнопка «ещё» подгружает следующую пачку без перезагрузки страницы. Следующую пачку можно начать грузить заранее, пока человек ещё читает первую - тогда клик кажется мгновенным.

Зачем так: страница товара и без отзывов тяжёлая. Сто отзывов сразу замедлят и первый показ, и поисковую разметку (в неё попадают только реально нарисованные отзывы).

Относительное время

Пишем «2 месяца назад», а точную дату прячем в подсказку при наведении. Люди сравнивают опыт с «сейчас», а не с календарём. Отзыв 2019 года про модель 2024 года выглядит иначе, чем «2 месяца назад».

Плашка «проверенная покупка»

Это не украшение. Это перевод инварианта схемы на человеческий язык. Раз отзыв нельзя создать без заказа, мы имеем право написать это вслух. Без плашки блок выглядит как обычные комментарии, которые кто угодно мог накрутить.

Имя, страна, почему нет флагов

Публично: имя плюс первая буква фамилии («James S.»), страна словами, дата. Не полное имя, не город, не почта.

Флаг страны я сознательно не ставлю. Три причины:

  • В маленькой стране имя + редкий заказ + флаг уже опознают человека. GDPR просит минимизировать.
  • Флаг читается как политика, а не как «откуда заказ».
  • Слово «Эстония» понятно скринридеру и в чёрно-белой печати. Иконка флага - нет.

Город не показываем по той же причине минимизации. Страны достаточно, чтобы понять контекст («пишут ли люди с моего рынка»).

Один отзыв, несколько моделей. Аналогия с MacBook

Представьте Apple. «MacBook Pro 14"» - это карточка товара. Space Gray 512 ГБ и Silver 1 ТБ - это варианты. Человек купил 512 ГБ. Его опыт почти целиком про тот же ноутбук: экран, клавиатура, нагрев. Но батарея и вес уже другие.

Поэтому отзыв пишут на купленный вариант, а показывают на всех вариантах той же карточки. И обязательно помечают: «это про 512 ГБ», если вы сейчас смотрите страницу 1 ТБ.

Один и тот же отзыв на двух страницах

Страница купленного: MacBook 14" · 512 ГБ

Тихий, экран отличный. К вечеру батареи как раз хватает на рабочий день.

✓ проверенная покупка ✓ именно эта модель · 512 ГБ
Соседняя страница: MacBook 14" · 1 ТБ

Тихий, экран отличный. К вечеру батареи как раз хватает на рабочий день.

✓ проверенная покупка заказана другая модель · 512 ГБ →

То же в ресторане: отзыв про «Цезарь с курицей» виден на странице «Цезарь с креветками», но бейдж говорит «человек заказывал курицу». У работника: отзыв про ремонт ванной виден в профиле, но помечен как «ванная, не кухня». Агрегат (среднее по карточке) считается по всем вариантам вместе. Иначе у каждого артикула будет по одному отзыву, и статистика никогда не сложится.

Как добиться, чтобы отзывы вообще писали

Форма может быть идеальной. Без письма после доставки её почти никто не откроет. Люди не просыпаются с желанием написать отзыв. Им нужно напомнить в тот момент, когда опыт уже есть, но ещё не забыт. Когда заказ становится delivered, сервис заказов ставит надёжную отложенную задачу примерно на 14 дней; worker отправляет приглашение, когда её срок наступил.

≈ 14 днейПервое письмо: «как прошло / как на вкус?». Кнопка ведёт в заказ, оттуда - в форму.
≈ 28 днейОдно напоминание, если по позиции всё ещё нет отзыва. Третьего письма в этой серии нет.
≈ 6-12 месяцевУже не «оставьте отзыв», а «как вещь себя показала». Отдельная фича, но про неё надо подумать в схеме заранее.

Первое письмо

Тема: Как заказанное вам подошло?

Здравствуйте, Мари!

Заказ #R123456789 доехал две недели назад. Как вам шуруповёрт? Ваша оценка помогает другим выбрать.

Оставить оценку

Не хотите такие письма? Отписаться

Важные мелочи. Письмо не просит пять звёзд, оно просит опыт. Отписка - отдельное подтверждение, а не ссылка, которая молча меняет настройку по GET (почтовые роботы такое открывают сами). Форма живёт на отдельной странице: в строке заказа места хватает только на кнопку.

Форма и модерация

Без этого блока отзывы не живут: человек должен суметь написать, а человек из поддержки - решить судьбу текста.

Как человек доходит до формы

Три короткие последовательности вместо одной большой: сначала система отправляет приглашение, затем покупатель попадает в форму из письма или со страницы товара, а после этого модератор выпускает текст для остальных посетителей.

Письмо с приглашением

Заказы orders Задача напоминания scheduler + worker Почтовый сервис transactional mail Покупатель почта статус → delivered поставить приглашение на +14 дней id отложенной задачи Отложенная задача заменяет периодический обход доставленных заказов. Раз в сутки можно сверять и дозаводить потерянные задачи. когда срок наступил: отправить приглашение письмо со ссылкой на заказ принято к отправке

Из письма или со страницы товара — в форму

Покупатель браузер + почта Витрина заказ / товар / форма Backend API отзывов проверка + POST /reviews alt [открывает письмо] GET ссылка из письма → заказ проверить подходящие позиции позиция + токен формы else [открывает купленный товар или соседний вариант] открыть страницу товара та же проверка права на отзыв звёзды + необязательный текст POST /reviews 201: held для текста, published для оценки без текста

Публичной кнопки «для всех» нет. Ссылка из письма отзыв не создаёт: она только открывает заказ. Форма живёт на отдельной странице - в строке заказа места хватает только на кнопку.

Approve — публикация для остальных

Поддержка почта + админка Backend API отзывов очередь модерации Витрина товар Другой покупатель текстовый отзыв → held + письмо открыть очередь по ссылке из письма оригинал, заказ и состояние held Approve published + обновить среднее и счётчик отзыв готов к показу открыть товар опубликованный отзыв + новый рейтинг

Форма

Обязательное поле одно - звёзды. Текст по желанию.

Очередь плюс письмо

Админка - место, куда заходят, когда уже сидят за компьютером. Отзыв приходит когда угодно. Поэтому на каждый текстовый отзыв в held уходит письмо в поддержку, а очередь остаётся источником истины.

Номер заказа в теме письма окупается сразу: хелпдеск сам привязывает тред к покупке. Админ текст не редактирует. Только Approve или Reject. Как только модератор правит чужие слова, отзывы перестают быть отзывами.

Разметка для поисковика

Поисковик читает не только то, что видит человек. У schema.org для этого два типа внутри карточки товара:

  • AggregateRating - среднее и число отзывов. Именно отсюда в выдаче появляются звёзды.
  • Review - один видимый отзыв: автор, дата, оценка, текст.

Отдельный JSON-LD не нужен, если на странице уже есть Product: оба блока вкладываются внутрь него. Коротко это выглядит так:

<article itemscope itemtype="https://schema.org/Product">
  <h1 itemprop="name">Шуруповёрт 18 В</h1>

  <div itemprop="aggregateRating" itemscope
       itemtype="https://schema.org/AggregateRating">
    <span itemprop="ratingValue">4.6</span>
    <span itemprop="reviewCount">23</span>
  </div>

  <article itemprop="review" itemscope
           itemtype="https://schema.org/Review">
    <span itemprop="author">James S.</span>
    <time itemprop="datePublished">2026-07-02</time>
    <span itemprop="reviewRating" itemscope
          itemtype="https://schema.org/Rating">
      <span itemprop="ratingValue">5</span>
    </span>
    <p itemprop="reviewBody">Держит момент ровно.</p>
  </article>
</article>

В разметку попадают только реально нарисованные опубликованные отзывы. Поэтому фильтр «1 звезда» нельзя делать сменой URL страницы: иначе Google увидит среднее 4.6 и в придачу только плохие тексты. Фильтр живёт внутри фрагмента страницы и канонический адрес не трогает.

Выдача Google по запросу tesla model y car reviews: у каждого результата звёзды, автор и блок преимуществ и недостатков
Ради этих звёзд в выдаче и живут AggregateRating. Здесь Google собрал чужие обзоры Tesla Model Y: оценка, автор, плюсы и минусы. Для магазина то же берётся из среднего и счётчика на карточке, не из картинки. Редакционный обзор и пользовательский отзыв для поисковика выглядят похоже, если разметка на месте.

Автоматический перевод и авто-флаггинг

Люди пишут на своём языке. На чужой витрине такой отзыв - шум. Ручная модерация при этом не масштабируется: человек читает каждый текст, чтобы поймать редкий спам и телефон в абзаце.

Обе задачи решает одна модель за один вызов. Она всё равно читает оригинал, чтобы понять язык. За тот же проход проверяет текст (персональные данные, спам, жалоба не по теме) и готовит переводы.

Переводим не «на все языки мира», а на фиксированный набор локалей, под которые сверстана витрина. Если сайт говорит на эстонском, английском, русском и финском - модель за один проход кладёт эти строки в review_translations. Язык оригинала в набор не входит: он уже лежит в reviews.body и source_lang.

Другая архитектура - переводить в язык зрителя по запросу и сразу сохранять результат в ту же таблицу. Первый человек с японским Accept-Language ждёт секунду, следующие читают кэш. Это выгоднее, если локалей много или витрина одна, а хвост языков широкий. Хуже, если модератор должен выпустить уже готовый текст: перевод может появиться после Approve, и на витрине на миг мелькнет оригинал.

ПодходКогда выигрываетЦена
Набор языков витрины заранееДва-пять локалей, модерация до публикации, мгновенное переключение языкаПлатим за языки, которые никто не откроет
По запросу языка зрителяМного локалей или непредсказуемый Accept-LanguageПервый зритель ждёт, перевод может опоздать к Approve
Подготовка не равна публикации. Оригинал и переводы сохраняются во время проверки, но до Approve на витрине пусто. Approve только выпускает уже готовые строки. Публикация мгновенная, модератор читает оригинал, а не пересказ. Для схемы «по запросу» Approve выпускает оригинал, а строка перевода дописывается позже.

Здесь появляется комната pending: «принят, автоматика думает». Теперь в ней реально кто-то находится - несколько секунд.

На экране всегда один текст, как у Airbnb. Кнопка не открывает второй блок, а заменяет абзац. Если язык отзыва совпал с языком витрины, кнопки нет.

Amazon на огромном каталоге выбирает второй путь ещё жёстче: оригинал остаётся на экране, перевод сам не подставляется. На английской витрине немецкий отзыв так и лежит по-немецки, а «Translate review to English» грузит перевод по клику. Это дешевле, когда языков много. И клик сам по себе сигнал: человек дочитал чужой текст достаточно далеко, чтобы захотеть понять его. Такой запрос можно писать в ту же копилку, что и «Полезно» - отзыв оказался достаточно ценным, чтобы преодолеть язык.

Страница отзывов Amazon: среднее 4,7, лента Reviews with images и немецкий отзыв с ссылкой Translate review to English
Amazon держит оригинал по умолчанию и грузит перевод по запросу. На том же экране фото вынесены из карточек в ленту «Reviews with images» над списком: глаз сначала видит живые снимки товара, потом тексты. Рейтинг от порядка не меняется. Клик «перевести» здесь ещё и метрика: отзыв достаточно интересен, чтобы читать его не на своём языке.
Список отзывов Euronics: эстонский текст с кнопкой перевода, отзыв только из звёзд и короткий отзыв на русском
Тот же магазин на странице товара. Эстонский текст с «Показать перевод», отзыв без абзаца (только звёзды, и это нормально), автор иногда просто «Euronics клиент». Публичная кнопка «Оставить отзыв» у меня намеренно отсутствует: писать можно только из заказа.

Переключатель перевода

Ризотто пришло горячим, грибы отличные. На двоих как раз.

M Mari K. Эстония

Почему одной шкалы 1-5 мало

«Четыре звезды» - это не смысл. Это сжатие. Один человек так сказал, потому что ризотто отличное, а ждали долго. Другой - потому что шуруповёрт средний, но приехал быстро. Третий оценил официанта, а не блюдо. Читатель этого не видит.

Плоская шкала хорошо работает как голосовалка и как число для Google. Как объяснение опыта - плохо. Именно поэтому на экране текст стоит выше автора, а гистограмма важнее среднего: они хотя бы показывают разброс.

Несколько осей помогают - и всё равно ограничивают

Следующий соблазн: вместо одной звезды спросить шесть. В ресторане - вкус, порция, ожидание, цена, обслуживание, атмосфера. У инструмента - момент, удобство, батарея, шум, кейс, цена. На экране это радар. Покупатель видит не «4.3», а «еда отличная, ждали долго».

Плюс для компании: систематически низкое «ожидание» - это претензия к смене, не к кухне. Оси заполняются кликами, их не надо переводить и модерировать.

Цена: шесть вопросов вместо одного убивают и так редкие отзывы. Google всё равно берёт одно число. Если оси необязательные, у одной будет 3 голоса, у другой 20 - радар начнёт врать, и ось придётся прятать до порога.

Вкус 4.8 Порция 4.4 Обслуживание 4.6 Цена 4.1 Ожидание 3.6 Атмосфера 4.2
Модалка отзывов Airbnb: среднее 4,77, гистограмма, шесть категорий вроде чистоты и заезда, теги тем и перевод отзыва
Airbnb держит шесть осей рядом со средним 4,77 и гистограммой. Читатель видит не «почти пять», а «чистота 4,6, заезд 4,9». Теги «упоминается в отзывах» - сводка тем из текстов, без отдельного чата. Ссылка «Как устроена система отзывов», перевод, стаж автора на платформе - те же вопросы, другой объект: ночь в квартире, не шуруповёрт.

Оси полезны как каталог тем. Они не заменяют живой рассказ. Человек всё равно напишет то, что вы не предусмотрели: «биты в комплекте нормальные, а замок на кейсе так и не открылся с первого раза». Шкала это не поймает.

AI-отзывы как ответ на оба ограничения

Люди плохо пишут в пустое поле. Получается «отлично» или жалоба на доставку. Несколько осей это чинят частично, ценой трения. Более сильный ход - короткий диалог.

Диалог вместо пустого поля

Ассистент. Коротко про сам шуруповёрт, не про доставку. Для чего брали?
Собрать кухню, потом полки в гараже
Ассистент. Как с крутящим моментом и битами? Слизывает?
Момент ровный, биты нормальные. Замок на кейсе тугой

Бот собирает черновик. Человек правит и подтверждает. Звёзды по-прежнему ставит сам. Можно закрыть чат и оставить только оценку. Дальше обычный путь: текст в held, Approve человека.

Когда отзывов много, второй AI-слой - сводка «что хвалят / что ругают» над списком. Не замена отзывам, а оглавление. Порог примерно 20 текстов: на пяти отзывах один громкий минус выглядит как мнение всех.

Что хвалят
  • Ровный момент, биты не слизывает
  • Порции честные, грибы свежие
Что ругают
  • Замок кейса тугой
  • Ждали сорок минут

Риски: одинаковый «голос магазина», юридическая пометка «собрано с помощником», галлюцинации в сводке. Звёзды при этом остаются фактом из базы. Если модель ошиблась, среднее всё равно честное.

Контекст автора

Для ресторана главный вопрос - повод визита: бизнес-ланч и день рождения читаются по-разному. Для инструмента - задача: собрал полку или крутил каркас. Для подрядчика - тип объекта. «Идеально подошло» бесполезно, если у автора другой контекст.

Карточки отзывов Glassdoor: должность, current или former employee, плюсы и минусы, кнопка Helpful
У работодателя контекст автора важнее голых звёзд: должность, current или former, город, плюсы и минусы отдельными полями. «Полезно» уже на карточке. Фильтр по job title - семейство, не точное совпадение: иначе при 404 отзывах список всегда пустой.

Данные часто уже есть в заказе. Одна колонка на отзыв, фильтр по семейству, не по точному совпадению: иначе фильтр всегда пустой. Точный адрес и госномер в публичный блок не попадают никогда.

Фильтр «для моей машины» и другие такие же случаи

Есть бизнесы, где купленная деталь обязана сесть на что-то, что уже есть у покупателя. Главный вопрос не «хорошая ли вещь», а «встанет ли на моё». Отзыв «идеально подошло» бесполезен, если у автора другой хост.

Запчасти - самый чистый пример. Человек ищет колодки не «вообще», а под свою Octavia. Машину он уже выбрал в подборе, она лежит в заказе. В форму её не надо набивать руками: подставляем из заказа и даём подтвердить или снять. В отзыв пишем название из каталога, не свободный текст. Госномер не показываем никогда.

Три степени совпадения, не да/нет

Все отзывы · 23 Моя модель: Octavia III · 7 Точно мой 1.6 TDI · 1 Только с текстом · 19

Встала за час, без доработок. Хват лучше дешёвого комплекта, который стоял до этого.

✓ проверенная покупка Škoda Octavia III 1.6 TDI · 2014
J James S. · ровно та же модификация

Встала без проблем, педаль мягче оригинала.

✓ проверенная покупка Škoda Octavia III 2.0 TSI · 2017
A Antti T. · то же семейство, другой мотор

Нормальные колодки за свои деньги. Первые недели пылят сильнее, чем ждал.

✓ проверенная покупка
D David W. · машину не указывал, бейджа нет

Точный фильтр «как у меня до мотора» на старте почти всегда пустой. Имеет смысл резать по семейству модели, а модификацию печатать в бейдже: читатель сам видит, что у автора 1.6 TDI, а у него 2.0 TSI.

Тот же паттерн живёт далеко не только у автозапчастей. Везде, где SKU подходит к каталогу уже купленных «хостов», отзыв надо читать через этот фильтр.

БизнесЧто уже есть у покупателяТочное совпадениеСемейство, по которому фильтруем
АвтозапчастиМашина в гаражеКонкретный мотор и годыМодель: Octavia III
Чехлы и стёклаТелефонiPhone 16 ProiPhone 16
КартриджиПринтерHP LaserJet Pro M404dnсерия M404
Оптика и батарейкиКамераSony A7 IVбайонет Sony E
ВелозапчастиРама и группаразмер 56 / Ultegraшоссейный велосипед
РемешкиЧасыконкретная модель, 20 ммширина ушка 20 мм
ПлагиныСтек сайтаWordPress 6.6 + WooWordPress
Фильтры HVACБлокточный артикул установкисерия производителя

Общее правило одно. Точный фильтр почти всегда пустой. Семейство даёт осмысленный список. Свободный текст («на мою машину», «на мой принтер») не храним: это уже есть в каталоге совместимости, его не надо переводить и модерировать. Если хост из заказа неизвестен, поле в форме не рисуем вообще.

Машину, телефон или принтер читателя берём только для фильтра, в чужой отзыв это не пишется. Автор мог посмотреть три хоста и купить деталь для четвёртого, поэтому в форме даём подтвердить, а не подставляем молча.

Обновление через 6-12 месяцев

Через две недели человек скажет «быстро приехало». Через год он знает главное: выдержало или нет. Этого не будет у конкурента, который спрашивает на второй день.

Первый отзыв и поздняя правка опыта

Собрал кухню за выходные. Момент ровный, биты не слизывает.

M Mari K.

Технически лучше отдельная связанная строка с ссылкой на родителя, а не поля внутри того же отзыва: обновление проходит ту же модерацию и перевод. В среднем рейтинге ветка считается за один голос, берём последнюю оценку. Иначе один человек голосует дважды. Это как раз то решение, которое дорого менять после запуска.

Фото и видео

Самый убедительный формат и самый тяжёлый: приём файлов, ресайз, превью, антивирус, модерация картинок, для видео ещё транскодинг. Плюс согласие на публикацию и удаление всех копий по GDPR.

Если медиа всё же появятся, в списке они должны стоять выше голого текста: глаз цепляется за фото сильнее, чем за дату. Рейтинг объекта от порядка списка не меняется. Amazon решает это лентой над списком, не перестановкой карточек: отдельная галерея из отзывов с фото даёт тот же приоритет медиа, только ещё раньше, до первого абзаца.

Сначала отзывы с медиа, фото раскрывается на месте

★
Сначала с фото и видео
Внутри группы - новые первыми. Рейтинг не меняется.

Ризотто горячее, грибы отличные. Прикладываю фото тарелки и короткое видео.

✓ проверенная покупка
Крупный план тарелки грибного ризотто
Грибное ризотто на столе в ресторане
видео 0:14 ▶
J James S. · 2 месяца назад

Держит момент ровно. Кейс удобный, замок тугой.

✓ проверенная покупка
M Marek T. · 1 месяц назад

Отзыв Marek новее, но стоит вторым: медиа перевешивает дату.

Крупный план тарелки грибного ризотто
Грибное ризотто на столе в ресторане
видео 0:14 ▶
Крупный план тарелки грибного ризотто
1 из 3 · загружено гостем

Почему не модалка: текст отзыва остаётся на экране, картинка читается вместе с тем, что человек про неё написал. Отдельное окно обрывает чтение и ломает «назад» на телефоне.

«Полезно» и центр автора

Голос других читателей даёт сортировку «сначала полезные» и мотивацию писать содержательнее. Цена: новая таблица голосов и защита от накрутки. Подпись «Полезно» важнее лайка: человек оценивает пользу опыта, а не соглашается со звёздами. Голос рейтинг объекта не меняет.

Кнопка на карточке и личный раздел

Ризотто горячее, грибы отличные. На двоих как раз. Если придёте вдвоём - берите ещё салат.

✓ проверенная покупка
один голос, повтор отменяет
M Mari K. · Эстония · 2 месяца назад
M
Ваши отзывы помогают выбирать
Счёт растёт, когда другие отмечают текст полезным.
84
12отзывов
47полезных
4.2на отзыв
тарелка
Ризотто с грибами
2 месяца назад · опубликован

Горячее, грибы отличные. На двоих как раз.

♡ Полезно · 18
кейс
Шуруповёрт 18 В
3 недели назад · проверяется

Момент ровный, биты нормальные. Замок тугой.

⏳ проверяется

Голосовать может только вошедший пользователь, нельзя голосовать за свой отзыв, один активный голос на пару «человек + отзыв». Гость видит счётчик, но клик просит вход и число заранее не увеличивает. Иначе один браузер превращается в сотни лайков очисткой cookie.

Экспертный статус и осторожная мотивация

Когда «Полезно» уже работает, появляется соблазн выделить авторов, чьи тексты стабильно помогают выбирать. Значок рядом с именем говорит: этот человек пишет не один раз и его тексты читают. Скидка может усилить мотивацию. Она же легко превращает отзывы в оплаченные рекомендации, если завязать её на пятёрку.

Публичный сигнал и награда в кабинете

Встала без доработок. Через 5 000 км нет вибрации, пыли меньше, чем у прошлого комплекта.

✓ проверенная покупка
M Mari K. ◆ эксперт · Эстония · 2 месяца назад

До статуса эксперта: 16 баллов

Пример порога: минимум 5 содержательных опубликованных отзывов, 25 полезных голосов от разных людей и нет недавних нарушений.

Награда за вклад: скидка 5% на следующий заказ

30 дней, один раз, не суммируется с другими промокодами. Это механика для эксперимента, не обещание с первого дня.

Значок означает опыт автора, не сертификат мастера. «Эксперт» нельзя выдавать за число покупок или один популярный отзыв. Нужны несколько опубликованных текстов, устойчивая доля «Полезно» и минимум независимых голосовавших. Иначе значок покупают одной удачной карточкой.
Не платить за положительность. Баллы и скидка зависят от полезности и конкретности текста, никогда от 5 звёзд. Резкий, точный негатив должен иметь те же шансы. Иначе люди начнут завышать оценки ради выгоды, а доверие к блоку отзывам рухнет. На странице правил поэтому нельзя писать «мы платим за отзыв». Если скидка появится, она платится за вклад, не за оценку.

Безопасная очередь запуска. Сначала центр автора: человек видит свои отзывы и следующий шаг. Потом «Полезно»: проверить, голосуют ли вообще. Потом значок на маленькой группе: сравнить полезность и конверсию, не только клики. Скидка - последний шаг, ограниченный A/B, и только после защиты от накрутки и расчёта экономики. Начинать со скидки нельзя: это сразу финансовый стимул писать что угодно.

Аватары

Живое лицо рядом с отзывом делает его похожим на слова человека, а не на строку в базе. Три источника по приоритету, ни один не обязателен: своё фото в кабинете, Gravatar по хэшу почты, буква в круге как запасной слой.

Одно и то же место: живое фото и запасная буква

Ризотто горячее, грибы отличные. На двоих как раз.

✓ проверенная покупка
James S. · Эстония · 2 месяца назад

Держит момент ровно, биты не слизывает.

✓ проверенная покупка
Mari K. · Финляндия · 3 месяца назад

Вкусно, но ждали сорок минут.

✓ проверенная покупка
A Aino V. · Швеция · 3 месяца назад

Gravatar - запрос из браузера читателя к третьей стороне: она видит хэш почты и IP. Без явного согласия и строки в политике приватности так нельзя. Покрытие в обычных магазинах низкое, поэтому основной эффект даёт только своя загрузка. Своё фото без модерации публиковать нельзя: на витрине окажется чужое лицо или что угодно ещё.

Публичный ответ и репутация бренда

Короткая реплика под негативом снимает яд для всех будущих читателей, не только для одного жалобщика. Технически просто. Организационно тяжело: кто отвечает, в какой срок, на каком языке, уходит ли письмо автору.

Ответ вложен под отзыв, это не второй отзыв

Порция пришла тёплой, салат размяк. Само ризотто нормальное, но вечер уже был испорчен.

✓ проверенный визит
A Aino V. · 3 месяца назад
Ответ кухни · 3 месяца назад

Извините за ожидание и тёплый салат. Мы сменили смену на этот слот и прислали вам ваучер на следующий визит. Если что-то ещё не так - ответьте на письмо заказа.

Правила, без которых ответ вредит: отвечать не только на единицы, не спорить с автором, не светить номер заказа, один ответ на отзыв. Диалог уводим в поддержку, публично оставляем итог.

Агрегат по всем товарам бренда (или по всем сменам сотрудника) превращает ручную плашку «премиум» в доказуемое число. Нужна защита от маленькой выборки: одна пятёрка не должна поднимать бренд выше того, у кого тысяча честных 4.6. И нельзя прятать слабые категории внутри красивого среднего.

Страница «как мы работаем с отзывами»

В ЕС, если вы показываете отзывы, вы скорее обязаны объяснить: проверяете ли, что их оставили реальные покупатели, и как именно. Хорошая новость: при схеме «отзыв обязан ссылаться на заказ» эта страница пишется за десять минут и звучит убедительно. Ссылка - спокойная сноска рядом с заголовком блока, не баннер «нам можно доверять».

Сводка Glassdoor по Bolt Tallinn: дисклеймер что компания не удаляет отзывы, оценка 3,3, одобрение CEO и график за полгода
Glassdoor выносит доверие в шапку: компанию нельзя править и удалять отзывы. Дальше не одно число, а пакет: 3,3, «посоветовали бы другу», одобрение CEO, прогноз бизнеса и график за полгода. Для бренда или сотрудника это ближе, чем среднее по одной карточке товара. Ссылка «see how Glassdoor protects users» - та же сноска про правила, только громче.

Сноска у блока и сама страница

4.6
23 отзыва
Как мы работаем с отзывами
  • Писать может только тот, кто уже заказал, поел или закрыл смену. Публичной кнопки «для всех» нет.
  • Мы не платим за отзыв и не просим пять звёзд.
  • Негатив не удаляем. Скрываем только спам, персональные данные и текст не по теме.

Приватность: единственное необратимое действие

Отзыв - место, где частное действие становится публичным. Два решения надо принять явно.

Что показывать. Имя плюс буква фамилии, страна словами, относительная дата. Всё остальное из заказа наружу не выходит.

Что остаётся после удаления аккаунта. Если отзывы исчезают вместе с аккаунтом, средний рейтинг товара переписывается задним числом. Если остаются, их надо обезличить. Оба варианта защитимы. Выбрать надо до запуска и написать это на экране удаления аккаунта, не только в политике.

Экран удаления и тот же отзыв после него

!

Удалить аккаунт

Ваши данные будут удалены. Опубликованные отзывы останутся на сайте - без имени, только с инициалами и страной.

Если нужно убрать конкретный отзыв, удалите его до удаления аккаунта или напишите нам.

Sobis autole täpselt, tarne võttis kolm päeva.

✓ проверенная покупка
? Покупатель · Эстония · 3 месяца назад

user_id обнулён, автор обезличен, текст и оценка остаются. Рейтинг товара не переписывается задним числом. Право удалить конкретный отзыв при этом сохраняется: сам автор до удаления аккаунта или админ по запросу.

Что я вынес из проектирования

Для себя я вынес полезный пример вертикальной фичи, которая снаружи не совсем очевидна. Отзывы выглядят как таблица и звёзды. Внутри это сразу несколько слоёв, и их надо проектировать вместе, а не как набор тикетов.

Надо было продумать базовый функционал: кто имеет право писать, что лежит в схеме, в каких комнатах живёт отзыв. Надо было исследовать конкурентов - не чтобы скопировать экран, а чтобы увидеть, какие вопросы они уже закрыли, а какие обошли. Надо было спроектировать UI/UX для разных ширин и разных состояний: телефон и монитор, карточка с текстом и без, язык витрины и чужой текст, медиа и голый абзац.

Отдельно - кто покупает и как он добавляет отзыв. Публичной кнопки «для всех» нет. Человек приходит из письма или со страницы купленного товара. Значит форма, письмо и модерация - одна фича, а не три бэклога.

Дальше приоритет. Фичи надо класть в очередь не по красоте, а по тяжести и важности. Инвариант «отзыв без заказа не существует» дешёвый и закрывает девять десятых будущих проблем. Фото, «Полезно», аватары и экспертный значок убедительны, но каждый тянет свою таблицу, антифрод и модерацию. Скидку за вклад нельзя запускать раньше защиты от накрутки и нельзя вязать к пятёрке. Фильтр каталога по звёздам и фильтр «для моего X» выглядят как галочки в сайдбаре, а на деле требуют индекс и аккуратное семейство, не точное совпадение. Их можно отложить. То, что дорого мигрировать - обновление через год и судьба отзыва при удалении аккаунта - решить надо до запуска.

Я тут даже не вдаюсь в детали почты. Рассылать ли всем, кто когда-то купил? Как дать отписаться и подписаться снова? Как отделить это от обычных транзакционных писем? Может, не спамить всем подряд и не писать по каждой покупке. То же про модерацию: какие правила, какой процесс отказа, что видит автор, когда текст не выпускают. Это отдельные продукты внутри той же вертикали. Для старта достаточно инварианта, трёх комнат состояния и человека, который нажимает Approve или Reject.