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

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

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

Если интерфейс полностью реализует клиент, используйте Public API. Для нативного приложения используйте 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.

До установки

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

  1. Точные production- и test-домены.
  2. URL страницы каталога эфиров.
  3. Товарный фид и единый строковый feedProductId товара.
  4. Примеры PDP, включая все используемые шаблоны.
  5. Требуемое поведение кнопки «Купить».
  6. Действующую CSP сайта и список целевых браузеров.

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

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

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

Каталог эфиров

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

live-container.html
<div id="shopstory"></div>

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

shopstory-sdk-init.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 · каталог и прямая корзинаПрокрутите схему по горизонтали
Вызовы идут сверху вниз. Обработчик addProductToCartById получает feedProductId, выполняет запрос к корзине и возвращает результат в SDK.

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

Методы основного SDK

Параметр SDK clientId принимает тот же идентификатор проекта, который в Public API называется applicationId. Используйте значение, выданное ShopStory, без преобразований. Общие правила: Идентификаторы.

show(options)

Монтирует каталог в контейнер сайта. Возвращает undefined (тип void), не предоставляет Promise загрузки каталога.

ПараметрОбязательноНазначение
containerElementДаСуществующий DOM-элемент, который сайт сохраняет на время работы SDK
config.clientIdДаСтроковый идентификатор проекта, выданный ShopStory
actionsНетОбработчики добавления товара в корзину и проверки наличия для этого экземпляра
cartUrlНетАдрес корзины для повторного клика по состоянию «В корзине»; относительный путь разрешается от origin сайта

await ShopStorySDK.show(...) не ждёт каталог. Ограничения повторной инициализации описаны в разделе SPA и lifecycle.

showPlayer(params)

Открывает указанную трансляцию в собственном контейнере в document.body. При первом вызове SDK создаёт контейнер, при следующих использует его повторно. Оба параметра обязательны:

ПараметрТипНазначение
clientIdstringИдентификатор проекта
streamIdstringИдентификатор трансляции из API

Возвращает Promise<void>. Promise завершается после внутренней инициализации SDK, ещё до подтверждения загрузки данных эфира и воспроизведения видео. Использовать его как сигнал «видео готово» нельзя.

show-player.js
async function openShopStoryPlayer(streamId) {
const sdk = window.ShopStorySDK;
if (!sdk) {
console.error('Основной bundle ShopStory не загружен');
return;
}

try {
await sdk.showPlayer({
clientId: 'assigned-application-id',
streamId,
});
} catch (error) {
console.error('Не удалось вызвать плеер ShopStory', error);
}
}

Передавайте идентификаторы строками. Список трансляций для собственного интерфейса получайте через GET /v3/streams.

showPlayer() не принимает actions и cartUrl и не наследует их из ранее вызванного show(). Для прямой корзины используйте плеер внутри каталога, созданного через show({ actions, ... }), либо согласованный commerce-контракт.

Готовность и ошибки

У основного SDK нет публичных событий или параметров onReady / onError для загрузки каталога и плеера. Событие load у <script> позволяет начать инициализацию; готовность каталога или видео оно не подтверждает.

Что произошлоЧто получает код сайта
Основной bundle не загрузился или не выполнилсяwindow.ShopStorySDK отсутствует; проверьте загрузку скрипта до вызова методов
show() вернулсяТолько завершение вызова монтирования; данные загружаются отдельно
showPlayer() завершил PromiseВнутренняя инициализация завершена; данные эфира и видео ещё могут загружаться
Вызов метода выбросил исключение или его Promise отклонёнИсключение можно обработать через try/catch
Ошибка обработана внутри SDK при загрузке или отрисовкеПубличного callback для сайта нет; возможны сообщение внутри SDK или отсутствие его интерфейса

try/catch в примере не перехватывает все ошибки загрузки и воспроизведения. При сбое до завершения инициализации Promise showPlayer() может остаться незавершённым. Не связывайте с ним разблокировку страницы, корзины или других функций сайта.

Состояние страницы без SDK и отключение loader через feature flag остаются на стороне клиента. Если вашему интерфейсу нужны собственные состояния загрузки, пустой выдачи и ошибки каталога, используйте Public API.

Типы для TypeScript

Для подключения через <script> добавьте локальный файл деклараций в каталог, включённый в tsconfig.json. Он описывает поддерживаемые на этой странице методы и параметры; сам SDK по-прежнему загружается скриптом.

shopstory-sdk.d.ts
type ProductAvailabilityMap = Record<string, boolean>;

type ClientActions = {
addProductToCartById?: (
feedProductId: string,
callback: (success: boolean) => void,
) => void;
addProductToCart?: (
vendorCode: string,
callback: (success: boolean) => void,
) => void;
resolveProductsAvailability?: (
feedProductIds: string[],
callback: (availability: ProductAvailabilityMap) => void,
) => void;
};

type ShopStoryShowOptions = {
containerElement: Element;
config: { clientId: string };
actions?: ClientActions;
cartUrl?: string;
};

type ShopStoryPlayerParams = {
clientId: string;
streamId: string;
};

declare global {
interface Window {
ShopStorySDK?: {
show(options: ShopStoryShowOptions): void;
showPlayer(params: ShopStoryPlayerParams): Promise<void>;
refreshProductsAvailability?(): void;
};
}
}

export {};

Поле ShopStorySDK намеренно необязательное: до выполнения bundle объекта нет. По той же причине необязателен refreshProductsAvailability — вызывайте его только через проверку существования. Результат корзины и приоритет обработчиков описаны в разделе Добавление в корзину, карта наличия — в разделе Наличие и остатки.

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

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

shopstory-pip-loader.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. Порядок запросов и поведение без связанного эфира — в загрузке на 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, который возвращает фактический результат клиентской корзины: Добавление в корзину.

Состояние кнопки до клика задаёт наличие. По умолчанию оно берётся из снимка фида; для остатка выбранного магазина в тот же объект actions передаётся обработчик наличия, а метод refreshProductsAvailability() обновляет карточки при смене магазина: Наличие и остатки.

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

SPA и lifecycle

Текущий публичный контракт основного SDK рассчитан на один вызов show() для одного стабильного container. Публичного destroy() нет. В SPA сохраняйте container между route transitions и не вызывайте show() из каждого render/effect без собственной защиты от повторной инициализации.

PiP bundle читает согласованный PDP-шаблон и идентификатор товара во время своего lifecycle. До оценки SPA-интеграции передайте ShopStory используемый router, список PDP routes, способ смены SKU и момент замены DOM. Проверка должна охватывать прямой вход, client-side переход между товарами, back/forward и уход с PDP.

Что включить в оценку

Work packageРабота клиентаНужный вход
BootstrapПодключить нужный bundle; для основного SDK передать clientId; исключить повторную инициализациюВыбранная поверхность, MPA/SPA topology и routes
КаталогСоздать стабильный container и состояние страницы без SDKURL каталога и test applicationId
Product PDPСохранить строковый feedProductId в согласованном местеВсе PDP/SKU templates и test products
CommerceВыбрать переход на PDP, callback основного SDK или custom PiP flowCart API, variant/store context и fallback
НаличиеРеализовать обработчик наличия и вызывать refreshProductsAvailability() при смене магазинаПакетный stock API, источник выбранного магазина и семантика available в фиде
SecurityОбновить действующую CSP и проверить registered originsCSP, media origins и browser matrix
ReleaseДобавить feature flag, acceptance и client-side rollbackTest/live/VOD fixtures и порядок включения

Если неизвестны SPA lifecycle, целевые браузеры или cart contract, оценка этих частей остаётся discovery scope. Базовый MPA-каталог с переходом на PDP можно оценивать отдельно.

Mobile

В приложении ритейлера подключите 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.
  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 и зарегистрированным origin
Кнопка «Купить» показывает неверный результатПроверьте callback и ответ API корзины клиента

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

Следующие разделы