<!-- Canonical: https://docs.shopstory.live/docs/guide/web-sdk -->

# Интеграция Web SDK

Web SDK добавляет готовые интерфейсы ShopStory на сайт. Подключение состоит из настройки проекта со стороны ShopStory, установки скриптов и совместной проверки на домене клиента.

Если интерфейс полностью реализует клиент, используйте [Public API](<https://docs.shopstory.live/docs/guide/quickstart>). Для нативного приложения используйте [Mobile SDK](<https://docs.shopstory.live/docs/guide/mobile-sdk>).

## Что доступно

- каталог прямых эфиров и записей;
- полноразмерный плеер;
- product mini-player на согласованных товарных страницах;
- уведомление об активном эфире, если оно включено для проекта;
- переход в карточку товара или согласованное действие корзины.

Доступные виджеты ShopStory включает в конфигурации проекта.

## Контуры Web SDK

| Поверхность | Подключение | Commerce-действие |
| --- | --- | --- |
| Каталог в блоке страницы с открытием полного плеера поверх неё | Основной bundle и один вызов `ShopStorySDK.show()` | В экземпляр `show()` можно передать `actions` и `cartUrl` |
| Product mini-player и live-уведомление на PDP | Отдельный auto-init PiP bundle и настройка PDP со стороны ShopStory | Базовый путь открывает плеер и URL товара; direct cart для этого пути согласуется отдельно |
| Собственный список эфиров | Public API и UI клиента | Реализуется кодом клиента |

Основной и PiP bundles имеют разные bootstrap-контракты. Не подключайте их на одной странице без схемы из integration handoff.

### Модальное окно и плеер внутри страницы

Контейнер в `show()` задаёт место **каталога**, а не полного плеера. При выборе эфира стандартный полный плеер открывается поверх страницы: на desktop — как модальное окно с затемнением, на mobile — на весь экран.

| Что нужно разместить | Как подключается |
| --- | --- |
| Каталог эфиров внутри страницы | `show({ containerElement, config })` монтирует каталог в заданный блок |
| Полный плеер без собственного каталога | `showPlayer({ clientId, streamId })` открывает эфир поверх страницы и создаёт свой root в `document.body` |
| Компактное product video на PDP | Отдельный [mini-player](<https://docs.shopstory.live/docs/guide/web-mini-player>) с согласованными положением и поведением |
| Полный плеер постоянно в блоке контента — inline | Отдельно согласуйте с ShopStory размещение, размеры, lifecycle и commerce до оценки; контейнер каталога не включает этот режим |

В `showPlayer()` нет параметра контейнера. Встраивание в собственное модальное окно сайта или inline-блок требует согласованного способа монтажа; не переносите player DOM и не меняйте positioning через произвольные CSS overrides. Параметры и ограничения методов: [Web SDK reference](<https://docs.shopstory.live/docs/guide/web-sdk-reference>).

## До установки

Передайте команде ShopStory:

1. Точные production- и test-домены.
2. URL страницы каталога эфиров.
3. [Товарный фид](<https://docs.shopstory.live/docs/guide/feed-requirements>) и единый строковый `feedProductId` товара.
4. Примеры PDP, включая все используемые шаблоны.
5. Требуемое поведение кнопки «Купить».
6. Действующую [CSP сайта](<https://docs.shopstory.live/docs/operations/csp-headers>) и список целевых браузеров.

ShopStory регистрирует домены и origins, связывает их с `applicationId`, готовит конфигурацию и согласует способ определения товара на PDP. Проверку SDK на домене начинайте после подтверждения этой конфигурации.

### Браузеры и маршрутизация до оценки

Зафиксируйте в integration handoff версии браузеров и ОС для основной страницы, standalone PiP и целевых mobile browsers. Матрица относится к конкретным bundle и конфигурации проекта; согласуйте её до оценки QA и выпуска.

Для каждого целевого окружения проверьте загрузку каталога/PDP, live и VOD, первый кадр, продолжение видео, product action и возврат. Для SPA добавьте прямой вход, переход между PDP, смену SKU и back/forward: [lifecycle Web SDK](<https://docs.shopstory.live/docs/guide/web-sdk-reference#spa-%D0%B8-lifecycle>). Успешный API-запрос или script load не заменяет эту приёмку.

До загрузки SDK согласуйте [consent flow](<https://docs.shopstory.live/docs/guide/analytics#consent-%D0%B8-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D0%B5>). Для standalone PiP отдельно подтвердите commerce handlers и способ их регистрации; `actions` основного SDK не подключаются к нему автоматически.

Идентификация проекта

Основной SDK получает `clientId` в вызове `show()` и сверяет проект с зарегистрированным hostname. Секрет в HTML для этого не требуется. Каждый новый hostname нужно заранее передать ShopStory.

## Запустить каталог

Получите `applicationId` и зарегистрируйте test origin до запуска. [Скачайте Web SDK starter](<https://docs.shopstory.live/downloads/shopstory-web-starter.zip>) и разместите её на согласованном origin. Введите выданный ID; пример загружает production SDK и не содержит demo-данных или клиентских credentials.

Проверка результата: каталог показывает контент вашего проекта, выбранный VOD открывается, а сбой SDK оставляет страницу работоспособной. Пустой каталог сам по себе не подтверждает ошибку доступа: заранее согласуйте тестовый контент.

### Разместить SDK в существующей странице

Создайте контейнер:

live-container.html

```html
<div id="shopstory"></div>
```

Подключите основной bundle и вызовите `show()` после его загрузки:

shopstory-sdk-init.html

```html
<script
  src="https://app.shopstory.live/sdk/shopstory-sdk/shopstory-sdk-v1.x.min.js"
  crossorigin="anonymous"
  charset="utf-8"
></script>

<script>
  const container = document.getElementById('shopstory');

  if (window.ShopStorySDK && container) {
    window.ShopStorySDK.show({
      containerElement: container,
      config: { clientId: 'assigned-application-id' },
    });
  }
</script>
```

`v1.x` — буквальная часть опубликованного имени web-bundle. Используйте этот URL без замены `x` и не конструируйте соседние адреса.

Этот URL является управляемым ShopStory release channel в рамках контракта `v1`, а не immutable client tag. Не копируйте bundle на свой CDN. ShopStory отвечает за выпуск и server-side rollback bundle; клиент должен уметь отключить loader своим feature flag или возвратом шаблона к состоянию без SDK. Контакт для уведомлений об изменениях и окно проверки фиксируются в integration handoff проекта.

Не добавляйте `async` или `defer` к основному bundle, если инициализация идёт следующим inline-скриптом. При отложенной загрузке вызывайте `show()` из собственного обработчика `load`.

Если `script-src` запрещает inline JavaScript, перенесите вызов `show()` в разрешённый same-origin файл либо используйте действующий nonce/hash сайта. Не добавляйте `'unsafe-inline'` в `script-src` ради этого примера.

## Как работает загрузка

После выполнения основного bundle в `window` появляется `ShopStorySDK`. Вызов `show()` монтирует интерфейс в переданный контейнер. Затем SDK инициализируется, самостоятельно запрашивает каталог и товары и показывает результат. Клиенту не нужно повторять эти запросы через Public API.

При выборе эфира SDK загружает его данные и открывает полный плеер поверх страницы. Ниже показан сценарий с настроенным `actions.addProductToCartById`. Без обработчика корзины кнопка «Купить» открывает URL товара.

Основной SDK · каталог и прямая корзина

```mermaid
---
config:
  theme: base
  fontFamily: Euclid Circular B, sans-serif
  themeVariables:
    actorBkg: '#f8f8fb'
    actorBorder: '#d8d7e0'
    actorTextColor: '#242329'
    actorLineColor: '#d8d7e0'
    signalColor: '#5c3dff'
    signalTextColor: '#4d4b55'
    noteBkgColor: '#f8f8fb'
    noteBorderColor: '#e7e6ec'
    noteTextColor: '#4d4b55'
  sequence:
    mirrorActors: false
    wrap: true
    actorMargin: 26
    width: 116
    height: 40
    actorFontSize: 14
    messageFontSize: 14
    noteFontSize: 14
    messageMargin: 24
---
sequenceDiagram
    accTitle: Каталог Web SDK и добавление товара в корзину
    accDescr: После загрузки bundle сайт вызывает show. SDK получает каталог и данные эфира у ShopStory. Нажатие Купить вызывает обработчик сайта, который обращается к корзине ритейлера и возвращает результат через callback.
    participant site as Сайт клиента
    participant sdk as Web SDK
    participant api as API ShopStory
    participant cart as API корзины
    Note over site,sdk: Bundle выполнен. SDK доступен
    site->>sdk: show(options)
    sdk-->>site: undefined
    sdk->>api: Запрос каталога
    api-->>sdk: Эфиры и товары
    Note over site,api: Каталог показан. Покупатель выбирает эфир
    sdk->>api: Данные эфира
    api-->>sdk: Эфир и URL видео
    Note over site,api: Плеер открыт. Покупатель нажимает «Купить»
    sdk->>site: Вызов обработчика
    site->>cart: Добавить товар с текущей сессией
    cart-->>site: Результат cart-команды
    site-->>sdk: callback(true / false)
    Note over site,sdk: «В корзине» или «Не удалось добавить»
```

Обработчик `addProductToCartById` получает `feedProductId`, выполняет запрос к корзине и возвращает результат в SDK.

Схема показывает успешную загрузку каталога и эфира. При отсутствии контента или сбое путь до плеера прерывается. Запросы SDK к ShopStory обслуживает сам SDK; их внутренние адреса не входят в контракт ручной интеграции.

## Методы и lifecycle

`show()` монтирует каталог и возвращает `void`; он не подтверждает готовность видео. `showPlayer()` открывает заданный эфир. Параметры, TypeScript types и ограничения SPA: [справочник Web SDK](<https://docs.shopstory.live/docs/guide/web-sdk-reference>).

## Product mini-player и live-уведомление

Для согласованных страниц подключите отдельный bundle перед закрывающим `</body>`:

shopstory-pip-loader.html

```html
<script
  id="shopstory-pip"
  src="https://app.shopstory.live/sdk/shopstory-pip-sdk/shopstory-pip-sdk-v1.x.min.js"
  crossorigin="anonymous"
  charset="utf-8"
  async
></script>
```

Bundle запускает только компоненты, включённые для проекта. Для product mini-player ShopStory заранее фиксирует:

- какие страницы считаются PDP;
- где находится тот же `feedProductId`, что передан в товарном фиде;
- положение виджета и отступы от элементов сайта;
- профиль превью, условие показа после прокрутки, включение Live в PiP и Continuous Video;
- на каких страницах виджет должен быть отключён;
- какое действие выполняет кнопка «Купить».

Контейнер PiP скрипт создаёт сам и добавляет в `document.body`; отдельный `<div>` для виджета не требуется. Клиент обеспечивает доступность товарного ID в согласованном месте. ShopStory может использовать существующую разметку или другой согласованный источник ID; если подходящего источника нет, потребуется добавить его на PDP. Универсального обязательного `data-*` атрибута для всех сайтов нет.

PiP проверяет контент асинхронно и запрашивает товарное медиа только после положительного ответа API. При прямом входе на PDP это короткое превью записи или текущий live; при включённом Continuous Video переход из полного плеера позволяет продолжить просмотр на PDP. Профиль WebM с субтитрами, ориентир размера превью, режимы PiP, условия продолжения и ограничения autoplay описаны в [режимах PiP на PDP](<https://docs.shopstory.live/docs/guide/web-mini-player#%D1%80%D0%B5%D0%B6%D0%B8%D0%BC%D1%8B-pip-%D0%BD%D0%B0-pdp>). Порядок запросов и поведение без связанного эфира — в [загрузке на PDP](<https://docs.shopstory.live/docs/guide/web-mini-player#%D0%BF%D0%BE%D1%80%D1%8F%D0%B4%D0%BE%D0%BA-%D0%B7%D0%B0%D0%B3%D1%80%D1%83%D0%B7%D0%BA%D0%B8-%D0%BD%D0%B0-pdp>).

Standalone PiP bundle инициализируется без объекта `actions` из основного `ShopStorySDK.show()`. Вызов `show()` на другой странице не подключает callback к player, открытому из PiP. Для нового проекта такой player открывает URL товара; direct cart на этом пути требует отдельного commerce-контракта. Не загружайте основной и PiP bundles вместе на одной странице без явно проверенной схемы от ShopStory.

Ответ `active` от mini-player API означает, что сервер нашёл подходящий live или запись. В ручной API-интеграции открывайте `body.stream.playerUrl` без изменения и не собирайте его из данных видеопровайдера. Показ виджета на странице отдельно зависит от настройки DOM-шаблона PDP.

## Покупательское действие

Базовый вариант открывает URL товара. Добавление без перехода требует callback, который возвращает фактический результат клиентской корзины: [Добавление в корзину](<https://docs.shopstory.live/docs/guide/add-to-cart>).

Состояние кнопки до клика задаёт наличие. По умолчанию оно берётся из снимка фида; для остатка выбранного магазина в тот же объект `actions` передаётся обработчик наличия, а метод `refreshProductsAvailability()` обновляет карточки при смене магазина: [Наличие и остатки](<https://docs.shopstory.live/docs/guide/product-availability>).

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

## Mobile

В приложении ритейлера подключите [Mobile SDK](<https://docs.shopstory.live/docs/guide/mobile-sdk>). Он принимает тот же `feedProductId`, управляет нативным video entrypoint и плеером, а действие с товаром передаёт router или cart-команде приложения.

Web-скрипты из этого раздела нельзя переносить в произвольный WebView. Доступ к пакету, точная совместимая версия, callbacks и приёмка передаются в integration handoff конкретного проекта.

## Проверка перед production

1. ShopStory подтвердил точные домены, `applicationId` и включённые компоненты.
2. Основной bundle загружается, `window.ShopStorySDK` определён до вызова `show()`.
3. Каталог отображает контент нужного проекта.
4. Тестовый `feedProductId` точно совпадает со строковым значением в последней принятой версии фида.
5. Mini-player появляется только на согласованных PDP и не перекрывает критичные элементы.
6. Live-уведомление отображается только если оно включено и есть активный эфир.
7. Callback корзины показывает успех или ошибку из фактического ответа commerce-системы.
8. Страница остаётся работоспособной при сетевой ошибке ShopStory.
9. CSP разрешает согласованные ресурсы: [CSP](<https://docs.shopstory.live/docs/operations/csp-headers>).
10. Проверены desktop и mobile web в целевых браузерах клиента.

## Диагностика

| Симптом | Проверка |
| --- | --- |
| `ShopStorySDK` не определён | Проверьте загрузку и выполнение bundle, CSP и отсутствие `async` при последовательной inline-инициализации |
| Запрос bundle заблокирован, например `ERR_BLOCKED_BY_CLIENT` | Проверьте блокировщики рекламы и трекеров, расширения и настройки защиты браузера |
| `await showPlayer()` завершился, но видео ещё нет | Promise подтверждает только инициализацию; проверьте запросы данных эфира и медиаресурсов в Network |
| Отображается неверный проект | Сверьте текущий hostname с доменами, переданными ShopStory |
| Каталог пуст | Проверьте публикацию эфира или записи и `applicationId` проекта |
| Mini-player API возвращает `active`, но виджета нет | Передайте ShopStory URL PDP и название используемого шаблона |
| Mini-player не находит товар | Сравните ID на странице со значением из принятого фида без числового преобразования |
| Браузер блокирует ресурс | Сверьте console и Network с [CSP](<https://docs.shopstory.live/docs/operations/csp-headers>) и зарегистрированным origin |
| Кнопка «Купить» показывает неверный результат | Проверьте callback и ответ API корзины клиента |

При обращении в поддержку передайте URL страницы, время возникновения проблемы, браузер, `applicationId` и фрагмент Console/Network без cookies, токенов и персональных данных.

## Следующие шаги

- [Настроить аналитику](<https://docs.shopstory.live/docs/guide/analytics-web>)
- [Открыть справочник Web SDK](<https://docs.shopstory.live/docs/guide/web-sdk-reference>)
- [Добавление в корзину](<https://docs.shopstory.live/docs/guide/add-to-cart>)
- [Товарный фид](<https://docs.shopstory.live/docs/guide/feed-requirements>)
- [Mobile SDK](<https://docs.shopstory.live/docs/guide/mobile-sdk>)
- [Mini-player API](<https://docs.shopstory.live/docs/guide/mini-player>)
- [Безопасность](<https://docs.shopstory.live/docs/operations/security>)
