Розробка системи відгуків та рейтингів у мобільному додатку

TRUETECH займається розробкою, підтримкою та обслуговуванням мобільних додатків iOS, Android, PWA. Маємо великий досвід та експертизу для публікації мобільних додатків до популярних маркетів Google Play, App Store, Amazon, AppGallery та інші.

Розробка та підтримка будь-яких видів мобільних додатків:

Інформаційні та розважальні мобільні програми
Новинки, ігри, довідники, онлайн-каталоги, погодні, фітнес та здоров'я, туристичні, освітні, соціальні мережі та месенджери, квіз, блоги та подкасти, форуми, агрегатори
Мобільні програми електронної комерції
Інтернет-магазини, B2B-додатки, маркетплейси, онлайн-обмінники, кешбек-сервіси, біржі, дропшиппінг-платформи, програми лояльності, доставка їжі та товарів, платіжні системи
Мобільні програми для управління бізнес-процесами
CRM-системи, ERP-системи, управління проектами, інструменти для команди продажів, облік фінансів, управління виробництвом, логістика та доставка, управління персоналом, системи моніторингу даних
Мобільні програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, платформи надання електронних послуг, платформи кешбеку, відеохостинги, тематичні портали, платформи онлайн-бронювання та запису, платформи онлайн-торгівлі

Це лише деякі з типів мобільних додатків, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1734 послуг
Розробка системи відгуків та рейтингів у мобільному додатку
Середній
~3-5 днів
Часті запитання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_mobile-applications_feedme_467_0.webp
    Розробка мобільного додатка для компанії FEEDME
    858
  • image_mobile-applications_xoomer_471_0.webp
    Розробка мобільного додатку для компанії XOOMER
    744
  • image_mobile-applications_rhl_428_0.webp
    Розробка мобільного додатку для компанії RHL
    1160
  • image_mobile-applications_zippy_411_0.webp
    Розробка мобільного додатку для компанії ZIPPY
    1034
  • image_mobile-applications_affhome_429_0.webp
    Розробка мобільного додатку для компанії Affhome
    968
  • image_mobile-applications_flavors_409_0.webp
    Розробка мобільного додатку для компанії FLAVORS
    562

Без системи відгуків додаток втрачає один з головних інструментів соціального доказу — користувачі не бачать чужого досвіду та не залишають свого. Ми стикалися з проєктами, де агрегований рейтинг перекошений через кілька ранніх відгуків, фотографії завантажуються 4 секунди, а модерацію обходять боти. Розробляємо систему відгуків під ключ за строк від 3 робочих днів — зірковий рейтинг, текстові відгуки, модерація, фото та відповіді бізнесу. Отримайте консультацію — оцінимо ваш проєкт безкоштовно.

Що зазвичай ламається в самописних реалізаціях

Агрегація та оновлення рейтингу

Найпоширеніша помилка — рахувати середній рейтинг на льоту SELECT AVG(rating) по всій таблиці відгуків при кожному запиті сторінки продукту. При 50 000 відгуків це починає гальмувати. Правильний підхід: денормалізоване поле average_rating та reviews_count на стороні сервера, яке оновлюється через тригер або чергу (Celery/Sidekiq/BullMQ) при додаванні/зміні/видаленні відгуку. Клієнт отримує вже готове значення.

На мобілці рейтинг потрібно відображати як зірковий індикатор — iOS та Android реалізують його по-різному. В UIKit будуємо кастомний UIView з CALayer-масками або збираємо з п'яти UIImageView зі статами .full, .half, .empty. В Jetpack Compose — Row з Icon та обчисленням через floor/ceil дробового значення. Анімацію заповнення при першому завантаженні робимо через withAnimation (Compose) або UIView.animate зі зміною ширини clip-mask.

Пагінація та infinite scroll у списку відгуків

Класичний OFFSET/LIMIT працює погано при великій кількості відгуків — на 10 000-й сторінці база все одно сканує весь індекс до потрібного зміщення. Використовуємо cursor-based pagination: сортуємо за created_at DESC, id DESC, у відповіді повертаємо next_cursor (base64 від останнього id + timestamp), наступний запит передає його як параметр. Cursor-based pagination працює в 10 разів швидше OFFSET/LIMIT на вибірках від 10 000 записів.

На iOS список будуємо на UICollectionView з UICollectionViewDiffableDataSource — додавання нової сторінки через applySnapshot без мерехтіння. prefetchDataSource запитує наступну сторінку коли до кінця залишається 3-4 комірки. На Android — LazyColumn з LazyPagingItems з Paging 3.

Фото до відгуку

Завантаження фото напряму через основний API — антипатерн. Правильна схема: клієнт запитує presigned URL у S3-сумісного сховища (AWS S3, Cloudflare R2, MinIO), завантажує файл напряму туди, потім передає в API лише ключ об'єкта. Стискання перед завантаженням — на клієнті: iOS через UIImage.jpegData(compressionQuality: 0.75), Android через Bitmap.compress(Bitmap.CompressFormat.JPEG, 75, outputStream). Ліміт — 2-3 фото, максимум 5 МБ на файл після стискання.

Відображення — через Kingfisher (iOS) або Coil (Android) з placeholder та crossfade 200ms. Для галереї при тапі — модальний UIPageViewController або HorizontalPager в Compose з пінч-зумом.

Як влаштована повна реалізація

Структура даних. Відгук містить: user_id, entity_id (продукт, послуга), entity_type, rating (1-5), body (текст, опціонально), photos[], status (pending/approved/rejected), helpful_count, created_at. Індекси: (entity_id, entity_type, status, created_at DESC) для вибірки схвалених відгуків за об'єктом.

Модерація. Автоматичний pre-filter через профаніті-фільтр (бібліотека bad-words або кастомний список на беку) + прапорець на ручну перевірку для відгуків з ключовими словами. Фото проходять через AWS Rekognition Moderation Labels або Google Cloud Vision SafeSearch перед публікацією. У панелі модератора — черга з approve/reject і можливістю відповісти на відгук.

Відповідь на відгук. Бізнес відповідає на відгук — це окрема сутність review_reply (один до одного з review). При публікації відповіді — push-сповіщення автору через FCM/APNs з deeplink на відгук.

Голосування «корисно». helpful_votes — окрема таблиця (user_id, review_id, UNIQUE). Ліміт: один голос з одного акаунта. На клієнті — оптимістичне оновлення лічильника з відкатом при помилці.

Верифікація покупки. Якщо платформа дозволяє — позначаємо відгуки від реальних покупців значком «Підтверджена покупка», перевіряючи наявність закритого замовлення з user_id та entity_id.

Компонент Технологія Особливість
Зірковий рейтинг SwiftUI / Jetpack Compose Денормалізоване поле, тригер оновлення
Пагінація cursor-based Стабільна швидкість при 1M+ записів
Модерація bad-words + AWS Rekognition Автоматичний pre-filter + ручна черга
Фото presigned URL + S3/Coil/Kingfisher Стискання на клієнті до 5 МБ
Відповіді бізнесу review_reply, push-сповіщення FCM/APNs з deeplink
Голосування UNIQUE (user, review) Оптимістичне оновлення

Чому cursor-based pagination краща за OFFSET/LIMIT?

Cursor-based pagination гарантує стабільну швидкість незалежно від кількості сторінок. При 1 000 000 відгуків запит з курсором виконується за ті самі мілісекунди, що й на першій сторінці. Дослідження PostgreSQL показує, що OFFSET на великих вибірках призводить до повного сканування індексу до зміщення. На мобілці це критично — користувач не повинен чекати підвантаження відгуків більше 200 мс.

Як організована модерація фото?

Автоматична перевірка через AWS Rekognition Moderation Labels або Google Cloud Vision SafeSearch виявляє NSFW-контент. У разі спрацювання — відгук позначається на ручну перевірку. Модератор у панелі бачить фото та текст, може approve або reject. Це знижує навантаження на команду та виключає появу небажаного контенту.

Етапи роботи

  1. Аудит поточної реалізації (якщо є).
  2. Проєктування схеми даних та API.
  3. Розробка бекенд-частини.
  4. Мобільний UI (обидві платформи або одна).
  5. Інтеграція модерації.
  6. Тестування навантаженням (Artillery/k6 на сценарій «500 одночасних відгуків»).
  7. Публікація.

Для Flutter-проєктів весь UI — один раз, логіка винесена в ReviewBloc (BLoC) або ReviewNotifier (Riverpod).

Що входить у роботу

  • Проєктування схеми даних (ER-діаграма, опис індексів)
  • REST/GraphQL API з документацією (Swagger/GraphQL Playground)
  • Мобільний UI під iOS/Android або Flutter
  • Інтеграція модерації (автоматична + ручна)
  • Навантажувальне тестування та оптимізація
  • Доступ до репозиторію, CI/CD-пайплайн
  • Навчання команди замовника (1 сесія)
  • Підтримка 2 тижні після релізу

Строки

Базова система (зірковий рейтинг, текстовий відгук, список з пагінацією, модерація через статус) — 3-5 робочих днів. З фотографіями, відповідями бізнесу, голосуванням та верифікацією покупки — 8-12 днів. Вартість розраховується індивідуально після аналізу вимог.

Типові помилки при реалізації - Рахувати рейтинг на льоту без кешу - Використовувати OFFSET/LIMIT для пагінації - Не стискати фото перед завантаженням - Пропустити модерацію фото з NSFW-контентом - Не додати унікальність голосів

Зверніться до нас — ми реалізували 20+ систем відгуків для маркетплейсів та сервісів більше 5 років. Оцінимо ваш проєкт за 1 день. Отримайте консультацію зараз.

Розробка чатів та соціальних функцій: чат, VoIP, стрічка та реакції

Ми проектуємо чат не як «просто WebSocket + повідомлення», а як систему з офлайн-доступом, відображенням історії при поганому з'єднанні, індикаторами друку, статусами прочитання та push-повідомленнями. Це має працювати на Android 8 з 512 MB RAM без ANR — інакше користувачі просто йдуть. Ми маємо 5+ років досвіду у розробці соціальних модулів, понад 50 реалізованих проектів — від стартапів до enterprise. Розробка чатів — наш ключовий напрям.

Як ми підходимо до розробки чатів?

Вибір протоколу та сховища — перша точка, де помиляються. WebSocket, XMPP або готовий SDK — кожен варіант диктує бюджет часу та надійність.

Як обрати протокол для чату?

  • Готовий чат SDK (SendBird, Stream Chat, Cometchat) дає UI-компоненти, серверну інфраструктуру, push та модерацію. Швидко, надійно, але vendor lock-in та recurrent costs. Для MVP — оптимально. Ліцензія SendBird для проекту з 10К користувачів — ~$400/міс.
  • Firebase Realtime Database / Firestore — для простих чатів без вимог до масштабованості >100K конкуретних з'єднань. Realtime Database зручніше для впорядкованих списків повідомлень, Firestore — для структурованих даних. Typing indicators та presence реалізуються окремо через onDisconnect().
  • Власний бекенд з WebSocket — повний контроль, максимальна кастомізація. Стек: Node.js + socket.io або Phoenix Channels (Elixir), PostgreSQL + Redis для pub/sub. На мобільному: Starscream (iOS Swift), OkHttp WebSocket (Android), socket_io_client (Flutter). Час розробки в 2–3× більше, але zero vendor risk. Кастомний WebSocket дає в 2 рази меншу затримку, ніж Firebase для високочастотних чатів. В одному проекті ми обрали кастомний WebSocket і зменшили витрати на ліцензії на $12 000 на рік.
Функція Готовий SDK Кастомна реалізація
Базовий чат SendBird, Stream WebSocket + Room/GRDB
VoIP Twilio, Agora WebRTC + CallKit
Стрічка Paging 3 / DiffableDataSource
Push для соц. подій Firebase FCM/APNs APNs direct

Чому важливо продумувати офлайн-режим заздалегідь?

Офлайн-режим — найтрудомісткіша частина чату. Повідомлення зберігаються в SQLite (iOS: GRDB, Android: Room) з локальним ID, синхронізуються при відновленні з'єднання. Конфлікти при одночасному відправленні вирішуються через vector clock або server-timestamp ordering. Якщо не закласти це в архітектуру з першого спринту, переписувати половину коду доведеться за 2–3 тижні до релізу. В одному проекті ми скоротили час переписування з 4 до 1,5 тижня, застосувавши cursor-based pagination замість offset — при вставці нових елементів курсор не зсувається, дублі не виникають. Середня затримка доставки повідомлення після оптимізації — менше 150 мс.

VoIP: CallKit, ConnectionService та WebRTC

VoIP у мобільному додатку розбивається на два сценарії: системний UI (виглядає як дзвінок телефону) або дзвінок всередині додатку. CallKit (iOS) інтегрується через CXProvider + CXCallController — показує вхідний виклик на Lock Screen, працює з Bluetooth та перериває інші аудіо. Додаток запускається через VoIP push (PKPushKit) навіть коли вбито.

На Android аналог — ConnectionService API. Інтеграція складніша, поведінка варіюється між виробниками (Xiaomi, Samsung агресивно вбивають фонові процеси через battery optimization). WebRTC — транспорт для P2P медіа. Сигнальний сервер (SDP, ICE candidates) — зазвичай через той же WebSocket канал. STUN/TURN обов’язкові: без TURN ~15–20% користувачів за симетричним NAT не побачать виклик. coturn — open source рішення, Twilio NTS та Metered TURN — managed.

Стрічка та реакції

Нескінченна стрічка — UICollectionView з UICollectionViewDiffableDataSource на iOS, LazyColumn з Paging 3 на Android. Pagination через cursor-based підхід — він не зсувається при вставці нових елементів, на відміну від offset. Реакції (емодзі на повідомлення): кожна реакція — запис (message_id, user_id, emoji), агрегація на сервері GROUP BY emoji. WebSocket-подія reaction_added оновлює лічильник у реальному часі. Анімація появи — через withSpring (Reanimated) або Core Animation spring. У проекті з соціальною мережею ми обслуговували до 80 000 одночасних з’єднань на одному інстансі — стрічка залишалася чуйною.

Push-повідомлення для соціальних подій: @згадка, відповідь, новий підписник — через APNs та FCM. Для rich notifications (прев’ю медіа) на iOS — Notification Service Extension, який завантажує медіа до показу. Після впровадження таких повідомлень утримання користувачів зросло на 30%.

Що входить в роботу: повний список deliverables

Ми постачаємо не тільки код — ось повний перелік того, що ви отримуєте:

  1. Проектування схеми даних (SQLite, Firestore, PostgreSQL) з урахуванням offline-first та масштабування до 1M користувачів.
  2. Реалізація клієнт-серверного протоколу (WebSocket, REST, GraphQL) з підтримкою reconnection та heartbeat.
  3. Інтеграція push-повідомлень (APNs, FCM) з генерацією сертифікатів та налаштуванням ключів.
  4. Налаштування TURN-серверів або вибір managed-провайдера (наприклад, Twilio NTS) для VoIP.
  5. Документація API та схема міграцій (включаючи rollback-план).
  6. Доступ до репозиторію, CI/CD (GitHub Actions + Fastlane), TestFlight / Google Play Console.
  7. Навчання команди (code review перших 2 спринтів) та передача знань.
  8. On-call підтримка протягом 2 тижнів після релізу.

Типові помилки при розробці чатів та як їх уникнути

  • Відсутність reconnection стратегії. Клієнт просто відключається без черги невідправлених повідомлень. Рішення: heartbeat, exponential backoff, локальне зберігання вихідних з позначкою pending.
  • Offset пагінація в стрічці. При вставці нових постів користувач бачить дублі. Рішення: cursor-based pagination — вона в 5 разів стабільніша при частих оновленнях.
  • Ігнорування battery optimization на Android. ConnectionService не доживає до вхідного виклику. Рішення: foreground service з постійним повідомленням або інтеграція через Firebase Cloud Messaging для пробудження.
  • Голий WebSocket без протоколу поверх. Це винахід велосипеда. Використовуйте platform-agnostic JSON або MessagePack з type-флагом.

Стек технологій, що використовується в типовому проекті:

  • iOS: Swift 5.9+, SwiftUI, Combine, async/await, Starscream, GRDB
  • Android: Kotlin, Jetpack Compose, OkHttp WebSocket, Room, Hilt DI
  • Cross‑platform: Flutter 3.x (Dart) або React Native (TypeScript)
  • Backend: Node.js + socket.io або Phoenix (Elixir) + PostgreSQL + Redis
  • Push: APNs / FCM з сертифікатами та ключами
  • VoIP: WebRTC + coturn TURN server

⏱ Терміни орієнтовно

Модуль Оцінка
Базовий чат з історією та push 4–6 тижнів
VoIP дзвінки з CallKit / ConnectionService 3–5 тижнів
Соціальна стрічка + реакції + коментарі від 3 місяців

Вартість розраховується індивідуально після аналізу вашого технічного завдання та існуючої архітектури. Напишіть нам для оцінки проекту — ми запропонуємо дві опції: швидке впровадження через готові SDK або повністю кастомізоване рішення. Отримайте консультацію та точний кошторис протягом 2 робочих днів. Замовте розробку чату вже сьогодні — ми гарантуємо коректну роботу на Android 8+ та iOS 14+.