Система отзывов: доверие, интерфейс и фичи
Главная мысль, с которой я начинал проектировать отзывы: сайт должен стать более заслуживающим доверия за счёт слов реальных людей. Не за счёт красивого описания от копирайтера. За счёт пользовательского контента - того, что написал человек, который уже купил, поел, нанял, попробовал.
Отзывы выглядят как двухдневная задача: таблица, звёздочки, форма. Я так и думал, пока не сел проектировать их всерьёз. Почти вся сложность лежит не в «нарисовать звёзды», а в трёх местах: кому вообще можно писать, как выглядит карточка на экране, и кто решает, что текст можно показывать людям.
Ниже - разбор с инженерной стороны. Я пишу его так, чтобы он читался про любую систему отзывов: товары в магазине, рестораны, курьеры, подрядчики, сотрудники. Меняются слова, не структура.
Зачем это бизнесу (и почему это влияет на схему)
Три цели. У каждой есть эмоция для покупателя и жёсткое требование для базы.
Доверие
Человек покупает у незнакомца, если видит опыт других. Значит отзыв обязан ссылаться на настоящую покупку, бронь или смену - не на «анонима из интернета».
Поиск
Звёзды в выдаче Google - бесплатный клик. Поисковик берёт не картинку, а два числа: среднюю оценку и сколько отзывов. Эти числа должны считаться дёшево на каждой карточке.
Меньше возвратов
«Собрал за час» или «порция холодная» описывает объект точнее карточки производителя. Значит текст важнее голых звёзд, и текст надо проверять глазами.
Это не лирика. Доверие требует доказательства. Поиск требует агрегата (среднее + счётчик). Меньше возвратов требует живого текста и модерации.
Главный инвариант: отзыв нельзя написать «из воздуха»
Самое дешёвое решение, которое отсекает 90% будущих проблем: отзыв создаётся только из подтверждённого факта. Оплаченный заказ. Состоявшаяся бронь. Закрытая смена. Принятый проект.
Цена тоже реальная: отзывов будет мало. Публичной кнопки «оставить отзыв» для всех подряд нет. Писать могут только те, кто уже взаимодействовал. Это обмен количества на доверие, и его надо проговорить с бизнесом до старта.
Схема данных
Схема - это карта ящиков. В каком ящике лежит отзыв, и на какие другие ящики он обязан ссылаться. Базовая версия - таблица отзывов, таблица переводов и два числа на объекте, про который пишут.
Две мысли, без которых схема разваливается.
Два уровня объекта. Есть конкретный опыт («я купил 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 карточек - уже дорого ради двух чисел, которые меняются раз в неделю. Пересчитываем, когда отзыв опубликовали, скрыли, поправили или удалили.
Состояние - это граф, а не флаг
Соблазн большой: колонка «опубликовано: да/нет». Уже на второй неделе появляются вопросы, на которые флаг не отвечает. Отзыв отклонили навсегда или он ждёт решения? Можно ли автору править опубликованный текст? Куда девается текст после правки?
Поэтому состояние - это карта комнат и дверей. Комната говорит, где отзыв сейчас. Дверь говорит, кто имеет право перевести его в другую комнату.
Два неочевидных перехода, из-за которых флага мало.
Правка опубликованного текста возвращает отзыв в held. Иначе модерация обходится в два шага: написал безобидное, дождался одобрения, переписал на что угодно. Смена только звёзд состояние не меняет - в цифре проверять нечего.
Отзыв без текста публикуется сразу. Человеческая проверка нужна там, где есть свободный текст. Оценка - это голос, не высказывание.
Потыкайте переходы сами
pending («принят, автоматика ещё думает»). Пока автоматики нет, в этой комнате никто никогда не находится. Мёртвое состояние в списке дороже, чем миграция, которая его добавит позже.
Как это выглядит на экране
Схема отвечает на вопрос «что можно хранить». Экран отвечает на вопрос «что человек успеет понять за три секунды». Для отзывов это важнее, чем кажется: покупатель не читает документацию, он сканирует блок глазами.
Три ширины - три раскладки
Один и тот же набор данных. Три разных способа его разложить, потому что глаз работает по-разному на телефоне, планшете и мониторе.
Переключите ширину
Ризотто горячее, грибы отличные. На двоих как раз.
✓ проверенная покупкаНа узком экране звёзды отдельной колонкой слева съедают ширину текста. Поэтому звёзды сверху одной строкой, итог по центру, текст на всю ширину.
Ризотто горячее, грибы отличные. На двоих как раз.
Шуруповёрт держит момент, но кейс пришёл с трещиной. Заменили, я потерял выходные.
На средней ширине появляется колонка звёзд слева. Глаз бежит по краю как по линейке: сразу видно пятёрки и единицы, не читая каждый текст.
Ризотто горячее, грибы отличные. На двоих как раз.
✓ покупкаШуруповёрт держит момент, но кейс пришёл с трещиной.
✓ покупкаНа мониторе итог липнет слева (как оглавление), справа - карточки по две. Длинная лента на всю ширину делает короткие отзывы пустыми полосами.
В каталоге звёзды стоят сразу под названием, до описания. Если отзывов нет - серых звёзд и «0.0» тоже нет. Строка просто отсутствует. Иначе витрина выглядит как кладбище пустых рейтингов.
Порядок внутри карточки - по важности
Человек сканирует, а не читает. Значит самое важное должно быть выше.
Анатомия карточки
Длинный текст режем примерно до пяти строк. Клик раскрывает. Иначе одна простыня ломает сетку карточек на мониторе.
Гистограмма: зачем пять полосок, если уже есть 4.6
Среднее - это одно число. Оно врёт. Товар с одной пятёркой и товар с двадцатью тройками и пятёрками могут дать похожее среднее. Полоски показывают форму распределения.
Люди интуитивно ждут «J-кривую»: много пятёрок, немного четвёрок, почти нет единиц. Если полоски плоские или перевёрнутые, средний 4.6 уже не успокаивает. Сомневающийся покупатель всё равно ищет негатив. Вопрос только в том, найдёт он его у вас за один клик или уйдёт на другой сайт.
Кликните по строке распределения. Итог 4.6 не меняется
Полоски с нулём не кликаются: пустой список выглядит как сломанный сайт. При пяти отзывах фильтры только шумят. Разумный порог показа блока - штук от десяти.
Сортировка
Три режима, которые реально нужны с первого дня. Каждый отвечает на разный вопрос читателя.
| Сортировка | Вопрос читателя | Почему не по умолчанию всегда |
|---|---|---|
| Сначала новые | «Что говорят сейчас?» | Хороший дефолт. Свежесть важнее, чем идеальный порядок. |
| Сначала критические | «Где подвох?» | Идеальный рейтинг подозрителен. Один клик до единиц повышает доверие ко всему блоку. |
| Сначала с текстом | «Хочу опыт, не голос» | Оценка без текста полезна для среднего, но в списке это пустая карточка. Её лучше не прятать, а отодвинуть вниз. |
Сортировка «сначала полезные» появится только вместе с кнопкой «Полезно». Сортировка каталога «товары с рейтингом от 4 звёзд» - тоже отдельная фича: для неё рейтинг надо класть в поисковый индекс, и каждый новый отзыв начнёт переиндексировать товар.
Подгрузка, а не простыня
На телефоне сначала 3 отзыва. На мониторе можно открыть больше. Кнопка «ещё» подгружает следующую пачку без перезагрузки страницы. Следующую пачку можно начать грузить заранее, пока человек ещё читает первую - тогда клик кажется мгновенным.
Зачем так: страница товара и без отзывов тяжёлая. Сто отзывов сразу замедлят и первый показ, и поисковую разметку (в неё попадают только реально нарисованные отзывы).
Относительное время
Пишем «2 месяца назад», а точную дату прячем в подсказку при наведении. Люди сравнивают опыт с «сейчас», а не с календарём. Отзыв 2019 года про модель 2024 года выглядит иначе, чем «2 месяца назад».
Плашка «проверенная покупка»
Это не украшение. Это перевод инварианта схемы на человеческий язык. Раз отзыв нельзя создать без заказа, мы имеем право написать это вслух. Без плашки блок выглядит как обычные комментарии, которые кто угодно мог накрутить.
Имя, страна, почему нет флагов
Публично: имя плюс первая буква фамилии («James S.»), страна словами, дата. Не полное имя, не город, не почта.
Флаг страны я сознательно не ставлю. Три причины:
- В маленькой стране имя + редкий заказ + флаг уже опознают человека. GDPR просит минимизировать.
- Флаг читается как политика, а не как «откуда заказ».
- Слово «Эстония» понятно скринридеру и в чёрно-белой печати. Иконка флага - нет.
Город не показываем по той же причине минимизации. Страны достаточно, чтобы понять контекст («пишут ли люди с моего рынка»).
Один отзыв, несколько моделей. Аналогия с MacBook
Представьте Apple. «MacBook Pro 14"» - это карточка товара. Space Gray 512 ГБ и Silver 1 ТБ - это варианты. Человек купил 512 ГБ. Его опыт почти целиком про тот же ноутбук: экран, клавиатура, нагрев. Но батарея и вес уже другие.
Поэтому отзыв пишут на купленный вариант, а показывают на всех вариантах той же карточки. И обязательно помечают: «это про 512 ГБ», если вы сейчас смотрите страницу 1 ТБ.
Один и тот же отзыв на двух страницах
Тихий, экран отличный. К вечеру батареи как раз хватает на рабочий день.
✓ проверенная покупка ✓ именно эта модель · 512 ГБТихий, экран отличный. К вечеру батареи как раз хватает на рабочий день.
✓ проверенная покупка заказана другая модель · 512 ГБ →То же в ресторане: отзыв про «Цезарь с курицей» виден на странице «Цезарь с креветками», но бейдж говорит «человек заказывал курицу». У работника: отзыв про ремонт ванной виден в профиле, но помечен как «ванная, не кухня». Агрегат (среднее по карточке) считается по всем вариантам вместе. Иначе у каждого артикула будет по одному отзыву, и статистика никогда не сложится.
Как добиться, чтобы отзывы вообще писали
Форма может быть идеальной. Без письма после доставки её почти никто не откроет. Люди не просыпаются с желанием написать отзыв. Им нужно напомнить в тот момент, когда опыт уже есть, но ещё не забыт.
Первое письмо
Здравствуйте, Мари!
Заказ #R123456789 доехал две недели назад. Как вам шуруповёрт? Ваша оценка помогает другим выбрать.
Не хотите такие письма? Отписаться
Важные мелочи. Письмо не просит пять звёзд, оно просит опыт. Отписка - отдельное подтверждение, а не ссылка, которая молча меняет настройку по GET (почтовые роботы такое открывают сами). Форма живёт на отдельной странице: в строке заказа места хватает только на кнопку.
Форма и модерация
Без этого блока отзывы не живут: человек должен суметь написать, а человек из поддержки - решить судьбу текста.
Как человек доходит до формы
Две точки входа, один контроллер. Либо письмо после доставки ведёт в заказ, и оттуда - в форму по позиции. Либо человек сам открывает страницу купленного товара (или соседнего варианта) и видит форму, потому что у него уже есть подходящий заказ.
Публичной кнопки «для всех» нет. Ссылка из письма отзыв не создаёт: она только открывает заказ. Форма живёт на отдельной странице - в строке заказа места хватает только на кнопку.
Форма
Обязательное поле одно - звёзды. Текст по желанию.
Очередь плюс письмо
Админка - место, куда заходят, когда уже сидят за компьютером. Отзыв приходит когда угодно. Поэтому на каждый текстовый отзыв в 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 |
Здесь появляется комната pending: «принят, автоматика думает». Теперь в ней реально кто-то находится - несколько секунд.
На экране всегда один текст, как у Airbnb. Кнопка не открывает второй блок, а заменяет абзац. Если язык отзыва совпал с языком витрины, кнопки нет.
Переключатель перевода
Ризотто пришло горячим, грибы отличные. На двоих как раз.
Почему одной шкалы 1-5 мало
«Четыре звезды» - это не смысл. Это сжатие. Один человек так сказал, потому что ризотто отличное, а ждали долго. Другой - потому что шуруповёрт средний, но приехал быстро. Третий оценил официанта, а не блюдо. Читатель этого не видит.
Плоская шкала хорошо работает как голосовалка и как число для Google. Как объяснение опыта - плохо. Именно поэтому на экране текст стоит выше автора, а гистограмма важнее среднего: они хотя бы показывают разброс.
Несколько осей помогают - и всё равно ограничивают
Следующий соблазн: вместо одной звезды спросить шесть. В ресторане - вкус, порция, ожидание, цена, обслуживание, атмосфера. У инструмента - момент, удобство, батарея, шум, кейс, цена. На экране это радар. Покупатель видит не «4.3», а «еда отличная, ждали долго».
Плюс для компании: систематически низкое «ожидание» - это претензия к смене, не к кухне. Оси заполняются кликами, их не надо переводить и модерировать.
Цена: шесть вопросов вместо одного убивают и так редкие отзывы. Google всё равно берёт одно число. Если оси необязательные, у одной будет 3 голоса, у другой 20 - радар начнёт врать, и ось придётся прятать до порога.
Оси полезны как каталог тем. Они не заменяют живой рассказ. Человек всё равно напишет то, что вы не предусмотрели: «биты в комплекте нормальные, а замок на кейсе так и не открылся с первого раза». Шкала это не поймает.
AI-отзывы как ответ на оба ограничения
Люди плохо пишут в пустое поле. Получается «отлично» или жалоба на доставку. Несколько осей это чинят частично, ценой трения. Более сильный ход - короткий диалог.
Диалог вместо пустого поля
Бот собирает черновик. Человек правит и подтверждает. Звёзды по-прежнему ставит сам. Можно закрыть чат и оставить только оценку. Дальше обычный путь: текст в held, Approve человека.
Когда отзывов много, второй AI-слой - сводка «что хвалят / что ругают» над списком. Не замена отзывам, а оглавление. Порог примерно 20 текстов: на пяти отзывах один громкий минус выглядит как мнение всех.
- Ровный момент, биты не слизывает
- Порции честные, грибы свежие
- Замок кейса тугой
- Ждали сорок минут
Риски: одинаковый «голос магазина», юридическая пометка «собрано с помощником», галлюцинации в сводке. Звёзды при этом остаются фактом из базы. Если модель ошиблась, среднее всё равно честное.
Контекст автора
Для ресторана главный вопрос - повод визита: бизнес-ланч и день рождения читаются по-разному. Для инструмента - задача: собрал полку или крутил каркас. Для подрядчика - тип объекта. «Идеально подошло» бесполезно, если у автора другой контекст.
Данные часто уже есть в заказе. Одна колонка на отзыв, фильтр по семейству, не по точному совпадению: иначе фильтр всегда пустой. Точный адрес и госномер в публичный блок не попадают никогда.
Обновление через 6-12 месяцев
Через две недели человек скажет «быстро приехало». Через год он знает главное: выдержало или нет. Этого не будет у конкурента, который спрашивает на второй день.
Первый отзыв и поздняя правка опыта
Собрал кухню за выходные. Момент ровный, биты не слизывает.
На стройке батарея села быстрее обещанного. Замок кейса так и остался тугим. Купил бы снова из-за момента.
Технически лучше отдельная связанная строка с ссылкой на родителя, а не поля внутри того же отзыва: обновление проходит ту же модерацию и перевод. В среднем рейтинге ветка считается за один голос, берём последнюю оценку. Иначе один человек голосует дважды. Это как раз то решение, которое дорого менять после запуска.
Фото и видео
Самый убедительный формат и самый тяжёлый: приём файлов, ресайз, превью, антивирус, модерация картинок, для видео ещё транскодинг. Плюс согласие на публикацию и удаление всех копий по GDPR.
Если медиа всё же появятся, в списке они должны стоять выше голого текста: глаз цепляется за фото сильнее, чем за дату. Рейтинг объекта от порядка списка не меняется.
Сначала отзывы с медиа, фото раскрывается на месте
Внутри группы - новые первыми. Рейтинг не меняется.
Ризотто горячее, грибы отличные. Прикладываю фото тарелки и короткое видео.
✓ проверенная покупкаДержит момент ровно. Кейс удобный, замок тугой.
✓ проверенная покупкаОтзыв Marek новее, но стоит вторым: медиа перевешивает дату.
Почему не модалка: текст отзыва остаётся на экране, картинка читается вместе с тем, что человек про неё написал. Отдельное окно обрывает чтение и ломает «назад» на телефоне.
«Полезно» и центр автора
Голос других читателей даёт сортировку «сначала полезные» и мотивацию писать содержательнее. Цена: новая таблица голосов и защита от накрутки. Подпись «Полезно» важнее лайка: человек оценивает пользу опыта, а не соглашается со звёздами. Голос рейтинг объекта не меняет.
Кнопка на карточке и личный раздел
Ризотто горячее, грибы отличные. На двоих как раз. Если придёте вдвоём - берите ещё салат.
✓ проверенная покупка2 месяца назад · опубликован
Горячее, грибы отличные. На двоих как раз.
♡ Полезно · 183 недели назад · проверяется
Момент ровный, биты нормальные. Замок тугой.
⏳ проверяетсяГолосовать может только вошедший пользователь, нельзя голосовать за свой отзыв, один активный голос на пару «человек + отзыв». Гость видит счётчик, но клик просит вход и число заранее не увеличивает. Иначе один браузер превращается в сотни лайков очисткой cookie.
Аватары
Живое лицо рядом с отзывом делает его похожим на слова человека, а не на строку в базе. Три источника по приоритету, ни один не обязателен: своё фото в кабинете, Gravatar по хэшу почты, буква в круге как запасной слой.
Одно и то же место: фото, identicon, буква
Ризотто горячее, грибы отличные. На двоих как раз.
✓ проверенная покупкаДержит момент ровно, биты не слизывает.
✓ проверенная покупкаВкусно, но ждали сорок минут.
✓ проверенная покупкаGravatar - запрос из браузера читателя к третьей стороне: она видит хэш почты и IP. Без явного согласия и строки в политике приватности так нельзя. Покрытие в обычных магазинах низкое, поэтому основной эффект даёт только своя загрузка. Своё фото без модерации публиковать нельзя: на витрине окажется чужое лицо или что угодно ещё.
Публичный ответ и репутация бренда
Короткая реплика под негативом снимает яд для всех будущих читателей, не только для одного жалобщика. Технически просто. Организационно тяжело: кто отвечает, в какой срок, на каком языке, уходит ли письмо автору.
Ответ вложен под отзыв, это не второй отзыв
Порция пришла тёплой, салат размяк. Само ризотто нормальное, но вечер уже был испорчен.
✓ проверенный визитИзвините за ожидание и тёплый салат. Мы сменили смену на этот слот и прислали вам ваучер на следующий визит. Если что-то ещё не так - ответьте на письмо заказа.
Правила, без которых ответ вредит: отвечать не только на единицы, не спорить с автором, не светить номер заказа, один ответ на отзыв. Диалог уводим в поддержку, публично оставляем итог.
Агрегат по всем товарам бренда (или по всем сменам сотрудника) превращает ручную плашку «премиум» в доказуемое число. Нужна защита от маленькой выборки: одна пятёрка не должна поднимать бренд выше того, у кого тысяча честных 4.6. И нельзя прятать слабые категории внутри красивого среднего.
Страница «как мы работаем с отзывами»
В ЕС, если вы показываете отзывы, вы скорее обязаны объяснить: проверяете ли, что их оставили реальные покупатели, и как именно. Хорошая новость: при схеме «отзыв обязан ссылаться на заказ» эта страница пишется за десять минут и звучит убедительно. Ссылка - спокойная сноска рядом с заголовком блока, не баннер «нам можно доверять».
Сноска у блока и сама страница
Отзывы гостей
Как мы работаем с отзывами →- Писать может только тот, кто уже заказал, поел или закрыл смену. Публичной кнопки «для всех» нет.
- Мы не платим за отзыв и не просим пять звёзд.
- Негатив не удаляем. Скрываем только спам, персональные данные и текст не по теме.
Приватность: единственное необратимое действие
Отзыв - место, где частное действие становится публичным. Два решения надо принять явно.
Что показывать. Имя плюс буква фамилии, страна словами, относительная дата. Всё остальное из заказа наружу не выходит.
Что остаётся после удаления аккаунта. Если отзывы исчезают вместе с аккаунтом, средний рейтинг товара переписывается задним числом. Если остаются, их надо обезличить. Оба варианта защитимы. Выбрать надо до запуска и написать это на экране удаления аккаунта, не только в политике.
Что я вынес из проектирования
- Доверие - цель, схема - инструмент. Пользовательский контент повышает доверие только если его нельзя накрутить и легко прочитать.
- Инвариант в базе дешевле антифрода. Отзыв без заказа не существует.
- Переводы - отдельная таблица и отдельное решение. Оригинал живёт в отзыве, строки витрины - в
review_translations. Набор языков сайта заранее дешевле модерировать, чем перевод по запросу зрителя. - Экран не менее схемы. Порядок в карточке, гистограмма, сортировка «критические сначала» и бейдж проверенной покупки - это и есть перевод инварианта на человеческий язык.
- Два уровня объекта обязательны. Конкретный опыт и сущность репутации. Аналогия с MacBook работает в любом домене.
- Состояние - граф. Флага «опубликовано» хватает на неделю.
- Одной шкалы мало, шести осей часто тоже мало. Живой текст плюс, когда-нибудь, диалог с моделью закрывают смысл лучше, чем ещё один ряд звёзд.
- LLM вторым шагом, не первым. Ручная модерация даёт примеры того, что реально приходит. Промпт до живых отзывов ловит воображаемые проблемы.
- До запуска надо решить только то, что дорого мигрировать: формат обновления через год и судьба отзыва при удалении аккаунта. Остальное - по данным.