> For the complete documentation index, see [llms.txt](https://docs.fstrk.io/knowledge_base/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.fstrk.io/knowledge_base/intagrations/mobilnoe-prilozhenie.md).

# Мобильное приложение

Если ваше мобильное приложение должно поддерживать переписку с оператором или ботом, не нужно разрабатывать чат с нуля. Виджет Fasttrack встраивается в нативное приложение через стандартный компонент `WebView`: приложение открывает обычную HTML-страницу со скриптом виджета, а дальше всё работает само. В этой статье — как настроить страницу, передать идентификатор пользователя и подготовить приложение к работе на Android и iOS.

***

### Предварительные требования

Прежде чем начать, убедитесь, что у вас есть:

* Доступ к личному кабинету Fasttrack с правами на просмотр настроек виджета.
* Созданный виджет в разделе [**Маркетинг → Виджет**](https://my.fstrk.io/campaigns/widget).
* UUID виджета — уникальный идентификатор вида `4bb3a79e-8075-4244-9440-cd266790cf1c`. Где взять: откройте нужный виджет → вкладка **«Общие»** → блок **«Скрипт для мобильного приложения (WebView)»**. Там же готовый сниппет с кнопкой «Копировать».

<figure><img src="/files/RQKDZ2eVJsLMF6ZTsJQ3" alt=""><figcaption></figcaption></figure>

* Для мобильного разработчика: доступ к исходному коду приложения и возможность добавить или изменить компонент `WebView`.

***

### Пошаговая инструкция

#### Шаг 1. Получите скрипт виджета в админке

1. Перейдите в [**Маркетинг → Виджет**](https://my.fstrk.io/campaigns/widget) и выберите нужный виджет.
2. Откройте вкладку **«Общие»** и найдите блок **«Скрипт для мобильного приложения (WebView)»**.

   <figure><img src="/files/Y52JxO65h0au4YNYoL7q" alt=""><figcaption></figcaption></figure>
3. Нажмите **«Копировать»** — вы получите готовый тег `<script>` с вашим UUID.

***

#### Шаг 2. Создайте HTML-страницу для WebView

Создайте на вашем сервере (или в ресурсах приложения) HTML-файл и вставьте скопированный скрипт. Минимально рабочий вариант:

```html
<!DOCTYPE html>
<html lang="ru">
<head>
  <meta charset="UTF-8">
  <meta name="viewport"
        content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0, viewport-fit=cover">
  <style>
    html, body { margin: 0; padding: 0; height: 100%; background: #fff; }
  </style>
</head>
<body>
  <script async
    src="https://cdn.fstrk.io/widget3-cdn/<UUID-ВИДЖЕТА>.js"
    data-webview></script>
</body>
</html>
```

Замените `<UUID-ВИДЖЕТА>` на ваш UUID из предыдущего шага, либо вставьте скопированный скрипт из предыдущего пункта.

> **Важно:** Атрибут `data-webview` обязателен. Именно он переключает виджет в режим «только чат» — полноэкранный, без кнопки запуска, без обложки и без кнопки закрытия. Без этого атрибута откроется обычный виджет для сайта, который не подходит для встраивания в приложение.

***

#### Шаг 3. Передайте идентификатор пользователя (рекомендуется)

Чтобы пользователь при повторном открытии приложения — или на другом устройстве — видел свою прежнюю переписку, передайте его стабильный идентификатор в значении атрибута `data-webview`:

```html
<script async
  src="https://cdn.fstrk.io/widget3-cdn/<UUID-ВИДЖЕТА>.js"
  data-webview="a3f1c9e2-7b4d-4f8a-9c11-2e6d5b8a1f30"></script>
```

Если значение не передать, виджет сгенерирует временный идентификатор и сохранит его в `localStorage` WebView. Переписка сохранится, пока пользователь не очистит кэш приложения — но при переустановке или на другом устройстве будет потеряна.

**Требования к идентификатору**

Идентификатор должен быть:

* **Стабильным** — одним и тем же для одного пользователя при каждом входе.
* **Неугадываемым** — UUID или криптографический хэш. Не используйте телефон, e-mail, порядковый номер или любое другое предсказуемое значение.

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

✅ Правильно: `data-webview="a3f1c9e2-7b4d-4f8a-9c11-2e6d5b8a1f30"`\
❌ Неправильно: `data-webview="42"`, `data-webview="+79991234567"`

***

#### Шаг 4. Передайте данные пользователя для оператора (необязательно)

Если вы хотите, чтобы оператор в чат-центре видел имя и контакты клиента, а не безликий «Web site user», добавьте атрибуты `data-user-*`:

```html
<script async
  src="https://cdn.fstrk.io/widget3-cdn/<UUID-ВИДЖЕТА>.js"
  data-webview="a3f1c9e2-7b4d-4f8a-9c11-2e6d5b8a1f30"
  data-user-name="Иван Петров"
  data-user-phone="+79991234567"
  data-user-email="ivan@example.com"></script>
```

| Атрибут           | Что передаёт            |
| ----------------- | ----------------------- |
| `data-user-name`  | Имя пользователя        |
| `data-user-phone` | Номер телефона          |
| `data-user-email` | Адрес электронной почты |

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

***

#### Шаг 5. Настройте WebView в нативном приложении

**Android**

В Android `WebView` JavaScript и DOM Storage отключены по умолчанию. Включите их явно:

```kotlin
webView.settings.javaScriptEnabled = true
webView.settings.domStorageEnabled = true
webView.loadUrl("https://your-domain.com/chat.html")
```

Также реализуйте `WebChromeClient.onShowFileChooser()` — иначе кнопка прикрепления файлов в чате будет молча не работать. Без этого метода Android `WebView` не умеет открывать системный выбор файлов.

```kotlin
private var fileCallback: ValueCallback<Array<Uri>>? = null
private val REQ_FILE = 1001

webView.webChromeClient = object : WebChromeClient() {
    override fun onShowFileChooser(
        view: WebView?,
        callback: ValueCallback<Array<Uri>>?,
        params: FileChooserParams?
    ): Boolean {
        fileCallback?.onReceiveValue(null)
        fileCallback = callback
        return try {
            startActivityForResult(params!!.createIntent(), REQ_FILE)
            true
        } catch (e: Exception) {
            fileCallback = null
            false
        }
    }
}

override fun onActivityResult(req: Int, res: Int, data: Intent?) {
    super.onActivityResult(req, res, data)
    if (req == REQ_FILE) {
        fileCallback?.onReceiveValue(
            WebChromeClient.FileChooserParams.parseResult(res, data)
        )
        fileCallback = null
    }
}
```

> **Важно:** Если ваши пользователи могут отправлять фото с камеры прямо из чата, добавьте в `AndroidManifest.xml` разрешение `android.permission.CAMERA`. Для выбора уже существующих файлов из галереи разрешений не нужно.

**iOS**

На iOS используйте `WKWebView` — JavaScript и хранилище включены в нём по умолчанию, дополнительная настройка не требуется. Системный пикер файлов также открывается автоматически.

```swift
let webView = WKWebView(frame: view.bounds)
view.addSubview(webView)

let url = URL(string: "https://your-domain.com/chat.html")!
webView.load(URLRequest(url: url))
```

***

#### Шаг 6. Полный пример HTML-страницы

Итоговая страница с передачей идентификатора и данных пользователя:

```html
<!DOCTYPE html>
<html lang="ru">
<head>
  <meta charset="UTF-8">
  <meta name="viewport"
        content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0, viewport-fit=cover">
  <style>
    html, body { margin: 0; padding: 0; height: 100%; background: #fff; }
  </style>
</head>
<body>
  <script async
    src="https://cdn.fstrk.io/widget3-cdn/4bb3a79e-8075-4244-9440-cd266790cf1c.js"
    data-webview="a3f1c9e2-7b4d-4f8a-9c11-2e6d5b8a1f30"
    data-user-name="Иван Петров"
    data-user-phone="+79991234567"
    data-user-email="ivan@example.com"></script>
</body>
</html>
```

***

### Как работает режим WebView — отличия от обычного виджета

|                     | Режим WebView (мобильное приложение) | Обычный виджет на сайте     |
| ------------------- | ------------------------------------ | --------------------------- |
| Запуск              | Сразу открыт полноэкранный чат       | Кнопка-launcher или обложка |
| Кнопка закрытия (×) | Нет                                  | Есть                        |
| Переход на обложку  | Нет                                  | Есть                        |
| Размер              | Весь экран                           | Плавающее окно              |

Закрытие чата — это скрытие или закрытие `WebView` средствами нативного приложения. Виджет сам закрыться не может — в этом смысл режима «киоска».

> **Важно:** Виджет не обращается к серверам Fasttrack при открытии страницы — только загружает JS-бандл с CDN. Подключение к чату (авторизация, WebSocket, история сообщений) происходит после первого действия пользователя. Это снижает расход трафика и ускоряет загрузку.

***

### Ограничения и подводные камни

**Минимальная ширина окна** — 320 px. Если `WebView` уже — виджет отобразится некорректно. Убедитесь, что у `html` и `body` нет внешних отступов и выставлен `height: 100%`.

**Смена пользователя на лету невозможна.** Идентификатор из `data-webview` читается один раз при загрузке страницы. Если нужно переключить учётную запись (например, после выхода из профиля) — перезагрузите страницу в `WebView` с новым значением атрибута.

**Анонимная сессия ненадёжна.** Без `data-webview` переписка хранится только в `localStorage` конкретного `WebView`. Очистка кэша, переустановка приложения или вход с другого устройства — и история теряется.

**Разные оформления для разных сценариев.** Цвета, заголовок, аватар и другие параметры внешнего вида задаются в админке и «запекаются» в бандл — настраивать их со стороны HTML не нужно и нельзя. Если вам нужны разные темы (например, для разных брендов или разделов приложения) — создайте отдельные виджеты с разными UUID.

> **Осторожно:** Не используйте предсказуемые идентификаторы пользователей. Виджет не проверяет личность — только публичный ключ. Утечка предсказуемого идентификатора позволит получить доступ к чужой переписке.

***

### Чеклист для самопроверки

* [ ] UUID виджета скопирован из вкладки «Общие» → «Скрипт для мобильного приложения (WebView)» — не из раздела для сайта.
* [ ] В теге `<script>` присутствует атрибут `data-webview` (пустой или со значением).
* [ ] Идентификатор пользователя в `data-webview` стабильный и неугадываемый (UUID или хэш, не телефон и не порядковый номер).
* [ ] На Android включены `javaScriptEnabled = true`, `domStorageEnabled = true` и реализован `onShowFileChooser()`.
* [ ] Стили `html, body { margin: 0; padding: 0; height: 100%; }` присутствуют на странице, ширина `WebView` не менее 320 px.
