Перейти к содержимому

Поиск в мобильном приложении

В приложении нет трекера и виджета, поэтому всё делается через API. Ключ не нужен: запросы можно отправлять прямо с устройства.

  1. ID пользователя. При первом запуске сгенерируйте UUID и сохраните (Keychain / SharedPreferences). Передавайте его как userId во все запросы и как user_id в события. Если пользователь авторизован и на сайте вы передаёте свой ID — используйте тот же, чтобы история связалась.

  2. Стартовый экран поиска. GET /api/v2/{uuid}/completions?query=&userId=… — история и популярные запросы; GET /api/{uuid}/popular?limit=10 — популярные товары.

  3. Подсказки при вводе. Debounce 150 мс, отмена предыдущего запроса:

    GET /api/v2/{uuid}/completions?query=сам&userId=…&client=mobile_app_ios
  4. Выдача и фильтры.

    GET /api/{uuid}/search?query=самоед&limit=20&skip=0&userId=…&client=mobile_app_ios&queryId=<uuid>

    Панель фильтров рисуйте из params ответа, выбранные фильтры передавайте в params (формат). Бесконечная лента — skip += limit с тем же queryId.

  5. Поиск по фото. Сожмите снимок до 512 px и отправьте POST /search с {"image":"data:image/jpeg;base64,…"} — код для iOS и Android.

  6. Карточка товара. GET /find-by-id?id=…&regionId=… — актуальные цены и наличие; под ней — GET /widgets/{id}?id=…&userId=… для похожих.

  7. События — без них не будет персонализации и статистики:

    • клик в выдаче → GET /event/click.json?type=productClick&entityId=…&queryId=…&params={"pos":N};
    • просмотр карточки, корзина, покупка → POST /event/datalayer.json с client: "mobile_app_ios".
struct SearchBooster {
static let base = URL(string: "https://api.searchbooster.net/api/\(UUID_PROJECT)")!
static let userId: String = {
if let id = UserDefaults.standard.string(forKey: "sb_user_id") { return id }
let id = UUID().uuidString
UserDefaults.standard.set(id, forKey: "sb_user_id")
return id
}()
static func search(_ query: String, skip: Int = 0) async throws -> SearchResponse {
var c = URLComponents(url: base.appendingPathComponent("search"), resolvingAgainstBaseURL: false)!
c.queryItems = [
.init(name: "query", value: query), .init(name: "limit", value: "20"),
.init(name: "skip", value: String(skip)), .init(name: "userId", value: userId),
.init(name: "client", value: "mobile_app_ios"),
]
let (data, _) = try await URLSession.shared.data(from: c.url!)
return try JSONDecoder().decode(SearchResponse.self, from: data)
}
}