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

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

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

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

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

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

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

🤝

Доверие

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

🔎

Поиск

Звёзды в выдаче 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» тоже нет. Строка просто отсутствует. Иначе витрина выглядит как кладбище пустых рейтингов.

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

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

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

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

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

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

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

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

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

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

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

Сортировка

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

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

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

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

На телефоне сначала 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 ГБ →

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Две точки входа, один контроллер. Либо письмо после доставки ведёт в заказ, и оттуда - в форму по позиции. Либо человек сам открывает страницу купленного товара (или соседнего варианта) и видит форму, потому что у него уже есть подходящий заказ.

Покупатель Письмо Сайт заказ или товар Форма из письма ≈ 14 дней · ссылка на заказ открыл заказ кнопка «оценить» со страницы товара зашёл на купленный товар тот же контроллер звёзды, текст по желанию текст → held и письмо в поддержку · без текста → сразу 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 и в придачу только плохие тексты. Фильтр живёт внутри фрагмента страницы и канонический адрес не трогает.

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

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

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

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

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

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

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

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

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

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

M Mari K. Эстония

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

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

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

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

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

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

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

Вкус 4.8 Порция 4.4 Обслуживание 4.6 Цена 4.1 Ожидание 3.6 Атмосфера 4.2

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

M Mari K.

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

Фото и видео

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

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

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

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

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

✓ проверенная покупка
фото 1
фото 2
видео 0:14 ▶
J James S. · 2 месяца назад

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

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

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

фото 1
фото 2
видео 0:14 ▶
фото 1 · тарелка крупно
1 из 3 · загружено гостем

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

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

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

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

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

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

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

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

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

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

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

Аватары

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

Одно и то же место: фото, identicon, буква

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • Доверие - цель, схема - инструмент. Пользовательский контент повышает доверие только если его нельзя накрутить и легко прочитать.
  • Инвариант в базе дешевле антифрода. Отзыв без заказа не существует.
  • Переводы - отдельная таблица и отдельное решение. Оригинал живёт в отзыве, строки витрины - в review_translations. Набор языков сайта заранее дешевле модерировать, чем перевод по запросу зрителя.
  • Экран не менее схемы. Порядок в карточке, гистограмма, сортировка «критические сначала» и бейдж проверенной покупки - это и есть перевод инварианта на человеческий язык.
  • Два уровня объекта обязательны. Конкретный опыт и сущность репутации. Аналогия с MacBook работает в любом домене.
  • Состояние - граф. Флага «опубликовано» хватает на неделю.
  • Одной шкалы мало, шести осей часто тоже мало. Живой текст плюс, когда-нибудь, диалог с моделью закрывают смысл лучше, чем ещё один ряд звёзд.
  • LLM вторым шагом, не первым. Ручная модерация даёт примеры того, что реально приходит. Промпт до живых отзывов ловит воображаемые проблемы.
  • До запуска надо решить только то, что дорого мигрировать: формат обновления через год и судьба отзыва при удалении аккаунта. Остальное - по данным.