Shoplive Developers
한국어KOEnglishEN日本語JA

Shoplive Web Player SDK 連携ガイド

ライブコマース配信を Web ページに組み込む手順をミッションに分けてご案内します。ミッション 1 だけで配信は表示されます — 残りは必要なものだけお選びください。

すばやく探す 左サイドバーの検索(または Ctrl+K / Cmd+K)で、このガイド内のセクションを探せます。ショートフォームの連携はショートフォームガイドをご覧ください。
はじめに

概要 & 要件

Shoplive Web Player SDK は、スクリプトタグ 1 つでライブ配信プレイヤーを Web ページに組み込みます。別途パッケージをインストールしたり、ビルドツールを設定したりする必要はありません。
好きな位置にプレイヤーを直接埋め込む、リンク 1 つで開く、別のページにプレビューを表示する — 必要な方法だけを選んで適用できます。

さっそく始める →

必要なもの

項目確認する場所
Access KeyShoplive Admin — 配信詳細ページ上部のサマリーカード
Campaign KeyShoplive Admin — 配信詳細ページ上部のサマリーカード
Shoplive Admin 配信詳細ページにおける Access key・Campaign key の表示位置
Shoplive Admin — 配信詳細ページ上部のサマリーカード。Access key・Campaign key の横にあるアイコンからコピーできます。上の画像では値を伏せています。

何を実現したいですか?

ミッション 1 を終えれば画面に配信が表示されます。ミッション 2〜6 は互いに独立しているので、順序に関係なく、必要なものだけ選んで適用してください — すべてをこなす必要のあるリストではありません。

やりたいこと参照先
ページの特定の位置にプレイヤーを埋め込む · 配信リストまで一度に表示する · リンク 1 つで配信を開くまずミッション 1 · 配信を表示する
チャットの表示名や入場制限など、ユーザー情報を連携する任意ミッション 2 · ユーザー情報の連携
クーポン・商品のタップ、ログインが必要な場面などで自社のコードを実行したい任意ミッション 3 · ユーザー操作を処理する
配信ページ以外でも配信中であることを知らせ、共有リンクから来てもらう任意ミッション 4 · 他のページでも配信を知らせる
表示中のプレイヤーを自社コードから操作する(クーポンを消す・ミュート・ダイアログ)任意ミッション 5 · プレイヤーを制御する
どのチャネルから流入し、実際に購入したかを集計する任意ミッション 6 · 計測 — 流入と購入
ブランドのお気に入り・カート・配信リマインド・オークションなど、有効化が必要な機能を組み込む任意付録 A · 有効化が必要な機能
配信を見ている途中で商品ページへ移動しても映像が途切れないようにする任意付録 B · PIP
SPA · アプリ WebView · RequireJS · ショートフォームとの同居など、特殊な環境に合わせる任意付録 C〜F

プレイヤー画面の各要素の呼び名は画面の用語ガイドにまとめています — ミッションを読んでいて removeBanner が何を消すのか迷ったら戻ってきてください。

ショートフォームも併用する場合 ライブ(shoplive.js)とショートフォーム(shoplive-shortform.js)は別のスクリプトですが、同じ window.cloud.shoplive オブジェクトを共有するため 1 ページに一緒に読み込めます。ユーザー情報は一度渡せば両方に反映され、注意点は 2 製品のプレビューが画面の同じ隅で重なりうることだけです — 詳しくは付録 F、ショートフォームの連携自体はショートフォームガイドをご覧ください。
はじめに

クイックスタート

最短の手順で画面にプレイヤーを表示するサンプルです。細かいオプションは下のミッション 1 からご覧ください。

<script src="https://static.shoplive.cloud/shoplive.js"></script>
<script>
  cloud.shoplive.initPlugin({ accessKey: 'YOUR_ACCESS_KEY' });
</script>

<div id="shoplive-player"></div>
<script>
  cloud.shoplive.setPlayer("shoplive-player", { campaignKey: "YOUR_CAMPAIGN_KEY" });
</script>

cloud.shoplive は SDK が用意するグローバル オブジェクトです。上のスクリプトが読み込まれると window.cloud.shoplive に initPlugin · setPlayer などの関数が追加されます。そのため import やバンドラーの設定なしに、どのスクリプトからでも cloud.shoplive.… と直接呼び出せます — ただし SDK のスクリプトタグより後で呼ぶ必要があります。使える関数の一覧は関数インデックスにあります。

次のステップ画面の用語ガイド · ミッション 1 から始める →

はじめに

画面の用語ガイド

プレイヤー画面の各要素の呼び名をまとめたものです。以降のミッション・イベント辞典・コマンド辞典でも同じ用語と同じ番号を使います。removeBanner が何を消すコマンドだったか迷ったら、この表に戻ってきてください。

この画像はモバイル SDK のキャプチャです Web プラグインは同じプレイヤー UI をそのまま表示するため、要素の名前と位置は同じです。ただし iPhone のステータスバーのようなアプリの外枠は Web にはなく、⑫ 最小化(PIP)ボタンも Web にはありません — 詳しい違いは表の下に記載しています。

プレイヤー画面

ライブプレイヤー画面の各要素に 1〜12 の番号を付けた図
番号要素表示条件Web での関連
①映像エリア常時playVideo · pauseVideo · videoRefresh(コマンド辞典)
②ブランドロゴ常時Shoplive Admin のキャンペーン設定 — コードでは変更しません
③キャンペーンタイトル常時Shoplive Admin のキャンペーン設定
④LIVE バッジ · 視聴者数 · いいね数LIVE 限定視聴者数・いいね数は ON_CHANGED_VIEWER_STAT、配信ステータス(開始・終了)は ON_CAMPAIGN_STATUS_CHANGED で受け取れます(ミッション 3 · 通知だけを受け取るイベント)。表示自体は ui.viewerCount · ui.likeCount でオン・オフできるだけです
⑤チャットオーバーレイLIVE 限定映像の上を流れるチャット。Web から制御する API はありません
⑥商品カード(左下 · NOW)常時タップすると CLICK_PRODUCT(ミッション 3)· リストを閉じるのは dismissGoodsList
⑦右側のアイコン列(♡ · ? · 💬)常時いいね · 問い合わせ · チャットを開く。列全体を hideControls · showControls で隠したり表示したりできます
⑧ミュートボタン常時mute · unmute。自動再生の制約により最初はミュートで始まります
⑨クーポンバブル運営者が発行したときタップすると Admin で選んだクリック時の動作がそのままイベントとして届きます(ミッション 3 · ポップアップ)· 削除は removeCoupon
⑩お知らせ pill運営者が発行したときお知らせもタップできます — ⑨ · ⑪ と同じクリック時の動作設定に従います(ミッション 3 · ポップアップ)· 削除は removeNotice
⑪イベントバナー · ポップアップ運営者が発行したときAdmin で選んだクリック時の動作がそのままイベント名になります — LINK · LINK_NEW_WINDOW · DOWNLOAD_COUPON · CUSTOM_ACTION(ミッション 3 · ポップアップ)。⑨ クーポン · ⑩ お知らせも同じ仕組みです · 削除は removeBanner
⑫右上のボタン常時Web では構成が異なります — 下の説明をご覧ください

モバイルとの違い

図の要素Web プラグイン
⑫ 最小化(in-App PIP)ボタンありません。画面の隅に小さく表示するのは別機能のミニプレビュー(setLiveMiniPreview)で、プレイヤー内のボタンではなく自社から呼び出します
‹ 戻るあります。タップすると CLICK_BACK_BUTTON — デフォルト動作は history.back() なのでページが戻ります。モーダルで表示している場合は閉じる処理も併せてご覧ください
共有アイコンあります。CLICK_SHARE_BTN · 共有する URL は shareUrl で指定します。非表示にするには hideShareButton
iPhone のステータスバー · ホームインジケーターアプリ画面の一部なので Web にはありません。Web プレイヤーは用意していただいた div のサイズ(またはモーダル)に合わせて描画されます

プレイヤー内の UI はほとんどが Shoplive Admin のキャンペーン設定でオン・オフします。コードから変更できるものは ミッション 1 · 画面に何を表示するかにまとめています。

前へ ← クイックスタート次へ → ミッション 1 · 配信を表示する

ミッション

ミッション 1 · 配信を表示する

目標Web ページに配信を表示する
事前準備Access Key · Campaign Key(Shoplive Admin — 配信詳細ページ上部のサマリーカード)

表示方法は 3 つあります。どれか 1 つを選べばよく、3 つとも同じ initPlugin() の上で動きます。

方法 A · プレイヤーのみ方法 B · リンクで開く方法 C · ライブページ テンプレート
画面に出るものプレイヤー 1 つプレイヤー 1 つ(全画面)メイン配信 + 配信リストまで一度に
位置・サイズのカスタム自由にできます不可(shoplive.show の固定レイアウト)領域単位で選択(プレイヤーのみ / リストのみ)
レイアウトを自社で組むかはい — コンテナと周囲の UI を自分で構成しますいいえいいえ — Shoplive のテンプレートを使います
ユーザー認証の設定コード(initPlugin)で設定URL の tk パラメータで設定コード(initPlugin)で設定
クーポン・商品タップなどのカスタムロジック(messageCallback)可能不可可能
PIP(商品ページへ移動しても見続ける)可能不可 — 自社ページに SDK がありません可能
主な用途イベント専用ページ、特定キャンペーンの特設ページ広告クリエイティブのランディング常設のライブコーナー — 配信が入れ替わり続けるページ

方法 Aプレイヤーを直接埋め込む

ページを自分で作れる場合はこの方法を使います。好きな位置にコンテナを置いて setPlayer を呼びます。

<script src="https://static.shoplive.cloud/shoplive.js"></script>
<script>
  cloud.shoplive.initPlugin({ accessKey: 'YOUR_ACCESS_KEY' });
</script>

<div id="shoplive-player"></div>
<script>
  cloud.shoplive.setPlayer("shoplive-player", {
    campaignKey: "YOUR_CAMPAIGN_KEY"
  });
</script>

プレイヤーはコンテナ div の中を埋めるので、コンテナのサイズと位置はページの CSS で決めます。配信が終わって CLOSED になっても campaignKey はそのままで構いません — 同じキーでアーカイブ再生されます。

方法 A の実際の画面。1 つの配信を告知するために自社で作ったライブ特設ページです。配信タイトル・日程・特典バッジ、右の商品リスト、下の見どころと注意事項まですべて自社で組んだレイアウトで、SDK が埋めるのは左の div 1 つだけです。スクロールしてもプレイヤーが付いてくるのは、その div に position:sticky を指定しているからで、ページの CSS で自由に決められるということです。動画内のショップは撮影用のサンプルで、文言は英語です。

画面に何を表示するか 任意

オプションデフォルト説明
ui.viewerCounttrue視聴者数を表示
ui.likeCounttrueいいね数を表示
ui.backButtonfalse戻るボタンを表示。タップすると CLICK_BACK_BUTTON が発生し、デフォルト動作は history.back()(ミッション 3)
ui.shareButtonfalse共有ボタンを表示(共有 URL)
cloud.shoplive.setPlayer("shoplive-player", {
  campaignKey: "YOUR_CAMPAIGN_KEY",
  ui: { viewerCount: true, likeCount: true, backButton: true, shareButton: true }
});

チャットや商品リストなどプレイヤー内部の構成はアカウント設定とテーマで決まります。上の 4 つ以外を変更したい場合は Shoplive 担当者までお問い合わせください。

共有ボタンが送る URL 任意

共有ボタンをオンにした場合、共有されるアドレスを initPlugin() の shareUrl で指定できます。指定しなければ現在のページのアドレスが使われます。共有の動作そのものを変える方法と URL の組み立てルールはミッション 3 をご覧ください。

cloud.shoplive.initPlugin({
  accessKey: 'YOUR_ACCESS_KEY',
  shareUrl: 'https://my-shop.com/live'   // 任意 — 省略すると現在のページ
});

常に全画面で 任意

cloud.shoplive.setPlayer("shoplive-player", {
  campaignKey: "YOUR_CAMPAIGN_KEY",
  isFullScreen: true
});
PC とモバイルの違い — isFullScreen には viewport meta タグが必須 isFullScreen: true を使うと、SDK がページの <meta name="viewport"> タグを探し、モバイルのピンチズームを抑えるよう値を調整します。このタグがページになければエラーも出さずに無視されるので、あらかじめ下のように入れておいてください。
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, viewport-fit=cover, shrink-to-fit=no">

その他のオプション 任意

特定の状況でのみ使う値です。通常は指定しなくて構いません。

オプション型説明
hideControlsbooleantrue にするとプレイヤーのコントロール UI を隠した状態で開始します。開始後はプレイヤー制御の showControls / hideControls コマンドでも切り替えられます
playerAliasstringこのプレイヤーに付ける別名。1 ページに複数のプレイヤーがあるとき getPlayer('別名') で正確に取り出すために使います(ミッション 5)。指定しなければ campaignKey で探します
closePlayerAfterCampaignEndnumber(ms)配信終了後この時間が経つと CLOSE_PLAYER イベントが届きます。配信が終わったときにページを片付けたり別の画面へ送ったりするための合図として使う値です — SDK はこのイベントでプレイヤーを閉じませんので、実際に取り除くには destroyPlayer() を自分で呼ぶ必要があります。
指定しない場合は、配信終了の30 秒後にプレイヤーが自分で再読み込みし、終了画面に落ち着きます
chatFilterPatternsstring[]正規表現文字列の配列。視聴者が送ろうとしているチャットがいずれかに一致すると送信されず、代わりに ON_FILTERED_CHAT イベントが発生します。独自の禁止ワード ポリシーをコードで載せるときに使います
passcodestringリハーサル配信をプレビューするための入場コード。リハーサルに設定された配信は ONAIR になるまでこの値がないと入場できません
brandobjectブランドのお気に入り機能を使うときに初期状態を渡します — { identifier, favorite }(付録 A · ブランドのお気に入り)

描き直しと後片付け

同じコンテナに setPlayer をもう一度呼ぶと、既存のプレイヤーを片付けて新しく作り直します。別の配信に差し替えるときに destroy を先に呼ぶ必要はありません。

逆にコンテナ自体が画面から消えるとき(SPA でコンポーネントがアンマウントされる場合など)は、SDK がそれを検知できず、プレイヤーが内部的に生き残ります。コンテナを取り除く前に destroyPlayer を呼んでください。

cloud.shoplive.destroyPlayer("shoplive-player");

方法 Bリンクで直接開く

ページを新しく作るのが難しい場合は、専用ページを用意せずに Shoplive が提供する shoplive.show ページを URL パラメータだけで呼び出します。ただし SDK は shoplive.show のページ内でのみ動作し、この URL を開く自社ページには読み込まれないため、initPlugin() を呼ぶことはできません。ユーザー操作の処理(ミッション 3)が必要な場合は方法 A または C を使ってください。

https://www.shoplive.show/v1/player.html?ak={access_key}&ck={campaign_key}&tk={ユーザー情報}
パラメータ必須説明
ak必須Access Key
ck必須Campaign Key
tk任意ユーザー情報 — URL エンコードした userObject JSON または JWT(ミッション 2)。ゲスト視聴なら省略
userId · userName
gender · age · userScore
任意tk の代わりに使う簡易方式。この 5 つのみ対応しており、tk も一緒に渡すと tk が優先されます(ミッション 2)
backButton任意1(表示)/ 0(非表示)
shareButton任意1(表示)/ 0(非表示)

共有ボタンのクリック時に渡すページ URL を指定する shareUrl オプション(方法 A 参照)は initPlugin() を直接呼ばないと適用されないため、方法 B では使えません。方法 B でできるのは shareButton=0 で共有ボタン自体を隠すことだけです。

方法 B の実際の画面。自社ページにはリンク 1 つを置くだけです。視聴ボタンを押すと Shoplive が提供するページが新しいウィンドウで開き、そこで配信が再生されます。開いた画面には自社のヘッダーも商品もなく、アドレスも自社ドメインではありません — そのためそのページには自社コードを置く場所がなく、messageCallback も登録できません。

方法 Cライブページ テンプレート — プレイヤーと配信リストを一度に

プレイヤー 1 つではなくライブコーナーのページ全体が必要なときに使います。空の div 1 つに setOverall を呼ぶと、その中にメイン配信(配信中、または直近の配信)+ 配信リストが Shoplive のテンプレートで描画されます。どの配信を出すかをコードで決めなくてよいので、配信が入れ替わり続ける常設コーナーに向いています。

<div id="shoplive-overall-area"></div>
<script>
  cloud.shoplive.setOverall('shoplive-overall-area');
</script>
方法 C の実際の画面。ショップの「ライブ」コーナーを想定した画面です。ヘッダー・ページタイトル・フッターは自社で作ったもので、その間のメイン配信と配信リスト、リストをタップすると開くモーダル プレイヤーまでが setOverall の描画した領域です。この画面では 2 つの領域を離して配置するために div を 2 つに分け、featuredOnly · campaignListsOnly でそれぞれ呼び出しています(どの領域だけを出すか)。

リストの配信をタップすると SDK が自動でモーダル プレイヤーを開きます。この動作を自分で処理したい場合は ON_CLICK_CAMPAIGN_LIST_ITEM を登録してください(ミッション 3)。

どの領域だけを出すか 任意

やりたいことオプション
デフォルト — メイン配信 + リストオプションなし
メイン配信(プレイヤー)領域のみ{ featuredOnly: true }
配信リスト領域のみ{ campaignListsOnly: true }
メイン配信を特定の配信に固定{ featuredOnly: true, featured: { fixedCampaignKey: 'YOUR_CAMPAIGN_KEY' } }

2 つの領域を離れた位置に置きたい場合は、div を 2 つ作り、一方を featuredOnly、もう一方を campaignListsOnly で呼び出してください。

リストの構成を決める 任意

cloud.shoplive.setOverall('shoplive-overall-area', {
  campaignListsOnly: true,
  campaignStatus: ['ONAIR', 'CLOSED'],   // この順に並びます
  tags: ['sale', 'new'],
  tagSearchOperator: 'OR',               // 'OR' いずれか一致 · 'AND' すべて一致
  displayTags: ['sale', 'new', 'best'],  // リストの上にフィルタータブとして表示
  campaignList: { layout: 'HORIZONTAL' } // 'GRID'(デフォルト)| 'HORIZONTAL'
});
オプションデフォルト説明
campaignStatusすべて'READY'(予定)· 'ONAIR'(配信中)· 'CLOSED'(終了・アーカイブ)。文字列 1 つ、または配列。配列で渡すと書いた順に並び、同じステータス内では配信予定時刻の新しい順です。この値は campaignListsOnly: true のときだけ効きます — メイン配信とリストを 1 つの div にまとめて描画するデフォルトのモードでは、配信中・予定・アーカイブの 3 セクションが常に出ます
tags / tagSearchOperator—配信に付けたタグでフィルター。複数あるときは 'OR' / 'AND' を選びます
displayTags—リストの上にフィルタータブとして出すタグ。視聴者がタップして絞り込めます
skus / goodsIds—特定の商品を含む配信のみ — skus は自社の商品コード、goodsIds は Shoplive 内部の商品 ID
campaignList.layout'GRID''GRID' グリッド · 'HORIZONTAL' 横 1 列スクロール
campaignList.type—'SECTION' を渡すとステータス別のセクションに分けて表示します
hasMoreButtontrueリスト下の「もっと見る」ボタン。false にすると 'GRID' では無限スクロールになります
ascendingステータス次第並び順。指定しない場合、campaignStatus が 'READY' の文字列 1 つのときだけ昇順(近い配信から)で、それ以外は降順です
sectionTitles既定の文言リストのセクション見出しを自社サービスの言い回しに変えます — { onair, ready, closed, all }
cloud.shoplive.setOverall('shoplive-overall-area', {
  sectionTitles: {
    onair:  'ライブ配信中',
    ready:  '配信予定',
    closed: '過去の配信',
    all:    'すべての配信'
  }
});

後片付け

SPA でページを離れるときは destroyOverall を呼びます。第 2 引数に true を渡すと、中に残っているプレイヤーまで併せて片付けます。

cloud.shoplive.destroyOverall('shoplive-overall-area', true);

モーダルで表示する 任意

ページに領域を作らず、ボタンを押したときに画面の上にモーダルとして配信を表示する方式です。バナーやボタンからすぐに配信を開くときに使います。

<button id="open-live">ライブを見る</button>
<script>
  document.getElementById('open-live').addEventListener('click', function () {
    cloud.shoplive.showFeaturedPlayerModal({ campaignKey: 'YOUR_CAMPAIGN_KEY' });
  });

  // コードから閉じる
  // cloud.shoplive.dismissLayerModalPlayer();
</script>
戻るを押すとモーダルだけが閉じます モーダルが開くと SDK が URL に配信キーを記録するため、モバイルで戻るを押してもページを離れずモーダルだけが閉じます。この動作が独自ルーターと衝突する場合は showFeaturedPlayerModal({ campaignKey, disableHistoryHook: true }) でオフにできます — 代わりに戻るで前のページへ遷移します。

完了の確認

  • (方法 A)指定した div の位置にプレイヤーが描画され、配信が ONAIR なら自動再生を試みる(ブラウザの自動再生ポリシーにより制限される場合があります)
  • (方法 B)URL だけで、専用ページを作らずにプレイヤーが開く
  • (方法 C)指定した div の中にメイン配信と配信リストが描画され、リストの配信をタップするとモーダルが開く
  • 共有ボタンをオンにした場合、タップすると shareUrl を指定していればそのページが、指定していなければ現在のページが共有される

前へ ← 画面の用語ガイド次へ → ミッション 2 · ユーザー情報の連携

ミッション

ミッション 2 · ユーザー情報の連携

目標チャットの表示名、ポップアップのクリックログ、入場制限などに使う視聴者情報を連携する
事前準備ミッション 1(方法 A または B)が完了 ·(JWT 認証の場合)バックエンドの署名処理を用意(ステップ 5)
setUserObject()・setUserJWT() はユーザー情報を渡すもので、ユーザーを認証するものではありません ログイン(ID・パスワード、ソーシャルログインなど)はすべて自社サイト側で行います。これらの関数はいまの視聴者が誰かを Shoplive に伝えるだけで、チャット・視聴・統計がその会員に紐づきます。Shoplive はユーザーの資格情報を確認しません。JWT 認証では、その情報が自社サーバーが発行し改ざんされていないか(署名)を Shoplive が確認でき、簡易認証(userObject)ではその確認なしに情報をそのまま渡します。

ステップ 1 · ログイン状態で選ぶ — 推奨の設定

ユーザー推奨理由
未ログイン何も呼び出さない(ゲスト)ユーザー情報を渡す必要はありません。ゲストのチャット可否は Admin で設定し、不可の場合はチャット入力欄が無効になり「チャットに参加する」という案内が表示されます。ゲストを区別する識別子が必要ならゲスト uid を受け取るを参照してください
ログイン (推奨)setUserJWT() — サーバーが署名した JWT(JWT 認証)改ざんできないため、userScore・userType による入場制限のような権限の判定に使えます
ログイン(バックエンド作業が難しい場合)setUserObject() — id・名前などを直接渡す(簡易認証)クライアントの値を署名なしでそのまま渡します。識別・統計には十分ですが、権限の検証には使わないでください
ログイン(Cafe24 · WISA · ゴドモール · Shopify のショップ)プラットフォーム自動連携ショップが既に把握しているログイン状態を SDK が読み取ります。上の 2 つとはどちらか一方で、ユーザー情報を直接渡した場合はそちらが優先されます
ログアウト・ユーザー情報のリセットcloud.shoplive.logout() · または setUserObject(null) / setUserJWT(null)設定したユーザー情報を消去し、ゲスト状態に戻ります
推奨の流れ ページ表示(未ログイン)→ 何もしない → ログイン中:ページを開くたびに(SPA なら setUserJWT() を呼ぶ直前ごとに)バックエンドから新しく発行した JWT を受け取り initPlugin({ userJWT }) または setUserJWT() → ログアウト時に logout()(または null を渡す)でユーザー情報をリセット。 方法 B(リンクで開く)は同じ JWT を tk パラメータで渡します(ステップ 2)。

ステップ 2 · 選んだ方式で呼び出す

ユーザー情報が initPlugin() の時点で分かっていれば、その呼び出しにそのまま含めます。ログイン状態が後から確定する場合(SPA など)は setUserObject() / setUserJWT() を後から呼びます。簡易認証は userId 以外すべて任意で、JWT には別途必須フィールドがあります(ステップ 5 参照)。ゲストは両方とも呼ばなければ大丈夫です。

// 簡易認証 — userId のみ必須、ほかは任意
const userObject = {
  userId: "",     // 必須 — ログインユーザーの一意な ID。空ならゲスト扱い
  userName: "",   // 任意 — チャットに表示される名前。未指定の場合はキャンペーン設定により入力を促すか自動生成。禁止ワードは * に置き換えて表示
  gender: "",     // 任意 — "m" | "f" | 未指定なら空
  age: "",        // 任意 — 統計では 5 歳単位にグループ化して表示されます
  userScore: "",  // 任意 — -100〜100 の整数。抽選対象の制限などの基準に使えます
  userType: "",   // 任意 — 入場制限(Entry Type)設定時に参照される値
  profile: "",    // 任意 — チャット一覧のプロフィール画像 URL、推奨 64x64px
  custom: "",     // 任意 — 自由形式のデータ、最大 1KB
  canBid: true    // 任意 — オークションの入札資格(付録 A · オークション)
};

// 方法 1 — initPlugin() の呼び出しにそのまま含める
cloud.shoplive.initPlugin({ accessKey: "YOUR_ACCESS_KEY", userObject });

// 方法 2 — initPlugin() のあとに別途呼ぶ(ログイン情報が後から確定するとき)
cloud.shoplive.initPlugin({ accessKey: "YOUR_ACCESS_KEY" });
cloud.shoplive.setUserObject(userObject);


// JWT 認証も方式は同じ — ステップ 5 で作ったトークンを渡します
cloud.shoplive.initPlugin({ accessKey: "YOUR_ACCESS_KEY", userJWT: "USER_JWT" });
// または
cloud.shoplive.setUserJWT("USER_JWT");


// ログアウト・ユーザー情報のリセット — 設定したユーザー情報を消去し、ゲスト状態に戻ります
cloud.shoplive.logout();
// または渡した値を null に: cloud.shoplive.setUserObject(null) / cloud.shoplive.setUserJWT(null)
方法 B(リンクで開く)の場合 — URL の tk パラメータで渡す 方法 B では initPlugin() の呼び出し自体がないため、上の userObject を JSON 文字列にして URL エンコードした値を tk パラメータに入れます。JWT はエンコードせずトークン文字列をそのまま入れます。
// 簡易認証
https://www.shoplive.show/v1/player.html?ak=YOUR_ACCESS_KEY&ck=YOUR_CAMPAIGN_KEY&tk=encodeURIComponent(JSON.stringify(userObject))

// JWT
https://www.shoplive.show/v1/player.html?ak=YOUR_ACCESS_KEY&ck=YOUR_CAMPAIGN_KEY&tk=USER_JWT

フィールドが少なければ個別パラメータでも渡せます。userId・userName・gender・age・userScore はクエリパラメータとして直接渡せるので、JSON を作ってエンコードする必要がありません。ただし userType・profile・custom・canBid と JWT はこの方式では渡せないため tk を使ってください。tk も一緒に渡すと tk が優先されます。

https://www.shoplive.show/v1/player.html?ak=YOUR_ACCESS_KEY&ck=YOUR_CAMPAIGN_KEY&userId=MEMBER_ID&userName=NICKNAME

ステップ 3 · ショップ プラットフォームを使うなら — 自動連携 任意

Cafe24・WISA・ゴドモール・Shopify で構築したショップなら、setUserObject() を自分で呼ぶ代わりに initPlugin() に platform だけを渡して、ショップのログイン状態を読み取らせることができます。ステップ 2 の代替であり、ステップ 2 に追加する作業ではありません。

ユーザー情報を直接渡すと自動連携は動きません SDK は userObject・userJWT がない場合にのみプラットフォーム自動連携を試みます。initPlugin() にユーザー情報を一緒に渡していれば、そちらが使われて platform は無視されます。どちらか一方だけを使ってください。
オークションを使うなら — 自動連携されたユーザーは canBid がオンになります プラットフォーム自動連携で作られたユーザー情報には canBid: true が常に付きます。つまりショップにログインしている人なら誰でもオークションに入札できます。会員ランクや購入履歴などで入札資格を絞る必要がある場合は、自動連携ではなくステップ 2 のように setUserObject() を直接呼んで canBid を計算して渡すか、CAN_BID_REQUIRED で入札時点に判断してください。
platform の値どうやって読み取るかページに用意するもの
'CAFE24'Cafe24 スキンのログイン状態モジュールが描画する会員情報を読みます。値が遅れて入るスキンでは、入るまで待ってから連携しますスキンにログイン状態モジュールがなければ下の A を追加します
'WISA' · 'GODOMALL'ページ上の決められた id の要素から会員情報を読みます下の B の 2 つの要素を自分で出力する必要があります
'SHOPIFY'同じ方式で読み取り、さらにプレイヤー内のカート機能が有効になりますB + カート連携(付録 A · カートに入れる)

いずれの場合も、どのページから入ってもログイン状態を拾えるよう共通レイアウト(全ページが共有するヘッダー領域)に入れるのが確実です。

<!-- 1. SDK の読み込み -->
<script src="https://static.shoplive.cloud/shoplive.js"></script>

<!-- A. Cafe24 — スキンにログイン状態モジュールがない場合のみ追加します。
       {$id} {$name} は Cafe24 がログイン会員の ID・名前に置き換えます。
       このモジュールが描画されると .xans-member-var-id / .xans-member-var-name が作られ、
       SDK はその 2 つのクラスを探して読み取ります -->
<div module="Layout_stateLogon" style="display:none;">{$id} {$name}</div>

<!-- B. WISA · ゴドモール · Shopify — 会員情報をこの id で出力します。
       波かっこの中はショップ ソリューションが提供する会員変数に置き換えてください
         · ゴドモール : {=gSess.memId} / {=gSess.memNm}
         · WISA       : {{$회원아이디}} / {{$회원명}}
       未ログイン時は値が空になるのでゲストとして動作します -->
<div style="display:none;">
  <span id="cloud-shoplive-user-id">MEMBER_ID</span>
  <span id="cloud-shoplive-user-name">NICKNAME</span>
</div>

<script>
  // 2. platform だけを渡します — setUserObject は呼びません
  cloud.shoplive.initPlugin({
    accessKey: 'YOUR_ACCESS_KEY',
    platform: 'CAFE24'      // 'CAFE24' | 'WISA' | 'GODOMALL' | 'SHOPIFY'
  });
</script>
visibility: hidden で隠すと値が空になります 会員情報の要素を画面に見せない場合、display: none や画面外へ追い出す方法は値の読み取りに問題ありませんが、visibility: hidden は空文字列として読まれてゲストになります。また Cafe24 以外は初期化時に一度だけ読むので、会員情報をスクリプトで後から埋める場合は initPlugin() をそのあとに呼んでください。

連携できたか確かめるには。ログイン状態で配信に入り、チャットに表示される名前を見てください。Cafe24 で会員情報の領域(.xans-member-var-id・.xans-member-var-name)が見つからない場合はコンソールに Failed - Get Cafe24 account が出ます。ほかのプラットフォームは要素がなければ静かにゲストのままです。自動連携が難しければ、ステップ 2 のように setUserObject() を直接呼べば大丈夫です。

各ショップの管理画面でコードをどこに入れるかは、付録 G · ショッププラットフォーム別の設置場所をご覧ください。

ステップ 4 · ID のハッシュ化 — 会員 ID の原文を渡さない

社内の会員 ID をそのまま渡したくない場合は、自社サーバーでハッシュ化した値を userId として使えます。マスキングと違い、Shoplive は元の ID を知ることができませんが、自社は同じハッシュ処理(同じアルゴリズム・ソルト)で同じ値を再計算し、元のユーザーに対応付けられます。同じユーザーが常に同じ値になるよう(統計・再訪の識別のため)一貫した方式で処理してください。

// Node.js — 自社サーバーでハッシュ化します(salt・アルゴリズムは常に同じに)
const crypto = require('crypto');

function hashUserId(raw) {
  return crypto.createHash('sha256')
    .update(raw + 'YOUR_SALT')
    .digest('hex');
}

const userId = hashUserId('MEMBER_ID');   // userObject.userId または JWT の userId に使います
セキュリティに関する注意 ハッシュ化は平文の隠蔽にすぎず、認証ではありません。権限の検証が必要な場合は必ずサーバー署名の JWT(setUserJWT())を使用してください。salt のポリシーは Shoplive チームと合意した値を推奨します。

ステップ 5 · JWT 認証用のトークンを作る(自社バックエンド)

JWT 認証に使う JWT は、Shoplive が発行した Secret Key で自社のバックエンドが署名します。ページはバックエンドから受け取った JWT を initPlugin({ userJWT }) または setUserJWT() に渡すだけです(方法 B は tk パラメータ)。

  1. Shoplive の担当者から Secret Key を受け取ります — base64 でエンコードされた文字列です
  2. ログインしたユーザー情報で下記の payload を作り、HS256 で署名します
  3. ページから要求されるたびに(setUserJWT() を呼ぶ直前ごとに)JWT を新しく発行して返します。ブラウザに JWT を保存して使い回さないでください
JWT は毎回新しく生成して使います ブラウザ(localStorage・Cookie など)に JWT をキャッシュしたり、古いトークンを使い回したりしないでください。前回の発行以降にユーザー情報(名前・等級・タイプ)が変わっている可能性があり、漏えいしたトークンは exp まで使えてしまいます。ページを開くたびに、または setUserJWT() を呼ぶたびに、バックエンドから新しい JWT を受け取るようにしてください。
フィールド名の違いにご注意ください JWT の payload(クレーム)フィールドには、簡易認証と名前が異なるものがあります — チャットの表示名は userName ではなく name で、有効期限 exp が必須です。exp は JWT ライブラリが提供する期限設定 API(下の例の setExpiration・expiresIn)で指定してください — ライブラリが exp を埋めてくれます。
claim必須説明例
exp必須有効期限(Unix 秒)。ライブラリの期限設定で埋めます1516239022
userId必須ログインユーザーの一意性を保証できる値。ハッシュ値でも構いません(ステップ 4)。空ならゲスト扱いMEMBER_ID
iat任意発行時刻(Unix 秒)1516195822
name任意チャットに表示される名前(簡易認証の userName に対応)。禁止語は * に置き換えて表示NICKNAME
gender任意性別 — m · f · 空(未指定)f
age任意年齢。統計では 5 歳単位でまとめて表示されます27
userScore任意ユーザーランク(-100〜100)。抽選対象の制限などの基準10
userType任意入場制限(Entry Type)設定時に参照される値VIP
profile任意チャット一覧のプロフィール画像 URL、推奨 64x64pxhttps://…/profile.png
custom任意自由形式のデータ、最大 1KB{"grade":"vip"}
canBid任意true / false。オークションの入札資格(付録 A · オークション)true

署名する

署名の例です。2 つのコードは同じトークンを作ります — Secret Key が base64 文字列のため、ライブラリによってそのまま渡すかデコードして渡すかが異なる点だけ注意してください。

// Java — jjwt。signWith が base64 文字列を自動でデコードします
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;

String base64EncodedSecretKey = "YOUR_BASE64_SECRET_KEY";   // Shoplive 担当者から受け取った値
long expiration = System.currentTimeMillis() + 12 * 60 * 60 * 1000L;   // 12 時間

String jwt = Jwts.builder()
    .signWith(SignatureAlgorithm.HS256, base64EncodedSecretKey)
    .setExpiration(new Date(expiration))
    .setIssuedAt(new Date())
    .claim("userId", "MEMBER_ID")     // 必須
    .claim("name", "NICKNAME")        // 任意 — チャットの表示名
    .claim("userScore", 10)           // 任意
    .claim("userType", "VIP")         // 任意
    .compact();
// Node.js — jsonwebtoken。secretKey を自分でデコードして渡す必要があります
const jwt = require('jsonwebtoken');

const base64EncodedSecretKey = 'YOUR_BASE64_SECRET_KEY';   // Shoplive 担当者から受け取った値
const secret = Buffer.from(base64EncodedSecretKey, 'base64');   // ← デコードが必要

const token = jwt.sign(
  {
    userId: 'MEMBER_ID',   // 必須
    name: 'NICKNAME',      // 任意 — チャットの表示名
    userScore: 10,         // 任意
    userType: 'VIP'        // 任意
  },
  secret,
  { algorithm: 'HS256', expiresIn: '12h' }
);
Secret Key はバックエンドだけに Secret Key があれば、誰でも好きな userId・userScore で他のユーザーになりすましたトークンを作れてしまいます。ブラウザにバンドルされるコードや公開リポジトリには置かず、必ず自社サーバーでのみ署名し、完成したトークンだけをフロントへ渡してください。簡易認証(setUserObject())は署名がないため、権限の検証には使えません。

ゲストも区別する必要があるなら — ゲスト uid を受け取る 任意

ユーザー情報を渡していないゲストの視聴者には、プレイヤーが任意の識別子 uid を発行します。この値を自社側でも把握したい場合 — 未ログイン視聴者のクーポン発行履歴をまとめる、自社ログを Shoplive の統計と突き合わせるなど — は、messageCallback に ON_UID_ISSUED を登録します。プレイヤーがサーバーに接続するたびに届きます。

const messageCallback = {
  ON_UID_ISSUED: function (payload) {
    // payload.uid — プレイヤーが発行したゲスト識別子 · payload.campaignKey — どの配信か
    const stored = localStorage.getItem('shoplive_uid');
    if (stored !== payload.uid) {
      localStorage.setItem('shoplive_uid', payload.uid);
    }
  }
};
cloud.shoplive.initPlugin({ accessKey: 'YOUR_ACCESS_KEY', messageCallback });
ゲストにのみ使い、恒久的な ID にはしないでください
  • ログイン済みの視聴者は userId で識別されます。 このイベントはログインの有無にかかわらず届きますが、ユーザー情報を渡した視聴者については渡した userId を基準にし、uid はゲストにのみ使ってください。
  • 値は変わることがあります。 プレイヤーはゲストの uid をブラウザに 2 時間保持し、その後に再び訪れると新しい値を発行します。ブラウザのストレージを消したり別のブラウザから入ったりしても変わります。届くたびに保存済みの値と比較して更新してください。

完了の確認

  • ログイン後にチャットを送信すると、指定したユーザー名(会員名)が表示される
  • (入場制限を設定した場合)userScore / userType の基準に合うユーザーだけが入場できる
  • ログアウト → cloud.shoplive.logout() でユーザー情報をリセットしたあとはゲストとして視聴される

前へ ← ミッション 1 · 配信を表示する次へ → ミッション 3 · ユーザー操作を処理する

ミッション

ミッション 3 · ユーザー操作を処理する

目標クーポンのタップやログインが必要な場面を処理し、商品タップなどデフォルト動作があるアクションは必要なときだけ思いどおりに変える
事前準備ミッション 1(方法 A)の initPlugin() が完了 · クーポン・商品のタップを扱うなら、Admin で該当ポップアップ・商品のクリック動作を設定済み

クーポン・商品・ログインのように独自のビジネスロジックが必要な操作は、ほとんど messageCallback を通じて届きます。このステップの内容が実際の連携コードの中心です。

方法 B(リンクで開く)では使えません messageCallback はページに読み込まれた SDK の initPlugin() に登録する機能です。shoplive.show のリンク(ミッション 1 方法 B)はページに SDK 自体が読み込まれないため、コールバックを登録できません。クーポン・商品タップに反応するロジックが必要なら方法 A を使ってください。
関連リファレンス Goods
  1. initPlugin() の呼び出し時に messageCallback へアクション名ごとの関数を登録します。
  2. 登録しておくと、そのアクションが起きるたびに自動で呼ばれます。
  3. (任意)コールバックの中で getPlayer() を使いプレイヤー UI を更新します。
const messageCallback = {
  DOWNLOAD_COUPON: function (payload) {
    console.log('クーポンがタップされました。coupon code: ' + payload.coupon);
    fetch('YOUR_COUPON_API')
      .then(function (res) { return res.json(); })
      .then(function (res) {
        if (res.success) {
          alert('クーポンを取得しました。');
          // 応答を待つ間にプレイヤーが閉じている可能性があるのでここで取得します(ミッション 5)
          const player = cloud.shoplive.getPlayer(payload.campaignKey);
          if (player) player.sendMessage('removeCoupon');
        } else {
          alert('クーポンはすべて配布済みです。');
        }
      });
  },
  // CLICK_PRODUCT は任意 — 定義しなければデフォルト動作(新しいウィンドウで開く)がそのまま使われます。
  // 同じウィンドウで遷移させたいときなど、違う動作にしたい場合だけ下のように追加してください。
  // CLICK_PRODUCT: function (payload) {
  //   location.href = payload.url;
  // },
  LOGIN_REQUIRED: function (payload) {
    // ゲストがログインの必要な機能にアクセスしたとき
  },
};
cloud.shoplive.initPlugin({
  accessKey: "YOUR_ACCESS_KEY",
  messageCallback
});
API の呼び出しは Admin ではなく自社コードで Admin に「自社クーポン API の URL」を登録しておけば Shoplive が代わりに呼んでくれる、という機能はありません。上のコードの fetch('YOUR_COUPON_API') のように、クーポンがタップされたら自社サーバーの API を呼ぶ処理は messageCallback の中に自分で書きます。

主なアクション

発生タイミングの太字の番号は画面の用語ガイドの図の番号です — 視聴者が画面の何をタップしたときにそのアクションが届くのかがすぐ分かります。

アクション発生タイミングpayload用途
DOWNLOAD_COUPONクリック動作が「クーポンダウンロード」に設定されたポップアップのタップ ⑨ ⑩ ⑪campaignKey, coupon, popupResourceId, type(BANNER/COUPON/NOTICE)定義しないと何も起きません — クーポン発行を自社システムと連携するには必須
CUSTOM_ACTIONクリック動作が「カスタム」に設定されたポップアップのタップ ⑨ ⑩ ⑪campaignKey, id, type(BANNER/COUPON/NOTICE), payload.payload(Admin のクーポン編集画面で設定したカスタム JSON)標準フィールドで足りないとき、好きなデータを自由形式で載せられます
CLICK_PRODUCT商品のタップ ⑥Goods定義しなければ自動で新しいウィンドウへ遷移。同じウィンドウで遷移したいときや URL パラメータを足すときに上書き
LOGIN_REQUIREDゲストがログインの必要な機能にアクセス ⑦campaignKeyログインページへ遷移させる処理を実装。認証方式そのものはミッション 2 を参照
CLICK_SHARE_BTN共有ボタンのタップ ⑫campaignKey, shareUrl, title登録しなければデフォルト動作(OS の共有シート、またはクリップボードへコピー)が自動で実行されます。登録するとデフォルト動作が置き換わり実行されなくなるため、ログだけ取りたい場合でも共有そのものを下のように自分で実装する必要があります
LINKクリック動作が「リンク」に設定されたポップアップのタップ(または商品リスト上部のリンクのタップ)⑨ ⑩ ⑪campaignKey, popupResourceId, type(BANNER/COUPON/NOTICE), url上書きしなければ同じウィンドウでの遷移がデフォルト。ただし Web PIP がオンなら、プレイヤーを表示したまま遷移します
CLICK_BACK_BUTTONプレイヤーの戻るボタンのタップ(ui.backButton をオンにした場合)⑫なし上書きしなければ history.back()。独自ルーターへ渡すなら上書き
ON_CLICK_CAMPAIGN_LIST_ITEM配信リスト(方法 C)で配信を 1 つタップ — プレイヤーの外ですak, campaign(Campaign)上書きしなければモーダル プレイヤーが開きます。独自の詳細ページへ送るときに上書き
ON_CLICK_CLOSE_PLAYER_MODALモーダル プレイヤーの閉じるボタンのタップ — プレイヤーの外ですcampaign(Campaign)上書きしなければモーダルが閉じます。閉じる前に確認ダイアログを出すなど、割り込むときに上書き
LINK_NEW_WINDOWクリック動作が「リンク(新しいウィンドウ)」に設定されたポップアップのタップ(または商品リスト上部のリンクのタップ)⑨ ⑩ ⑪campaignKey, popupResourceId, type(BANNER/COUPON/NOTICE), url上書きしなければ新しいウィンドウでの遷移がデフォルト
ON_CLICK_SCHEME_BUTTONプレイヤー内のスキームボタンのタップ — 商品を見る・追加・削除、オークション落札者の決済 ⑥scheme(開くアドレス), schemeType, campaignKey上書きしなければ scheme を新しいウィンドウで開きます。schemeType で何がタップされたかを判別して自社ロジックへ渡すときに上書き — 'GO_PRODUCT' · 'ADD_PRODUCT' · 'REMOVE_PRODUCT' · 'WINNER_CHECKOUT'(オークション落札者の決済)
REQUEST_FULL_SCREEN
EXIT_FULL_SCREEN
プレイヤーから全画面への切り替え・解除が要求されたとき ①campaignKey(解除時はなし)上書きしなければプレイヤーの iframe にブラウザの全画面を適用・解除します。自社のレイアウトで拡大したい場合に上書き
ブラウザ PIP から来たページでは payload.url にパラメータが 1 つ付きます 視聴者がブラウザ PIP の状態で遷移してきたページでは、CLICK_PRODUCT · LINK · LINK_NEW_WINDOW の payload.url の末尾に csl_bp が自動で付きます。次のページでも PIP を続けるための目印です。この URL を自社ロジックで加工する場合は、見慣れないパラメータが混ざって来ることがある点にご注意ください — 削除すると遷移先で PIP が途切れます。
CLICK_SHARE_BTN を登録するとデフォルトの共有動作がなくなります 共有ボタンを押すと navigator.share(対応していれば OS の共有シート)やクリップボードへのコピーが自動で実行されます。共有されるアドレスは配信キーが付いた URL です — shareUrl(ミッション 1 の initPlugin() オプション)を指定していればそのアドレスに ?ck=、指定していなければ現在のページのアドレスに ?_sl_ck= が自動で追加されます。付くパラメータと、そのアドレスから来たときの動作はミッション 4 · 共有 URL にまとめています。shareUrl に既にあるクエリパラメータは保持されるので、utm_source などのマーケティング計測パラメータをあらかじめ付けておけます。クリップボードにコピーされた場合は、プレイヤーに 「Copy to clipboard completed.」の案内が自動で表示されます。 CLICK_SHARE_BTN を登録した瞬間、このデフォルト動作は実行されなくなります。タップのログだけを取りたい場合でも、下のように共有動作そのものを自分で実装する必要があります。
CLICK_SHARE_BTN: function (payload) {
  // ログなど、必要な処理
  console.log('共有がタップされました', payload.campaignKey);

  // デフォルト動作を保ちたいなら自分で作り直します
  // payload.shareUrl が空の場合は SDK が組み立てていたアドレスを自分で作る必要があります
  if (navigator.share) {
    navigator.share({ title: payload.title || '', text: '', url: payload.shareUrl });
  } else if (navigator.clipboard) {
    navigator.clipboard.writeText(payload.shareUrl);
  }
}

バナー(⑪)・クーポン(⑨)・お知らせ(⑩)のポップアップは、Admin でポップアップごとにタップ時の動作を設定します。全体は次のとおりです。

Admin 設定開発コード説明
クーポンダウンロード必要(DOWNLOAD_COUPON)コールバック未登録では何も起きません
リンク(同じウィンドウ)任意(LINK)コールバック未登録なら同じウィンドウでの遷移がデフォルト
リンク(新しいウィンドウ)任意(LINK_NEW_WINDOW)コールバック未登録なら新しいウィンドウでの遷移がデフォルト
カスタム必要(CUSTOM_ACTION)Admin で定義した任意の payload を渡します
詳細ポップアップ(画像)不要messageCallback なしでプレイヤーが自前で画像を表示します
ボトムシートを開く不要messageCallback なしでプレイヤーが自前でボトムシートを表示します

クリック動作を設定したのに登録したコールバックが呼ばれない場合は、上の表で「開発コード不要」の項目に設定されていないか Admin で確認してみてください。

通知だけを受け取るイベント — 置き換えるものがないもの

プレイヤーから上がってくるイベントには、どの配信で起きたことかが分かるよう payload.campaignKey が常に一緒に載ります。下の表に個別に記載していないイベントも同様です。

下のイベントには SDK のデフォルト動作がありません。登録しても何かを置き換えることはなく、ただ「こういうことが起きた」と知らせるだけです。アナリティクスの送信や、自社画面の状態を合わせるのに使います。

ON_PLUGIN_INITIALIZED の liveMiniPreview は、Admin に設定された値に SDK のデフォルト値(位置 BOTTOM_RIGHT · 余白 16 · 表示時間 300)を埋めた最終結果です。ミニプレビューの位置に合わせて自社 UI をずらす必要があるときは、この値を読んでください。

イベント発生タイミングpayload
ON_PLUGIN_INITIALIZEDinitPlugin() が完全に終わったとき。初期化前に先に呼んだ関数がすべて実行されたあとに届きますliveMiniPreview — ミニプレビューの実際に適用された設定(position · marginTop · marginRight · marginBottom · marginLeft · dismissPreviewDuration)
ON_PLAYER_STARTED視聴者がプレイヤーに入り再生が始まったときaccessKey · campaignKey · isPreview(プレビュー時のみ)
NOW_ONAIR_CHECKED配信中のものがあるか確認できた時点campaignKey · campaignStatus · title · startedAt · tags
ON_CAMPAIGN_STATUS_CHANGEDプレイヤーが再生中の配信のステータスが変わったとき — 配信の開始・終了はここに届きます。プレイヤーが開いたときに現在のステータスで一度届き、その後は変わるたびに届きますstatus('READY' · 'ONAIR' · 'CLOSED' など)· campaignKey
ON_CHANGED_VIEWER_STAT視聴者数・いいね数が更新されたとき(配信中は随時)viewerCount · likeCount · campaignKey
ON_PLAYER_MODAL_SHOWN
ON_PLAYER_MODAL_HIDDEN
モーダル プレイヤーが表示・非表示になったときcampaign(Campaign)
ON_LIVE_MINI_PREVIEW_SHOWN
ON_LIVE_MINI_PREVIEW_HIDDEN
ミニプレビュー バナーが表示・非表示になったときなし
ON_CLICK_CLOSE_LIVE_MINI_PREVIEW視聴者がミニプレビューの閉じるボタンを押したときcampaign(Campaign)
ON_PRODUCT_LIST_SHOWN商品リストのポップアップが開いたときproductList — Goods の配列
ON_CHANGED_CAMPAIGN_PRODUCT_LIST配信に紐づく商品リストが変わったとき — 運営者が配信中に商品を追加・削除すると届きますproductList · campaignKey
ON_RECEIVED_CHAT新しいチャットが届いたとき。一度に複数がまとめて届きますchatList(配列)· campaignKey
ON_ERASED_CHAT運営者がチャットを削除したとき。独自のチャット一覧を作っている場合はこのタイミングで消しますlid(削除されたチャットの id)· campaignKey
ON_CHAT_INPUT_FOCUS_IN
ON_CHAT_INPUT_FOCUS_OUT
視聴者がチャット入力欄にフォーカスを入れた・外したとき。モバイルではキーボードが上がるタイミングです — 下の CHAT_READY を参照campaignKey
ON_FILTERED_CHATchatFilterPatterns に該当してチャットが送信されなかったときmessage · regExp(一致したパターン)
ON_UID_ISSUEDプレイヤーがサーバーに接続し、視聴者の識別子が決まったとき。ゲストの識別に使う方法はミッション 2 · ゲスト uid を受け取るuid · campaignKey
const messageCallback = {
  ON_PLAYER_STARTED: function (payload) {
    analytics.track('live_player_started', { campaignKey: payload.campaignKey });
  },
  ON_PLAYER_MODAL_HIDDEN: function (payload) {
    // モーダルが閉じたので自社ページの状態を戻す
    document.body.classList.remove('live-open');
  }
};
cloud.shoplive.initPlugin({ accessKey: 'YOUR_ACCESS_KEY', messageCallback });
チャット入力中はコンテナに CHAT_READY クラスが付きます 視聴者がチャット入力欄にフォーカスを入れると、SDK が自社で作ったプレイヤーの div に CHAT_READY クラスを付け、フォーカスが外れると外します。モバイルでキーボードがプレイヤーを覆うとき、コールバックを登録せず CSS だけでレイアウトを変えられます。
/* チャット入力中は下の領域をたたんでおく */
#shoplive-player.CHAT_READY ~ .my-product-section {
  display: none;
}

Goods payload の構造(CLICK_PRODUCT)

フィールド説明
sku商品コード
name商品名
brandブランド
url商品詳細ページの URL — 定義しなければこの値で新しいウィンドウへ遷移
goodsId商品の識別子
campaignId配信の識別子
description商品説明
showingNowNOW マークの表示有無
salesStatusON_SALE / SOLDOUT / ALMOST_SOLDOUT
originalPrice販売価格
discountedPrice割引価格
discountPercentage割引率
currency通貨(例: KRW)
isCartOnカートに入っているか

カートに入れる(CLICK_PRODUCT_CART)アクションも同じ Goods 構造を payload として使います。

カートに入れるボタン(別途有効化が必要) 商品リストにカートボタンを表示するには、まず Shoplive(ask@shoplive.cloud)へ有効化をご依頼ください。有効化後は CLICK_PRODUCT_CART アクション(payload: Goods)でカートボタンのタップを処理できます。

Campaign payload の構造(配信情報)

配信リストのタップ・モーダルの表示・ミニプレビューなど配信単位で発生するイベントは、配信情報を一緒に渡します。次の 6 つは常に含まれます。

フィールド説明
campaignKey配信の固有キー — setPlayer・showFeaturedPlayerModal にそのまま渡せます
campaignStatus'READY'(予定)· 'ONAIR'(配信中)· 'CLOSED'(終了)
title配信タイトル
scheduledAt配信予定時刻(ミリ秒の timestamp)
startedAt実際の開始時刻。開始前は null
endedAt実際の終了時刻。終了前は null

イベントによっては tags・memo・backgroundUrl などが追加で載ることもあります。上の 6 つ以外のフィールドはイベントごとに異なるので、実際に使う前に console.log(payload) で確認してください。

ユーザー行動のログ(任意)

いいね・共有・チャット送信など、プレイヤー内の UI タップを自社で追跡したい場合は EVENT_LOG アクションを登録します。上で扱ったアクションと違い、処理すべきビジネスロジックがない純粋なログ用途なので、別途の有効化依頼なしにすぐ使えます。

EVENT_LOG: function (payload) {
  console.log(payload.name, payload.feature, payload.parameter);
  // 例: payload.name が 'like_button', 'share_button', 'chat_send_button', 'coupon' など
}
フィールド説明
nameイベント名(ボタン・アクションごとに異なります)
feature"click" / "action" / "show"
parameterイベントごとの参照情報(ある場合)
campaignKey配信の識別子

追跡できるイベント名

payload.feature で性格が分かれます — click は視聴者が直接押したもの、show は画面に現れたもの、action はそれ以外の動作です。

featureイベント名
clickback_button · option_button · share_button · pip_button · like_button · chat_button · chat_send_button · mute_button · unmute_button · hide_controls · show_controls · video_expand_button · video_contract_button · landscape_button · portrait_button · coupon · notice · banner · product_list_button · product_list_item · product_list_banner · product_buy_button · product_add_to_watchlist · product_remove_from_watchlist · brand_favorite_button · benefit_button · benefit_contents · qna_list_button · qna_list_faq_tab · qna_list_all_answer_tab · qna_list_my_answer_tab · qna_chat_card · video_display_resolution_change · video_display_resolution_close · edit_nickname_close_button · edit_nickname_clear_button · edit_nickname_save_button · replay_play_button · replay_pause_button
showplayer_on_foreground · player_on_background · player_active_seconds · product_list_banner · show_qna_chat_card · quiz_question_show · quiz_answer_show
actionproduct_list_show · product_list_hide · product_list_expand · quiz_select · replay_seek · redirect_campaign

配信にクーポン・クイズ・Q&A などがなければ、該当するイベントは発生しません。一覧にない名前が届いた場合は新しく追加されたものなので、payload をそのまま渡して記録しておけば大丈夫です。

視聴時間を計る

プレイヤーがアクティブな間、player_active_seconds が3 秒間隔で届きます。累計視聴時間は parameter.activatedDuration に計算済みで届くので、自分で足し合わせる必要はありません。

parameter フィールド説明
activatedDuration累計視聴時間(ミリ秒)。タブが隠れていた区間は除かれています
interval直前の報告からの経過時間(ミリ秒)
activatedAt視聴を開始した時刻(ミリ秒の timestamp)
videoCurrentTime映像の再生位置(秒)。アーカイブのどこを見ているか
mode'LIVE' · 'REPLAY'(アーカイブ)· 'PREVIEW'(プレビュー)— ライブとアーカイブの視聴時間を分けて集計するときに使います
EVENT_LOG: function (payload) {
  if (payload.name === 'player_active_seconds') {
    const p = payload.parameter;
    // 累計視聴時間は SDK が計算して送ってくれます(ミリ秒)
    analytics.track('live_watch', {
      campaignKey: payload.campaignKey,
      mode: p.mode,                       // LIVE / REPLAY / PREVIEW
      seconds: Math.floor(p.activatedDuration / 1000)
    });
  }
}

累計は配信中(ONAIR)で、かつタブが画面に見えているときに進みます。タブが隠れていた区間は activatedDuration に含まれないので、player_on_foreground / player_on_background で別途ふるい分ける必要はありません。

完了の確認

  • クーポンをタップすると、登録したコールバックが呼ばれる
  • 商品をタップすると、payload で商品情報が届く
  • ゲストがチャットなどログインの必要な機能をタップすると LOGIN_REQUIRED が呼ばれる

前へ ← ミッション 2 · ユーザー情報の連携次へ → ミッション 4 · 他のページでも配信を知らせる

ミッション

ミッション 4 · 他のページでも配信を知らせる

目標配信を表示したページの外からも視聴者を配信へ連れてくる
事前準備ミッション 1 が完了(プレイヤーを表示するページが 1 つあること)

ミッション 1 が「配信をどこに描くか」だったのに対し、このミッションはどうやってそのページへ来てもらうかです。手段は 3 つあり、互いに独立しているので必要なものだけ使ってください。

ミニプレビュー — 配信中の番組を他のページの隅に表示する

配信中のものがあると、配信ページ以外のページの隅に小さなバナーが出て配信をプレビューします。視聴者がタップするとモーダル プレイヤーへそのまま繋がります。

別途の呼び出しは不要です。プレビューを出したいページに initPlugin() を入れておけば、配信中のものがあるときに自動で表示されます。そのため通常は共通レイアウトに初期化コードを一度入れるだけで済みます。

<!-- 共通レイアウト(全ページが共有する head 領域)に一度だけ -->
<script src="https://static.shoplive.cloud/shoplive.js"></script>
<script>
  cloud.shoplive.initPlugin({ accessKey: 'YOUR_ACCESS_KEY' });
</script>

いつ出て、いつ出ないか

原理は 1 つです — 視聴者がすでに配信を見ているページには出ません。配信へ連れてくるのが目的なのに既に来ているので出す理由がなく、画面を覆うだけです。残りは重複表示を防ぐための条件です。

こういうときは出ません理由
同じページに setPlayer のプレイヤーが表示されているときすでに配信を見ている画面です。プレイヤーが閉じれば再び出ます
モーダル プレイヤーが開いているとき
setOverall のメイン配信領域が生きているとき
ページが iframe の中で開かれたときコンソールに Disabled mini preview in iframe が出ます
ブラウザ PIP から来たページのときアドレスに csl_bp があれば既に PIP で視聴中なのでスキップします(ミッション 3)
視聴者が閉じたあと、猶予時間の中にあるときすぐ下の閉じたあとどのくらい出ないかを参照
閉じたあとどのくらい出ないか — 設定がなければそのセッション中ずっと出ません 視聴者がバナーを閉じるとその時刻がセッション ストレージ(sl_p.close_clicked_timestamp)に記録され、Admin に設定された猶予時間(秒)のあいだ再表示されません。この値が設定されていない場合は猶予ではなくブロックです — そのセッション中は二度と出ません。猶予時間を設けたい場合は Shoplive 担当者へ設定をご依頼ください。

同じタイムスタンプはモーダル プレイヤーを閉じたときにも記録されます。そのため視聴者が配信を見て閉じると、ミニプレビューも一緒に静かになります。

開発中にもう一度見たい場合は、ブラウザの開発者ツールのセッション ストレージから上のキーを削除してください。

自分で表示・非表示にする 任意

自動で出るのを避け、自社が決めたタイミングだけ表示したい場合は、初期化で自動表示をオフにして自分で呼び出します。

// 初期化時に自動表示をオフにする
cloud.shoplive.initPlugin({
  accessKey: 'YOUR_ACCESS_KEY',
  useAutoPreview: false
});

// 好きなタイミングで
cloud.shoplive.showLiveMiniPreview();     // 表示
cloud.shoplive.dismissLiveMiniPreview();  // 非表示

自動表示をオフにしても上のブロック条件はそのまま適用されます — showLiveMiniPreview() を直接呼んでも、iframe の中だったり猶予時間中だったりすれば何も起きません。

タップ時の動作を変える 任意

デフォルト動作はモーダル プレイヤーを開くことです。独自のライブページへ送りたい場合は下のように割り込みます。

cloud.shoplive.setOnClickLiveMiniPreview(function (campaign) {
  // campaign には campaignKey · title · campaignStatus などが入っています
  location.href = '/live?ck=' + campaign.campaignKey;
});

バナーが表示・非表示・クローズされる瞬間は通知イベント(ON_LIVE_MINI_PREVIEW_SHOWN · ON_LIVE_MINI_PREVIEW_HIDDEN · ON_CLICK_CLOSE_LIVE_MINI_PREVIEW)で分かります。

位置とサイズ

どちらも自社コードでは変更しません — 位置と余白は Shoplive Admin の設定で、サイズは画面幅で決まります。周囲の UI をずらすときの参考にしてください。

位置
項目どう決まるか
デフォルトの位置Admin の position — デフォルト値は右下(BOTTOM_RIGHT)
画面端からの余白Admin の marginTop · marginRight · marginBottom · marginLeft — デフォルト値はそれぞれ 16(px)
視聴者が動かすドラッグで動かせます。動かした位置はセッション ストレージ(cslltposclnm)に記憶され、ページを移動しても保持されます。Admin 設定でドラッグを禁止することもできます

いま適用されている値は ON_PLUGIN_INITIALIZED イベントで読み取れます — ミニプレビューが出る位置を避けて自社 UI(フローティングボタンなど)を配置するときに使います。ただし視聴者がドラッグで動かしたあとは実際の位置が変わります。

サイズ
配信の形画面幅幅高さ
縦型(9:15)1025px 以上17vw17vw × 15/9(幅の約 1.67 倍)
481 〜 1024px26vw26vw × 15/9
480px 以下35vw35vw × 6/4(幅の 1.5 倍)
横型(15:9)すべての幅26vw26vw × 9/15
配信の形最小最大
縦型100 × 150px200 × 332px
横型160 × 96px332 × 200px

比率は 9:16・16:9 ではなく 9:15・15:9 です。ピクセル単位で位置を合わせるときはご注意ください。

プレイヤーの共有ボタン(ui.shareButton)が作るアドレスと、そのアドレスから来たときの動作です。shareUrl を指定したかどうかで、付くパラメータとその後の動作が変わりますので、2 つを分けてご覧ください。

initPlugin の設定共有されるアドレスそのアドレスから来ると
shareUrl 未指定(デフォルト)現在のページのアドレス + ?_sl_ck={campaignKey}同じページに setOverall があれば、SDK がこの値を読んでモーダル プレイヤーを自動で開きます
shareUrl: 'https://my-shop.com/live'指定したアドレス + ?ck={campaignKey}自動では開きません。自社コードで ck を読み、自分でプレイヤーを表示する必要があります
// shareUrl を指定した場合 — 受け取る側で自分で開きます
const ck = new URLSearchParams(location.search).get('ck');
if (ck) {
  cloud.shoplive.showFeaturedPlayerModal({ campaignKey: ck });
  // または cloud.shoplive.setPlayer('shoplive-player', { campaignKey: ck });
}
モーダルが開くとアドレスも変わります どの経路であれモーダル プレイヤーが開くと、SDK が現在のアドレスに _sl_ck を付け、閉じると戻します。おかげで再生中にアドレスバーをコピーして送れば、受け取った人も同じ配信が開いた状態で入ってこられますし、モバイルで戻るを押してもページを離れずモーダルだけが閉じます。独自ルーターと衝突する場合は disableHistoryHook でオフにできます。

マーケティングの流入経路を残すには、共有・広告のアドレスに utm_source · utm_medium · utm_campaign · utm_content を付けてください。SDK がこの値を読み取り、視聴・コンバージョンの記録に併せて残します(ミッション 6)。

utm_source がない場合は広告 ID のパラメータが代わりに使われます — adid · adId · adld · adLd · ad-ld · ad-id · ad-Id のうち最初に見つかった値です。広告プラットフォームが adid で送ってくる場合は、アドレスを直さなくてもそのまま拾われます。

配信カード · 配信中カバー 任意

リスト全体(方法 C)までは要らず、特定の配信 1 つだけ、あるいは配信中のときだけ何かを見せたいときに使います。

関数何が描かれるか
setLivePreview(containerId, { campaignKey, onClick })指定した配信のプレビューカード。配信中なら映像が、終了していればポスター画像が出ます。onClick を渡すとタップ時にその関数が実行されます
destroyLivePreview(containerId?)上のカードを削除します。引数を省略するとページ上のすべてのカード
setOnAirCover(containerId)配信中のものがあるときだけその領域にカバーが現れます。なければ何も描きません
setLandscapeOnAirCover(containerId)上と同じで横型配信向けのカバー
<div id="live-card"></div>
<script>
  cloud.shoplive.setLivePreview('live-card', {
    campaignKey: 'YOUR_CAMPAIGN_KEY',
    onClick: function (campaign) {
      cloud.shoplive.showFeaturedPlayerModal({ campaignKey: campaign.campaignKey });
    }
  });
</script>

<div id="on-air-cover"></div>
<script>
  cloud.shoplive.setOnAirCover('on-air-cover');
</script>

カバーが実際に表示されたかは ON_ONAIR_COVER_SHOWN イベントの payload.show で分かります — 配信がなくカバーが出ないときに、その場所を別のバナーで埋めるといった使い方ができます。

完了の確認

  • 配信中のとき、初期化コードを入れた他のページの隅にミニプレビューが出る
  • ミニプレビューをタップするとモーダル プレイヤーが開く(または自社が指定した動作が実行される)
  • 再生中にアドレスバーをコピーして新しいタブに貼ると、同じ配信が開いた状態で表示される

前へ ← ミッション 3 · ユーザー操作を処理する次へ → ミッション 5 · プレイヤーを制御する

ミッション

ミッション 5 · プレイヤーを制御する 任意

目標すでに表示されているプレイヤーを自社コードから操作する — クーポンを消す、ミュート、ダイアログを出すなど
事前準備ミッション 1 でプレイヤーが表示されている状態

ミッション 3 が「プレイヤーからの知らせを受け取る」側だとすれば、このミッションはその逆方向です。プレイヤーのオブジェクトを取得して命令を送ります。

SDK の読み込みから命令の送信までを 1 ページにまとめると次のようになります。1 · 2 · 4 は ミッション 1 方法 A そのままで、このミッションが加えるのは 3 と 5 です。

<!-- 1. SDK の読み込み -->
<script src="https://static.shoplive.cloud/shoplive.js"></script>

<!-- 2. プレイヤーが入る場所 -->
<div id="shoplive-player"></div>

<!-- 3.(任意)プレイヤーを操作する自社 UI — ここではプレイヤー外のミュートボタン -->
<button type="button" id="mute-btn">ミュート</button>

<script>
  // 4. 初期化してプレイヤーを表示します(ミッション 1)
  cloud.shoplive.initPlugin({ accessKey: 'YOUR_ACCESS_KEY' });
  cloud.shoplive.setPlayer('shoplive-player', { campaignKey: 'YOUR_CAMPAIGN_KEY' });

  // 5.(任意)命令を送ります — ここでは外のボタンが押されたとき
  document.getElementById('mute-btn').addEventListener('click', function () {
    const player = cloud.shoplive.getPlayer('YOUR_CAMPAIGN_KEY');
    if (!player) return;              // まだ表示されていなければ何もしません
    player.sendMessage('mute');
  });
</script>

3 · 5 はこの例で選んだ 1 つの方式にすぎません。プレイヤーの外にボタンを置いて押したらミュートする形を示しましたが、命令を送るタイミングは何でも構いません — 自社ページの別の UI、スクロールやタイマーなどの独自ロジック、あるいは ミッション 3 のコールバックの中など、どこからでも getPlayer() で取得して送れます。プレイヤーをただ表示するだけなら、このミッション自体が不要です。

setPlayer() のすぐ次の行で getPlayer() を呼ぶと undefined です initPlugin() はサーバーから設定を取得する非同期の処理で、その間 setPlayer() はキューに入って後から実行されます。そのためすぐ次の行にはまだプレイヤーが存在しません。

上の例のように視聴者がボタンを押すタイミングで取得するのが一番簡単です。ページが開いてすぐ何かを送る必要があるなら、再生が始まった通知を受け取ってから取得してください。
cloud.shoplive.initPlugin({
  accessKey: 'YOUR_ACCESS_KEY',
  messageCallback: {
    // 再生が始まった直後 — この時点ではプレイヤーが必ず存在します
    ON_PLAYER_STARTED: function (payload) {
      const player = cloud.shoplive.getPlayer(payload.campaignKey);
      if (player) player.sendMessage('hideControls');
    }
  }
});

cloud.shoplive.setPlayer('shoplive-player', { campaignKey: 'YOUR_CAMPAIGN_KEY' });

プレイヤーを取得する

呼び出し何が返るか
getPlayer()いまアクティブなプレイヤーを 1 つ。配信中(ONAIR)のものがあればそれを優先し、なければ最後に作られたプレイヤーを返します
getPlayer('CAMPAIGN_KEY')その配信のプレイヤー。playerAlias を指定していれば別名でも探せます
getActivePlayers()いま生きているプレイヤーの配列。1 ページに複数表示しているとき、すべてを巡回するのに使います
プレイヤーがなければ undefined です まだ setPlayer が実行される前や、すべて片付けられたあとは getPlayer() は何も返しません。messageCallback が呼ばれる瞬間はプレイヤーが表示されている時点なので安全ですが、その中で fetch などを待ったあとは話が別です — 待っている間に視聴者がモーダルを閉じたかもしれません。非同期の待機のあとはプレイヤーを取り直し、if (player) で確認してください。

プレイヤーのオブジェクトから直接読める値は次のとおりです。

プロパティ説明
campaignKeyこのプレイヤーが再生している配信のキー
campaignStatus'READY' · 'ONAIR' · 'CLOSED' — リアルタイムで更新されます
playerAlias指定していればその別名
containerプレイヤーが入っている、自社が作った div 要素

送れるコマンド

player.sendMessage(コマンド, payload) の形です。以下は自社連携で使うものです。

コマンドpayload動作
removeCouponなし画面に出ているクーポン ポップアップを消します。クーポン発行の処理を終えたあとに呼ぶのが一般的です
removeBanner · removeNoticeなしバナー · お知らせのポップアップを消します
mute · unmuteなしミュートのオン · オフ
playVideo · pauseVideoなし再生 · 一時停止
videoRefreshなし映像を読み込み直します。ネットワークが切れて復帰したあとの回復用
hideControls · showControlsなしコントロール UI の非表示 · 表示
dismissGoodsListなし開いている商品リストのポップアップを閉じます
GET_CURRENT_PLAYBACK_TIMEなし現在の再生位置を問い合わせます。答えはすぐには返らず CURRENT_PLAYBACK_TIME イベントで戻ってきます — 下を参照
showDialog{ title, message }
任意: cancelText · confirmText · confirmTextColor · confirmBackgroundColor
プレイヤーの上にダイアログを出します。confirmText を渡すと確認 · キャンセルの 2 ボタンになり、渡さなければ閉じるボタン 1 つだけになります。title は空にすると省略されます
showToast{ message }
任意: duration · position
短いトーストを表示します。duration はミリ秒で、0 なら自分で消すまで残ります。position はデフォルト 'BOTTOM'
答えが返ってくるコマンド — 再生位置を問い合わせる ほとんどのコマンドは送ったら終わりですが、GET_CURRENT_PLAYBACK_TIME は問い合わせて答えを受け取る唯一のコマンドです。答えは messageCallback の CURRENT_PLAYBACK_TIME に届きます。
// 1) 問い合わせる
cloud.shoplive.getPlayer(PAGE_CAMPAIGN_KEY).sendMessage('GET_CURRENT_PLAYBACK_TIME');

// 2) 答えを受け取る
const messageCallback = {
  CURRENT_PLAYBACK_TIME: function (payload) {
    payload.playbackTimeInSeconds;  // 132.4  (数値、秒)
    payload.playbackTime;           // '00:02:12'  (HH:mm:ss の文字列)
  },
};

ライブなら配信開始時刻からの経過時間、アーカイブなら映像の現在の再生位置です。配信開始時刻がまだ分からない場合は 0 が返ります。

const messageCallback = {
  DOWNLOAD_COUPON: function (payload) {
    fetch('YOUR_COUPON_API', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ coupon: payload.coupon })
    })
      .then(function (res) { return res.json(); })
      .then(function (res) {
        // 応答を待つ間にプレイヤーが閉じている可能性があるので、ここで取り直します
        const player = cloud.shoplive.getPlayer(payload.campaignKey);
        if (!player) return;

        if (res.success) {
          player.sendMessage('showDialog', {
            title: 'クーポン発行完了',
            message: 'クーポン番号 ' + payload.coupon + ' が発行されました。'
          });
          player.sendMessage('removeCoupon');   // 受け取ったクーポンは画面から片付ける
        } else {
          player.sendMessage('showToast', { message: 'クーポンはすべて配布済みです。' });
        }
      })
      .catch(function () {
        const player = cloud.shoplive.getPlayer(payload.campaignKey);
        // 失敗したときに何もしないと、視聴者には押しても反応がないように感じられます
        if (player) player.sendMessage('showToast', { message: 'しばらくしてからもう一度お試しください。' });
      });
  }
};

cloud.shoplive.initPlugin({ accessKey: 'YOUR_ACCESS_KEY', messageCallback });

上の例で押さえておきたい点が 2 つあります。

  • getPlayer() ではなく getPlayer(payload.campaignKey) です。引数なしで呼ぶと配信中(ONAIR)のものが優先されるため、1 ページにプレイヤーが複数あるときクーポンをタップしたのとは別のプレイヤーにダイアログが出ることがあります。イベントの payload に campaignKey が入っているので、そのまま渡せば大丈夫です。
  • プレイヤーは await / then のあとに取り直します。サーバーの応答を待つ間に視聴者がモーダルを閉じると、そのプレイヤーは消えています。コールバックの先頭で掴んだオブジェクトにメッセージを送っても、どこにも届きません。

上の表にないコマンド名をコードで見かけた場合は、モバイル SDK の WebView や Shoplive の運用ツールが使う内部コマンドです。Web 連携では使いません。

完了の確認

  • getPlayer() がプレイヤーのオブジェクトを返し、campaignKey が表示した配信と一致する
  • クーポンのタップ後に removeCoupon を送るとクーポン ポップアップが消える
  • showDialog で送ったダイアログがプレイヤーの上に表示される

前へ ← ミッション 4 · 他のページでも配信を知らせる次へ → ミッション 6 · 計測 — 流入と購入

ミッション

ミッション 6 · 計測 — 流入と購入

目標どのチャネルから来て配信を見て、実際に購入まで至ったかを Shoplive の統計に繋げる
事前準備注文完了ページにスクリプトを入れられること ·(ログインのあるサービスなら)視聴時と同じ userId

視聴者が商品をタップして商品ページへ移動した瞬間、SDK の追跡は終わります。そのあと決済が成立したかは自社のページでしか分からないので、購入完了の時点で一度知らせていただくことで「この配信がどれだけ売上を作ったか」が集計されます。

どの購入がコンバージョンになるか 視聴者がライブ(またはアーカイブ)の映像を3 秒以上見たあと、その映像に登録された商品を28 日以内に購入するとコンバージョンとして記録されます。基準は最後に見た映像で、ライブ(アーカイブ)とショートフォームはそれぞれ別に集計されます。

どこから来たか — マーケティング流入の計測

配信ページのアドレスに utm_ で始まるパラメータを付けておくと、SDK がその値を読み取りどのチャネルから来た視聴者かを併せて記録します。Instagram のバナーから来た人と、SMS から来た人の視聴・購入を分けて見られます。

パラメータ何を入れるか例
utm_source流入チャネルinstagram
utm_mediumメディアの種別banner
utm_campaignマーケティング キャンペーンspring_sale
utm_contentクリエイティブtype2

4 つすべてを入れる必要はなく、必要なものだけ付ければ大丈夫です。

https://my-shop.com/live?utm_source=instagram&utm_medium=banner&utm_campaign=spring_sale
SDK は initPlugin() を呼ぶ瞬間のページアドレスから読み取ります つまりその時点でアドレスバーにクエリが残っている必要があります。SPA でルーティングしながらクエリストリングを落としてから初期化したり、広告リンクを受けてクエリのないアドレスへリダイレクトしてからプレイヤーを表示したりすると、流入情報がまるごと消えます — エラーも出ず、ただ空の値として記録されます。

ここで読み取った値は購入コンバージョンの報告にも自動で付いていきます。別途渡すものはなく、流入 → 視聴 → 購入が一本に繋がります。

集計結果は Shoplive Admin の統計で流入チャネル別に分けて見られます。

広告プラットフォームから来る場合

広告プラットフォームはリンクに独自の計測パラメータを付けて送ってきます。SDK がページのアドレスをまるごとプレイヤーまで渡すので、自社で処理することはありません — ただしそのアドレスがそのまま残っている必要があります。

  • Web — 広告リンクが着地したランディングページでクエリストリングを消さないでください。リダイレクトを 1 回挟む場合は、クエリをそのまま引き継いで渡してください
  • ハイブリッドアプリ(WebView) — アプリが広告リンクを受けて WebView を開くとき、クエリを WebView の URL へそのままコピーする必要があります。WebView 自体の設定は付録 D をご覧ください
  • ネイティブアプリ — Web SDK ではなく iOS・Android ネイティブ SDK のディープリンク処理の領域です。Shoplive 担当者までお問い合わせください

広告 ID は adId でも受け取ります — adid · ad-id のように表記が違っても認識します。

購入コンバージョン ステップ 1 · どこに入れるか

注文が確定したあと一度だけ開かれるページ — 通常は注文完了・決済完了ページです。カートや決済の途中の画面に入れると離脱した注文まで購入として集計され、リロードで何度も開かれるページに入れると同じ注文が重複して報告されます。

購入コンバージョン ステップ 2 · 送る

SDK の読み込み → 初期化 → ユーザー情報 → 報告 の順です。初期化が終わる前に sendConversionEvent() を呼んでも SDK が待たせてから実行するので、順番が原因で失敗することはありません。

<script src="https://static.shoplive.cloud/shoplive.js"></script>
<script>
  cloud.shoplive.initPlugin({ accessKey: 'YOUR_ACCESS_KEY' });

  // ログインユーザーなら、視聴時と「同じ」userId を入れます(ステップ 3 参照)
  cloud.shoplive.setUserObject({ userId: 'MEMBER_ID' });

  cloud.shoplive.sendConversionEvent({
    accessKey: 'YOUR_ACCESS_KEY',   // 必須
    eventType: 'purchase',          // 必須 — 'purchase'(購入完了)/ 'cartIn'(カートに追加)
    orderId: 'UNIQUE_ORDER_ID',     // 自社の注文番号
    products: [
      { productId: 'PRODUCT_ID_1', sku: 'PRODUCT_SKU_1', purchaseUnitPrice: 10000, purchaseQuantity: 1, currency: 'KRW' },
      { productId: 'PRODUCT_ID_2', sku: 'PRODUCT_SKU_2', purchaseUnitPrice: 15000, purchaseQuantity: 2, currency: 'KRW' }
    ]
  });
</script>
フィールド必須説明
accessKey必須初期化で渡していても、このオブジェクトにもう一度入れる必要があります — ないとコンソールに Invalid request が出るだけで送信されません
eventType必須どのコンバージョンか — 購入完了は 'purchase'、カート追加は 'cartIn'
orderId任意自社の注文番号。そのまま一緒に送信されます — どの注文のコンバージョンかをあとで突き合わせたいなら入れておいてください
products任意購入した商品の配列 — 各項目のフィールドは下の表を参照
timestamp任意購入時刻。入れなければ呼び出し時刻が使われます
custom任意一緒に残したい任意の値
userObject · userJWT任意この呼び出しだけに使うユーザー情報。入れなければ setUserObject() · setUserJWT() で渡した値が使われます

アドレスに utm_source などの UTM パラメータがあれば、このリクエストに一緒に載って送信されます — 広告・共有の流入別にコンバージョンを分けて見たい場合は、流入アドレスに UTM を付けておいてください。

products 配列の各項目です。

フィールド必須説明
productId必須Shoplive に登録された商品 ID
sku必須商品コード
purchaseUnitPrice必須購入単価
purchaseQuantity必須購入数量
currency必須通貨(例: 'KRW')
customerProductId任意自社独自の商品 ID

ここでの「必須」は SDK の型宣言に基づくものです。実際には accessKey と eventType だけを検査して送信するため、一部が欠けてもリクエスト自体は送られます — ただし集計から静かに漏れることがあるので、埋めて送ってください。

購入コンバージョン ステップ 3 · 視聴記録と結び付く基準

視聴記録と購入報告は別々のリクエストとして送られます。映像を 3 秒以上見た時点でプレイヤーが視聴記録を送り、購入は上の sendConversionEvent() が送ります。この 2 つをサーバーが識別子で突き合わせてコンバージョンが成立します。そのため識別子がずれていると、両方の記録が残っていてもコンバージョンとして集計されません — 次の 3 つのいずれかが一致している必要があります。

区分結び付く基準自社で合わせるもの
ログインユーザーuserId配信を見るときにミッション 2 で渡した値とまったく同じ値を注文完了ページでも渡します。ハッシュ化しているなら同じハッシュ値である必要があります
未ログイン(ゲスト)ブラウザに保存された匿名識別子呼び出すものはありませんが、同じブラウザ · 同じドメインである必要があります
独自の識別子がある場合anonIdinitPlugin({ anonId }) で渡すと、ログインなしでも視聴と購入を結び付けられます。ページのアドレスに ?anonId= で渡しても認識されます
ゲストのコンバージョンはドメインが分かれると途切れます 匿名識別子はブラウザのストレージに保管され、ストレージはドメインごとに分離されています。配信を見せたページと注文完了ページのドメインが違うと(例: www.shop.com で見て order.shop.com で決済)、同じ人として繋がりません。ドメインを揃えるのが難しければ、userId か anonId で結び付けるのが確実です。

ショップ プラットフォームでは 任意

注文完了ページを自分で作れないプラットフォームでは、以下の場所に同じ呼び出しを入れます。注文番号と商品情報をプラットフォームが渡す値で埋める部分だけが異なります。

Cafe24

スキンの order_result.html(注文完了画面)の </body> 直前に入れます。注文番号は Cafe24 が埋める {$order_id} で受け取り、注文商品のリストは Cafe24 API で取得します。

<script src="https://static.shoplive.cloud/shoplive.js"></script>
<script>
  cloud.shoplive.initPlugin({ accessKey: 'YOUR_ACCESS_KEY' });

  const orderId = '{$order_id}';   // Cafe24 が実際の注文番号に置き換えます

  // 会員注文なら、視聴時と同じ userId を入れます
  // cloud.shoplive.setUserObject({ userId: 'MEMBER_ID' });

  cloud.shoplive.sendConversionEvent({
    accessKey: 'YOUR_ACCESS_KEY',
    eventType: 'purchase',
    orderId: orderId,
    products: [
      // Cafe24 API で取得した注文商品を { productId, sku, purchaseUnitPrice, purchaseQuantity, currency } の形で埋めます
    ]
  });
</script>

注文商品を Cafe24 API(CAFE24API.getOrderDetailInfo)で取得するにはアプリキーが必要です。この値は Shoplive 担当者までお問い合わせください。

Shopify

注文完了画面にスクリプトを直接入れられないため、カスタムピクセルに登録して checkout_completed のタイミングで呼び出します。

const script = document.createElement('script');
script.src = 'https://static.shoplive.cloud/shoplive.js';
script.async = true;
document.head.appendChild(script);

script.onload = function () {
  cloud.shoplive.initPlugin({ accessKey: 'YOUR_ACCESS_KEY' });

  analytics.subscribe('checkout_completed', function (event) {
    const checkout = event.data.checkout;

    // 会員注文なら、視聴時と同じ基準で userId を入れます
    const customerId = checkout.order.customer && checkout.order.customer.id;
    if (customerId) {
      cloud.shoplive.setUserObject({ userId: String(customerId) });
    }

    cloud.shoplive.sendConversionEvent({
      accessKey: 'YOUR_ACCESS_KEY',
      eventType: 'purchase',
      orderId: checkout.order.id,
      products: checkout.lineItems.map(function (item) {
        return {
          productId: item.variant.product.id,
          sku: item.variant.sku,
          purchaseUnitPrice: parseFloat(item.variant.price.amount),
          purchaseQuantity: item.quantity,
          currency: item.variant.price.currencyCode
        };
      })
    });
  });
};

完了の確認

  • 注文完了ページで、ネットワークタブに /conversion/event リクエストが 1 回記録される
  • リロードや戻るで同じ注文が複数回報告されない
  • (ログイン)リクエスト送信時の userId が、配信を見たときに渡した値と同じ
  • 集計結果は Shoplive Admin のコンバージョン レポートで確認します — 反映に時間がかかることがあります

前へ ← ミッション 5 · プレイヤーを制御する次へ → 全体のサンプル

はじめに

全体のサンプル — ミッションを 1 ページにまとめる

ここまでの内容を 1 ページにまとめると次のような形になります。実際のサービスに合わせて YOUR_ACCESS_KEY、YOUR_CAMPAIGN_KEY とコールバック内のロジックを埋めるだけです。購入コンバージョン(ミッション 6)はこのページではなく注文完了ページに入るので、下に分けて置いています。

ライブページ

<script src="https://static.shoplive.cloud/shoplive.js"></script>
<script>
  // ── ミッション 3 · ユーザー操作の処理
  const messageCallback = {
    DOWNLOAD_COUPON: function (payload) {
      // 自社のクーポン発行 API を呼び、成功したときだけ画面からクーポンを片付ける(ミッション 5)
      fetch('YOUR_COUPON_API', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ coupon: payload.coupon })
      })
        .then(function (res) { return res.json(); })
        .then(function (res) {
          // 応答を待つ間にプレイヤーが閉じている可能性があるのでここで取得する
          const player = cloud.shoplive.getPlayer(payload.campaignKey);
          if (!player) return;
          if (res.success) {
            player.sendMessage('removeCoupon');
          } else {
            player.sendMessage('showToast', { message: 'クーポンはすべて配布済みです。' });
          }
        });
    },
    LOGIN_REQUIRED: function () {
      location.href = '/login?returnTo=' + encodeURIComponent(location.href);
    },
    ON_CLICK_CAMPAIGN_LIST_ITEM: function (payload) {
      // デフォルト動作はモーダルを開くこと。独自の配信詳細ページへ送りたいときだけ上書きします
      //(モーダルで開くデフォルト動作をそのまま使うなら、このコールバックは登録しないでください)
      location.href = '/live/' + payload.campaign.campaignKey;
    }
  };

  // ── ミッション 1 · 初期化(ミッション 4 · 共有 URL の指定)
  cloud.shoplive.initPlugin({
    accessKey: 'YOUR_ACCESS_KEY',
    messageCallback: messageCallback,
    shareUrl: 'https://my-shop.com/live'
  });

  // ── ミッション 2 · ログインユーザーなら連携(ゲストならこのブロックごとスキップ)
  cloud.shoplive.setUserObject({ userId: 'YOUR_HASHED_USER_ID', userName: 'YOUR_USER_NAME' });

  // このページに固定で表示する配信
  const PAGE_CAMPAIGN_KEY = 'YOUR_CAMPAIGN_KEY';
</script>

<!-- ── ミッション 1 · 方法 A — 特定の配信 1 つをこの場所に -->
<div id="shoplive-player"></div>
<script>
  cloud.shoplive.setPlayer('shoplive-player', {
    campaignKey: PAGE_CAMPAIGN_KEY,
    ui: { shareButton: true }
  });
</script>

<!-- ── ミッション 1 · 方法 C — メイン配信 + リストをテンプレートで(方法 A とどちらか一方) -->
<!--
<div id="shoplive-overall-area"></div>
<script>
  cloud.shoplive.setOverall('shoplive-overall-area');
</script>
-->

<!-- ── ミッション 4 · 共有リンクから来た場合はその配信を開く -->
<script>
  const ck = new URLSearchParams(location.search).get('ck');
  // このページに既に表示している配信ならモーダルを重ねて開かない
  if (ck && ck !== PAGE_CAMPAIGN_KEY) {
    cloud.shoplive.showFeaturedPlayerModal({ campaignKey: ck });
  }
</script>

注文完了ページ

<script src="https://static.shoplive.cloud/shoplive.js"></script>
<script>
  cloud.shoplive.initPlugin({ accessKey: 'YOUR_ACCESS_KEY' });

  // 配信を見たときと「同じ」userId でなければコンバージョンに繋がりません
  cloud.shoplive.setUserObject({ userId: 'YOUR_HASHED_USER_ID' });

  cloud.shoplive.sendConversionEvent({
    accessKey: 'YOUR_ACCESS_KEY',
    eventType: 'purchase',
    orderId: 'UNIQUE_ORDER_ID',
    products: [{
      productId: 'PRODUCT_ID',
      sku: 'PRODUCT_SKU',
      purchaseUnitPrice: 10000,
      purchaseQuantity: 1,
      currency: 'KRW'
    }]
  });
</script>

前へ ← ミッション 6 · 計測 — 流入と購入次へ → 付録

付録

付録 · 特定の状況でのみ

ミッションには含まれない、特定の状況でのみ必要になる機能です。

A. 有効化が必要な機能

次の 4 つはアカウントで機能が有効になっていないと動きません。コードを入れてもボタン自体が出てこない場合は、まず有効化の有無をご確認ください — ご依頼は ask@shoplive.cloud までお願いします。

ブランドのお気に入り

プレイヤー内のブランドお気に入りボタンです。視聴者がタップすると ON_CLICK_BRAND_FAVORITE_BUTTON が届くので、自社システムに保存したうえでその結果をプレイヤーへ返します。

const messageCallback = {
  // プレイヤーが開始したとき、またはブランド情報が変わったとき — 現在のユーザーのお気に入り状態を知らせる
  ON_CHANGED_BRAND_FAVORITE: function (payload) {
    const player = cloud.shoplive.getPlayer(payload.campaignKey);
    if (!player) return;
    player.sendMessage('SEND_COMMAND_MESSAGE', {
      command: 'SET_BRAND_FAVORITE',
      payload: { identifier: payload.identifier, favorite: true }
    });
  },
  // 視聴者がボタンを押したとき — 自社サーバーに保存する
  ON_CLICK_BRAND_FAVORITE_BUTTON: function (payload) {
    const { identifier, favorite } = payload;
    fetch('YOUR_FAVORITE_API', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ identifier, favorite })
    });
  }
};

cloud.shoplive.initPlugin({ accessKey: 'YOUR_ACCESS_KEY', messageCallback });

プレイヤーを表示するときに初期状態を一緒に渡すこともできます — setPlayer(id, { campaignKey, brand: { identifier, favorite } })。

カートに入れる

商品リストにカートボタンが表示され、タップすると CLICK_PRODUCT_CART が Goods payload と一緒に届きます。自社のカートに入れたあと、入っている状態をプレイヤーへ返すとボタンの見た目が変わります。

CLICK_PRODUCT_CART: function (payload) {
  addToMyCart(payload).then(function () {
    // 入れている間にプレイヤーが閉じている可能性があるのでここで取得する(ミッション 5)
    const player = cloud.shoplive.getPlayer(payload.campaignKey);
    if (!player) return;
    player.sendMessage('SEND_COMMAND_MESSAGE', {
      command: 'SET_PRODUCT_CART_ON',
      payload: { products: [{ sku: payload.sku, isCartOn: true }] }
    });
  });
}

Shopify ストアで platform: 'SHOPIFY' を使う場合は、カートへの追加・取得を SDK が直接処理するので、上のコールバックを実装する必要はありません。

配信リマインド

配信予定(READY)状態の配信カードのタイトル下に「Subscribe」ボタンが表示されます。ボタンは initPlugin() の設定で有効にし、すべての配信予定に出す方法と特定の配信にだけ出す方法の 2 通りがあります。

方法 1 · すべての配信予定に表示

webClientSettings の中に useRemind: true を 1 行追加します。以後に登録される配信予定にも自動で適用されます。

cloud.shoplive.initPlugin({
  accessKey: 'YOUR_ACCESS_KEY',
  webClientSettings: {
    useRemind: true
  }
});
方法 2 · 特定の配信にだけ表示

ボタンを出したい配信の campaignId を文字列の配列で渡します。リストにない配信にはボタンは表示されません。入れる値は campaignKey ではなく campaignId です — ガイドの他の箇所で使う配信キーとは別の値で、Admin の配信詳細で確認できます。

cloud.shoplive.initPlugin({
  accessKey: 'YOUR_ACCESS_KEY',
  listCampaignIdsForRemindButton: ['2262194', '2262195']
});
設定の組み合わせと結果

2 つの設定は併用できます。useRemind が有効なら、リストに関係なくすべての配信予定に表示されます。

useRemindlistCampaignIdsForRemindButton結果
true未指定配信予定すべてに表示
未指定または false指定リストにある配信のみ表示
true指定配信予定すべてに表示
未指定または false未指定表示しない
ボタンのクリックを受け取る

視聴者がボタンを押すと ON_CLICK_REMIND_CAMPAIGN が届き、payload.isReminded で申し込みか解除かを判別します。このコールバックに自社のリマインド予約処理をつなげてください。

ON_CLICK_REMIND_CAMPAIGN: function (payload) {
  const campaignKey = payload.campaign.campaignKey;
  if (payload.isReminded) {
    subscribeToMyPush(campaignKey);     // リマインドを申し込む
  } else {
    unsubscribeFromMyPush(campaignKey); // リマインドを解除する
  }
}

配信予定の状態でのみ表示されます。配信が始まるか終了すると、ボタンは自動で消えます。コードの設定が Admin の設定より優先されます — Admin でリマインド機能が有効でも、useRemind: false を渡すとボタンは消えます。申し込み状態はブラウザに保存されます — 申し込み後は同じブラウザで「Completed」と表示され、もう一度押すと解除されます。

オークション

リアルタイムのオークション機能です。自社で必ず処理する必要があるのは落札者を決済へ送ることの 1 つだけで、残りのイベントは独自 UI を作ったりログを残したりするときにだけ使います。

落札者を決済へ送る

オークションが終わると落札者に案内シートが表示されます。視聴者がそのシートの決済ボタンを押すと ON_AUCTION_WINNER_CHECKOUT_CLICKED が届きます。

ON_AUCTION_WINNER_CHECKOUT_CLICKED: function (payload) {
  // payload.auction.winnerCheckoutScheme に Admin で設定した決済アドレスが入っています
  const scheme = payload.auction && payload.auction.winnerCheckoutScheme;
  location.href = scheme || ('/checkout?sku=' + payload.product.sku);
}
ON_CLICK_BUY_BUTTON と混同しないでください ON_CLICK_BUY_BUTTON は商品リストの購入ボタンで、payload は Goods です。落札者の案内シートの決済ボタンはこのイベントを発生させません — オークションの決済を ON_CLICK_BUY_BUTTON だけで処理すると、落札者がボタンを押しても何も起きません。
payload の構造

下のオークションのイベントは同じ形の payload を受け取ります — product(商品)と auction(オークション)の 2 つのかたまりです。

場所主なフィールド
payload.productproductId · sku · name · brand · originalPrice · discountPrice · currency · url · imageUrl · stockStatus · auctionStatus
payload.auctionwinnerCheckoutScheme(落札者の決済アドレス)· winner({ name, uid, userId })· leader(現在の最高入札者)· currentPrice · winningPrice · startingPrice · bidRound · bidStatus · endingAt · endedAt · recommendedPrices
payload.transactionId落札者本人にのみ、取引 ID がある場合に ON_AUCTION_WINNER_DETERMINED に併せて載ります
オークションの進行を追う
イベントいつ
ON_AUCTION_READYオークションの準備ができたとき
ON_AUCTION_STARTEDオークションが始まったとき
ON_BID_STATUS_CHANGED入札状況が変わったとき(最高額・入札者の更新)
ON_BID_RESULT_RECEIVED自分が入れた入札の結果が返ってきたとき
ON_AUCTION_BID_TIME_EXTENDED終了間際の入札で終了時間が延長されたとき
ON_AUCTION_ENDEDオークションが終わったとき
ON_AUCTION_WINNER_DETERMINED落札者が決まったとき(すべての視聴者へ)
ON_AUCTION_SELF_WON自分が落札したとき(落札者本人にのみ)
入札資格

視聴者が入札しようとして資格がない場合、CAN_BID_REQUIRED が { isLogin: true, canBid: false } と一緒に届きます。ゲストにはこのイベントではなく LOGIN_REQUIRED が届きます — まずログインしてもらう必要があるためです。

入札資格は canBid で決めます ユーザー情報を渡すときに canBid で入札可否を指定します(ミッション 2)。ただしプラットフォーム自動連携を使うと canBid: true が必ず付くため、ショップにログインしている人なら誰でも入札できるようになります。会員ランクや購入履歴で資格を絞る必要がある場合は setUserObject() を直接呼んでください。

B. PIP — ページを移動しても配信を見続ける

視聴者が配信中に商品をタップすると、商品ページへ移動して配信が途切れます。PIP はページは移動しつつ映像だけを小さく残して視聴を続けさせます。

Shoplive にご依頼いただいて有効化する機能です(ask@shoplive.cloud)。有効化後は自社コードに追加するものはありません — 視聴者が商品をタップすると SDK が自動で PIP に切り替えます。

ミッション 1 の方法 B では使えません PIP は自社ページに SDK が読み込まれていないと動作しません。方法 B(リンクで開く)は Shoplive が提供するページを開くもので、SDK が自社ページにないため PIP は有効になりません。方法 A または 方法 C をお使いください。

2 つの方式

Web PIPブラウザ PIP
どう見えるか自社ページの上に小さなプレイヤーが浮かびます。視聴者がドラッグで動かせ、見た目も Shoplive プレイヤーと地続きですブラウザが提供する標準の PIP ウィンドウです。見た目は変えられません
どこまで付いてくるか同じタブの中でのみ維持されます他のタブ・他のサイトへ行っても付いてきます
使える条件遷移先のアドレスが自社と同じドメインである必要があります(Web PIP を使う前に確認する 3 点)視聴者が直接押した操作である必要があります(ブラウザ PIP の制約)
モバイルでは自社ページの上に直接描くのでデスクトップとモバイルで同じです弱いです — Android の WebView では限定的で、アプリ内ブラウザでは動作しません。デスクトップ中心とお考えください
こんなときに自社サイト内で商品詳細へ送るとき · モバイルの比率が高いとき外部ドメイン・他サイトへ送るとき · デスクトップの比率が高いとき

Web PIP を使う前に確認する 3 点

Web PIP は遷移先のページを iframe に収めて画面全体に重ねる方式で動作します。そのため以下のいずれかに引っかかると、有効にしても画面が描画されません。有効化をご依頼になる前にご確認ください。

確認すること可能不可
同じドメインかshop.com/live → shop.com/product/1shop.com/live → m.shop.com/product/1
サブドメインが違うだけでも不可です
X-Frame-Options ヘッダー自社ページに SAMEORIGIN を設定DENY だと iframe がまったく描画されません。外部サイトは自社では変更できません
Content-Security-Policyframe-src に遷移先のアドレスを許可許可リストになければ描画されません(FAQ · CSP)
商品ページが iframe の中で開きます — 既存の機能がそのまま動くか確認してください 同じドメインであっても iframe の中ではブロックされるスクリプトがあります。決済モジュール · 外部ライブラリ · ポップアップなど、これまで使っていた機能が正常に動作するか必ず実際にご確認ください。ここが Web PIP 導入で最もよく引っかかる点です。

決済 · ログインのページでは自動的に抜けます

決済のように iframe の中で進めてはいけないページがあります。そのため Web PIP は以下のアドレスへ遷移する瞬間、PIP を解除して本当のページ遷移に切り替えます。

/orderform.html   /login.html   /basket.html   /navercheckout
自社の決済アドレスが上と異なる場合はお知らせください 上の一覧は既定値です。自社の決済・ログインページのアドレスが異なる場合はそのアドレスも除外リストに入れる必要があります — そのままにすると決済が iframe の中で進んでしまいます。Shoplive 担当者にアドレスをお伝えいただければ追加できます。

ブラウザ PIP の制約

  • 視聴者が直接押した操作からのみ有効になります。ブラウザのセキュリティ ルールなので、コードから任意に呼び出すことはできません。
  • PIP への切り替えと新しいウィンドウを開く操作を同時には行えません。両方必要な場合は、PIP に切り替える操作を先に行い、新しいウィンドウはその次の操作に分けてください。
  • モバイル対応が弱いです。デスクトップのブラウザではおおむね動作しますが、Android の WebView(自社アプリ内の Web 画面 · LINE や Instagram のようなアプリ内ブラウザ)では限定的か、まったく動作しません。視聴者の大半がモバイル、あるいはアプリの WebView から来る場合はブラウザ PIP だけでは不十分です — 同じドメイン内で動く導線は Web PIP でカバーし、外部ドメインへ出る導線だけをブラウザ PIP に任せる形で分けてください。

自社コードから直接表示する 任意

既定は自動です — 視聴者がプレイヤー内で商品やリンクをタップすると SDK が自動で PIP に切り替えます(ミッション 3 の CLICK_PRODUCT · LINK のデフォルト動作)。自社 UI の別のボタンから同じ動作を起こしたい場合は次を使います。

// Web PIP に切り替えながら指定したアドレスへ遷移します
cloud.shoplive.navigateWithPIP('/product/1', 'YOUR_CAMPAIGN_KEY');

Web PIP が有効になっていない場合や、該当する配信のプレイヤーがない場合は何も起きません。PIP の状態で視聴者が小さなプレイヤーをタップすると、PIP が解除されて配信画面に戻ります。

C. SPA で使う

  • initPlugin({ isSPA: true }) — クライアント ルーティングでページが変わっても SDK を維持します。initPlugin は 1 ページのライフサイクルで1 回だけ動作し、2 回目の呼び出しは無視されます。
  • コンポーネントが消えるときは destroyPlayer(id) · destroyOverall(id, true) で片付けてください。コンテナの DOM だけを削除すると、SDK の内部にプレイヤーが残ります。
  • 独自ルーターが URL の変化を監視している場合は、モーダルがアドレスを変更しないよう disableHistoryHook をオンにしてください。initPlugin({ disableHistoryHook: true }) でページ全体に適用することもできます。

D. 自社アプリの WebView の中で表示する

配信を組み込んだ Web ページを自社アプリの WebView で開く場合(ハイブリッドアプリ)、WebView 側の設定を変えないと映像が再生されないか、全画面に飛び出します。以下はアプリのコードで一度設定すれば済みます。

プラットフォーム設定しないと
iOS(WKWebView)configuration.allowsInlineMediaPlayback = true再生が始まる瞬間にネイティブの全画面プレイヤーへ切り替わり、プレイヤー UI が消えます
Android(WebView)settings.mediaPlaybackRequiresUserGesture = false視聴者が直接タップするまで自動再生が始まりません
// iOS — WKWebView を作るとき
let configuration = WKWebViewConfiguration()
configuration.allowsInlineMediaPlayback = true
let webView = WKWebView(frame: rect, configuration: configuration)
// Android — WebView の作成後
webView.settings.mediaPlaybackRequiresUserGesture = false
モバイルアプリに配信を入れる方法は 2 つあります この付録はすでに作った Web ページをアプリの WebView で開く場合です。アプリの画面自体に配信を組み込むには、Web SDK ではなく iOS · Android のネイティブ SDK が別途ありますので、Shoplive 担当者までお問い合わせください。

E. RequireJS / AMD 環境

SDK は映像再生に hls.js を使います。通常は SDK が https://cdnjs.cloudflare.com から <script> タグで直接読み込みますが(CSP を使うならこのオリジンも許可してください)、ページが RequireJS でモジュールを管理していてその方式が使えない場合は、ローダーを渡して代わりに読み込ませます。

cloud.shoplive.initPlugin({
  accessKey: 'YOUR_ACCESS_KEY',
  useAMD: true,
  AMDLoader: require   // 省略すると window.require を使います
});
  • ページに既に window.Hls があれば useAMD は何もしません — SDK がそのオブジェクトをそのまま使います。
  • AMDLoader を省略すると window.require で代用します。どちらもなければコンソールに Invalid AMDLoader requirejs を残して中断し、このとき映像が再生されません — 再生されないのに他のエラーが出ていない場合は、まずこのログを確認してください。
  • 通常の <script> 読み込み環境では使う機会はありません。

F. ショートフォーム SDK と同じページで

ライブ(shoplive.js)とショートフォーム(shoplive-shortform.js)は別のスクリプトですが、同じ window.cloud.shoplive オブジェクトに関数を追加する方式なので、1 ページに一緒に読み込めます。読み込み順は関係ありません。

  • 初期化はそれぞれ呼びます — initPlugin() / initShortform()
  • ユーザー情報の関数(setUserObject · setUserJWT · logout)は2 つの SDK で共有されるため、1 回呼べば両方に反映されます。最後に呼んだ値が残ります
  • ライブのミニプレビューとショートフォームのプレビューは互いを認識しません。どちらも既定の位置が画面の隅なので同じ場所で重なることがあります — 2 つの機能を併用する場合は、どちらかの位置を別の角に指定してください。ライブ側の位置はミッション 4 · 位置とサイズ、ショートフォーム側はショートフォームガイドをご覧ください

ショートフォームの連携方法はショートフォームガイドをご覧ください。

G. ショッププラットフォーム別の設置場所

Cafe24・ゴドモール(Godomall)・WISA・MakeShop・imweb・Shopify で作ったショップで、管理画面のどこにコードを入れるかをまとめました。入れるコードはミッション 1(配信一覧・プレイヤー)とミッション 2 · ステップ 3(ログイン自動連携)と同じで、ここでは場所とプラットフォーム別の会員変数だけを扱います。

すべてのプラットフォームに共通の手順
  1. 運用中のスキンをコピーし、編集用スキンで作業します — 保存した瞬間に実際のショップへ反映されるのを防ぎます
  2. 共通レイアウト(全ページが共有する上部領域)に SDK の読み込み・会員情報の要素・initPlugin() を入れます — 下のコード ①
  3. 配信一覧を表示するページを新しく作り、setOverall() を入れます — 下のコード ②
  4. メニュー(入口)にそのページのアドレスをつなぎます
  5. 配信中にミニプレビューが表示されるか確認します。表示されなければ Admin の配信詳細で API・プラグインの公開をオンにします
PC とモバイルのスキンが別のプラットフォーム(Cafe24・ゴドモール・WISA・MakeShop)では、モバイルスキンで同じ手順をもう一度行います。

① 共通レイアウト

<!-- 共通レイアウト — すべてのページに 1 回だけ(場所は各プラットフォームを参照) -->
<script src="https://static.shoplive.cloud/shoplive.js"></script>
<!-- 会員情報の要素 — プラットフォーム別(下の各プラットフォームを参照) -->
<script>
  cloud.shoplive.initPlugin({
    accessKey: 'YOUR_ACCESS_KEY',   // Admin の配信詳細からコピー
    platform: 'CAFE24'              // プラットフォームに合った値(imweb は省略)
  });
</script>

② 配信一覧ページ

<!-- 配信一覧ページ — このページの HTML 領域に -->
<div id="shoplive-overall"></div>
<script defer>cloud.shoplive.setOverall('shoplive-overall');</script>

Cafe24

ログインeclogin.cafe24.com/Shop
PC代表デザイン(대표디자인)をコピー → コピーを選んで修正(수정) → エディタの主要画面(주요화면) › メイン画面(메인화면) → 下部 HTML 領域の <!--@layout(/layout/basic/layout.html)--> から共通レイアウトを開き、<body> のすぐ下に ①
配信一覧ページ左下のフォルダ追加(폴더추가)で live フォルダ → 画面追加(화면추가)で live.html(画面分類: 選択なし(自動)) → HTML 領域の既存コードを消して ②
入口メニュータブにマウスを乗せて編集(편집) → <a href="/live/live.html"> のようにパスを入力
モバイルモバイルの代表デザインをコピーして同じ手順
購入コンバージョンスキンの order_result.html の </body> 直前 — コードはミッション 6 · プラットフォームで

会員情報の要素

<div module="Layout_stateLogon" style="display:none;">{$id} {$name}</div>

ゴドモール(Godomall)

ログインnhn-commerce.com → 設置するショップを選択
PC管理画面 › デザイン(디자인)でスキンをコピーし作業スキンに設定(一覧に WORK と表示) → 全体レイアウト(전체 레이아웃)をダブルクリック › 上部レイアウト(상단 레이아웃) → <body> のすぐ下に ① → デザインページを保存(디자인 페이지 저장)
配信一覧ページ入れるフォルダをダブルクリック › 新しいページを追加(새로운 페이지 추가) → ファイル名を入力 → 追加したページに ② → 保存
入口ページの画面表示(화면보기)でアドレスをコピー → 全体レイアウト › 上部デザイン › 上部基本ファイル(상단 기본파일)のタブに貼り付け
モバイルモバイルショップのデザインスキン一覧で同じ手順

会員情報の要素

<div style="display:none;">
  <span id="cloud-shoplive-user-id">{=gSess.memId}</span>
  <span id="cloud-shoplive-user-name">{=gSess.memNm}</span>
</div>

WISA

ログインwisa.co.kr → 設置するショップ
PCデザイン › デザイン管理 › スキン管理(디자인 › 디자인관리 › 스킨 관리) — 使用中のスキンではなく編集スキンに反映され、編集スキンのプレビューで確認します → HTML 編集 › 上部共通ページ編集(상단공통페이지 편집)の一番上に ①
配信一覧ページHTML 編集 › 追加ページ編集(추가 페이지 편집) → ページ名を入力 → 内容編集(내용편집) → エディタを HTML に切り替え → ② → 確認
入口ページのファイル名を押してアドレスをコピー → 上部共通ページ編集のタブに貼り付け
モバイルモバイル › スキン管理で同じ手順。追加ページは属性修正(속성수정)でモバイルページ使用 = 使用する(모바일페이지 사용 = 사용함)にしてからモバイル追加ページに切り替えて入力

会員情報の要素

<div style="display:none;">
  <span id="cloud-shoplive-user-id">{{$회원아이디}}</span>
  <span id="cloud-shoplive-user-name">{{$회원명}}</span>
</div>

MakeShop

注記 · MakeShop platform: 'MAKESHOP' はミッション 2 · ステップ 3の対応値一覧にありません。ショートフォーム SDK のソースではこの値の処理が無効(コメントアウト)になっており、ライブ SDK での対応可否は確認中です。下は以前のドキュメント(Document360)の方法です。ログイン名がチャットに表示されなければ、ミッション 2 · ステップ 2のように setUserObject() を直接呼んでください。
ログインmakeshop.co.kr
PC個別デザイン(개별 디자인)で設置するスキンのデザイン編集(디자인 편집하기) → 基本上部(기본 상단)に ①(会員情報・platform は下のコード)
配信一覧ページ配信一覧を表示するページに ②
入口② を入れたページのアドレスをメニューのパスに指定
モバイルモバイル D4(個別デザイン) › HTML デザイン編集(HTML 디자인 편집하기) › 基本上部で同じ手順

会員情報の要素

<div style="display:none;">
  <span id="cloud-shoplive-user-id"><!--/user_id/--></span>
  <span id="cloud-shoplive-user-name"><!--/user_name/--></span>
</div>
<script>cloud.shoplive.initPlugin({ accessKey: 'YOUR_ACCESS_KEY', platform: 'MAKESHOP' });</script>

imweb

注記 · imweb imweb には platform の値がありません。imweb がログイン会員に入れておく window.MEMBER_UID で setUserObject() を呼ぶ方法(ミッション 2 · ステップ 2)です。この変数は imweb 側の動作なので、ショップごとに値があるか確認してください。
場所imweb 管理画面 › デザイン編集 › 共通レイアウトの <head> に下のコード — すべてのページに入っていないとミニプレビューが動きません
配信一覧ページ配信一覧を表示するページの HTML ウィジェット(または body 領域)に ②
注意initPlugin() が 1 ページに 2 回入らないようにします。サーバーが必要な JWT セキュア認証(ミッション 2)は imweb では使えません
<script src="https://static.shoplive.cloud/shoplive.js"></script>
<script>
  cloud.shoplive.initPlugin({ accessKey: 'YOUR_ACCESS_KEY' });
  if (window.MEMBER_UID) {            // imweb がログイン会員に入れておく会員番号
    cloud.shoplive.setUserObject({ userId: window.MEMBER_UID });
  }
</script>

Shopify

Shopify アプリ(ShopliveAssistant)で接続 — 推奨

  1. Shopify App Store の ShopliveAssistant ページで、右上のアカウントアイコンから連携するストアで合っているか確認します
  2. Install → アプリが求める権限(担当者情報・商品データなど)を確認してインストールを終えます
  3. Shopify 管理画面の Apps › Shoplive Assistant で Shoplive アカウントにログインします
  4. ストアにつながった Access Key を確認し(編集可)、商品同期で Shopify の商品を Shoplive に取り込みます — 最近の変更分のみ / オプションを個別商品として、から選択
  5. アプリはアカウント連携と商品同期までです。プレイヤーは下のテーマコードで設置します
PC・モバイル共通オンラインストア › テーマ › 現在のテーマのアクション › コードを編集 → theme.liquid の <body> のすぐ下に下のコード
配信一覧ページオンラインストア › ページ › ページを追加 → 内容を HTML に切り替えて下の ② のコード
入口オンラインストア › ナビゲーションでメニューにそのページを追加
購入コンバージョン設定 › カスタマーイベント › カスタムピクセル — コードはミッション 6 · プラットフォームで
カートplatform: 'SHOPIFY' ならプレイヤー内のカート追加・照会を SDK が処理します — A. 有効化が必要な機能

theme.liquid — ログイン中の顧客は Liquid 変数で渡します

<script src="https://static.shoplive.cloud/shoplive.js"></script>
<script>
  cloud.shoplive.initPlugin({ accessKey: 'YOUR_ACCESS_KEY', platform: 'SHOPIFY' });
  {% if customer %}
  cloud.shoplive.setUserObject({ userId: "{{ customer.id }}", userName: "{{ customer.first_name }}" });
  {% endif %}
</script>
<div id="shoplive-overall"></div>
<script defer>
  document.addEventListener('DOMContentLoaded', function () {
    cloud.shoplive.setOverall('shoplive-overall');
  });
</script>

前へ ← 全体のサンプル次へ → 関数インデックス

リファレンス

関数インデックス

cloud.shoplive.* のうち Web 連携で使う関数の一覧です。名前が分かっているとき、どの節を見ればよいか探すためのものです。

グループ関数ガイド
初期化initPlugin(config)クイックスタート · フィールド
プレイヤーsetPlayer(containerId, config) · destroyPlayer(containerId)ミッション 1 · 方法 A · フィールド
ライブページ テンプレートsetOverall(containerId, config?) · destroyOverall(containerId?, removeActivePlayer?)ミッション 1 · 方法 C · フィールド
モーダルshowFeaturedPlayerModal(config) · dismissLayerModalPlayer()ミッション 1 · モーダルで表示する
ミニプレビューshowLiveMiniPreview() · dismissLiveMiniPreview() · setOnClickLiveMiniPreview(fn)ミッション 4 · ミニプレビュー
配信カード · カバーsetLivePreview(containerId, config) · destroyLivePreview(containerId?) · setOnAirCover(containerId) · setLandscapeOnAirCover(containerId) · setFeaturedCampaign(containerId, config)ミッション 4 · 配信カード
ユーザーsetUserObject(user) · setUserJWT(jwt) · logout()ミッション 2
イベント(initPlugin のオプション)messageCallbackミッション 3 · イベント辞典
プレイヤー制御getPlayer(key?) · getActivePlayers() · player.sendMessage(action, payload)ミッション 5 · コマンド辞典
PIPnavigateWithPIP(url, campaignKey?)付録 B · PIP
購入コンバージョンsendConversionEvent(event)ミッション 6

この表にない名前が cloud.shoplive に見える場合は、モバイルアプリ SDK 連携用か Shoplive 内部用です。Web 連携では使いません。

前へ ← 付録次へ → 設定オブジェクト フィールド辞典

リファレンス

設定オブジェクト フィールド辞典

各関数に渡す設定オブジェクトにどんな値を入れられるかをまとめた一覧です。accessKey と campaignKey を除けばほとんどが任意項目なので、必要なものだけ入れて残りは空にしておけば、デフォルト値またはアカウント設定で動作します。

containerId は配信キーではなく自社ページの DOM 要素の id です setPlayer · setOverall · setLivePreview · setOnAirCover はあらかじめページに用意した空の要素の中に画面を描きます。そのため第 1 引数は、描く場所である <div> の id 属性の値です。CSS セレクタではなく document.getElementById() で探すので # は付けません。その id を持つ要素が見つからない場合はコンソールに Invalid containerId を残し、何も描画しません。

初期化 — initPlugin(config)

フィールド必須説明
accessKey必須Shoplive が発行する顧客識別キー
messageCallback任意イベントごとの動作を定義する関数マップ(ミッション 3)
userObject / userJWT任意ログインユーザーの情報。あとから setUserObject / setUserJWT で変更可能(ミッション 2)
platform任意ショップのログイン状態を SDK に読み取らせます — 'CAFE24' · 'WISA' · 'GODOMALL' · 'SHOPIFY'(ミッション 2 · ステップ 3)
shareUrl任意共有ボタンが送るアドレス。指定しなければ現在のページのアドレス(ミッション 4 · 共有 URL)
useAutoPreview任意false なら初期化時にミニプレビューを自動表示しません(ミッション 4)
isSPA任意true ならページ遷移時も SDK を維持(付録 C)
disableHistoryHook任意true ならモーダルが開くときにアドレスを変更しません(付録 C)
listCampaignIdsForRemindButton任意リマインドボタンを出す配信の campaignId 一覧(付録 A)
webClientSettings.useRemind任意true にすると、配信予定のすべての配信にリマインドボタンを表示します。Admin の設定より優先されます(付録 A)
anonId任意自社が管理する未ログイン識別子。コンバージョン集計に併せて使われます。?anonId= のクエリで渡しても認識されます(ミッション 6)
gaId任意Google Analytics のクライアント ID。Shoplive の記録と GA のデータを同じユーザーとして揃えるとき
customerDeviceId任意自社で使う端末識別 ID。SDK が送るリクエストに併せて載ります
useAMD / AMDLoader任意RequireJS 環境(付録 E)

ここにない値をコードで見かけた場合。モバイルアプリの WebView で SDK を表示するときにアプリが渡す値(広告識別子など)か、特定の顧客と個別に取り決めた値、あるいは Shoplive の開発用の値です。Web ページに直接連携する場合には使いません。

プレイヤー — setPlayer(containerId, config)

フィールドデフォルト説明
campaignKey必須再生する配信のキー。ないとコンソールに Invalid AccessKey or CampaignKey
ui.viewerCounttrue視聴者数を表示
ui.likeCounttrueいいね数を表示
ui.backButtonfalse戻るボタンを表示
ui.shareButtonfalse共有ボタンを表示
isFullScreenfalse常に全画面で実行(viewport meta が必要)
hideControlsfalseコントロール UI を隠した状態で開始
playerAlias—getPlayer('別名') で取り出すための別名(ミッション 5)
closePlayerAfterCampaignEnd—配信終了からこの時間(ms)が経つと CLOSE_PLAYER イベントが届きます。SDK はこのイベントで何もしないので、プレイヤーを実際に片付けるには destroyPlayer() または dismissLayerModalPlayer() を自分で呼ぶ必要があります。
指定しない場合は、配信終了の 30 秒後にプレイヤーが自分で再読み込みします(終了画面に落ち着きます)
chatFilterPatterns—正規表現文字列の配列。一致したチャットは送信されず ON_FILTERED_CHAT が発生
passcode—リハーサル配信の入場コード
brand—ブランドのお気に入りの初期状態 — { identifier, favorite }(付録 A)

ライブページ テンプレート — setOverall(containerId, config)

フィールドデフォルト説明
featuredOnlyfalseメイン配信(プレイヤー)領域のみ表示
featured.fixedCampaignKey—メイン配信を特定の配信に固定
campaignListsOnlyfalse配信リスト領域のみ表示
campaignStatusすべて'READY' · 'ONAIR' · 'CLOSED'。文字列または配列(書いた順に並びます)
tags / tagSearchOperator—タグ フィルター · 'OR' | 'AND'
displayTags—リストの上にフィルタータブとして出すタグ
skus / goodsIds—特定の商品を含む配信のみ — 自社の商品コード / Shoplive 内部の商品 ID
campaignList.layout'GRID''GRID' · 'HORIZONTAL'
campaignList.type—'SECTION' — ステータス別のセクションに分けて表示
hasMoreButtontruefalse なら 'GRID' で無限スクロール
ascendingステータス次第並び順。未指定なら campaignStatus が 'READY' の文字列 1 つのときだけ昇順
sectionTitles既定の文言{ onair, ready, closed, all }
disableHistoryHookfalseリストからモーダルを開くときにアドレスを変更しない

その他の関数

関数設定オブジェクト
showFeaturedPlayerModal(config)campaignKey(必須)· disableHistoryHook
setLivePreview(containerId, config)campaignKey(必須)· onClick(campaign)
setFeaturedCampaign(containerId, config)campaignKey(必須)· playerContainerId · playerAlias
sendConversionEvent(event)accessKey · eventType(どちらも必須)· orderId · products[] · timestamp · custom · userObject / userJWT(ミッション 6)

ユーザー情報 — setUserObject(user)

userId 以外はすべて任意です。JWT 認証のクレーム名はミッション 2 · ステップ 5 をご覧ください(チャットの表示名が userName ではなく name です)。

フィールド説明
userId必須。ログインユーザーの一意な ID。空ならゲスト扱いです
userNameチャットに表示される名前。禁止ワードは * に置き換えて表示されます
gender · age統計用。'm' / 'f'、年齢は 5 歳単位にグループ化して集計されます
userScore-100 〜 100 の整数。入場制限や抽選対象の制限の基準に使えます
userType入場制限(Entry Type)が設定された配信で参照される値(例: 'VIP')
profileチャット一覧に表示するプロフィール画像の URL。推奨 64×64px
custom自由形式のデータ、最大 1KB
canBidtrue / false。オークションの入札資格(付録 A · オークション)。プラットフォーム自動連携はこの値を常に true にします

前へ ← 関数インデックス次へ → イベント辞典

リファレンス

イベント辞典

initPlugin({ messageCallback }) に登録できるイベントの一覧です。使い方と例はミッション 3 にあり、ここは名前から素早く探すためのものです。画面列の番号は画面の用語ガイドの図に対応します。

デフォルト動作があるイベント — 登録すると置き換わります

登録しなくても SDK が自動で処理します。登録した瞬間デフォルト動作は実行されなくなるので、ログだけ取るつもりでも元の動作を自分で作り直す必要があります。

イベントデフォルト動作画面
CLICK_PRODUCT新しいウィンドウで payload.url へ遷移⑥
LINK同じウィンドウで payload.url へ遷移(Web PIP がオンならプレイヤーを維持)⑨ ⑩ ⑪
LINK_NEW_WINDOW新しいウィンドウで payload.url へ遷移⑨ ⑩ ⑪
CLICK_SHARE_BTNOS の共有シート(navigator.share)→ なければクリップボードへコピー(共有 URL)⑫
CLICK_BACK_BUTTONhistory.back()⑫
ON_CLICK_CAMPAIGN_LIST_ITEMモーダル プレイヤーを開く—
ON_CLICK_CLOSE_PLAYER_MODALモーダル プレイヤーを閉じる—
ON_CLICK_SCHEME_BUTTON新しいウィンドウで payload.scheme を開く。payload.schemeType は GO_PRODUCT · ADD_PRODUCT · REMOVE_PRODUCT · WINNER_CHECKOUT⑥
REQUEST_FULL_SCREEN · EXIT_FULL_SCREENブラウザの全画面へ切り替え · 解除①

デフォルト動作がないイベント — 登録して初めて何かが起きます

イベントいつ画面
DOWNLOAD_COUPONクリック動作が「クーポンダウンロード」のポップアップをタップしたとき。登録しないと何も起きません⑨ ⑩ ⑪
CUSTOM_ACTIONクリック動作が「カスタム」のポップアップをタップしたとき⑨ ⑩ ⑪
LOGIN_REQUIREDゲストがログインの必要な機能にアクセスしたとき⑦

この 3 つは、Shoplive Admin のポップアップ設定で選んだクリック動作がそのままイベント名になって届きます。設定した動作と登録したイベント名がずれるとコールバックが呼ばれないので、ミッション 3 の Admin 設定の表も併せてご覧ください。

通知だけを受け取るイベント

ON_PLUGIN_INITIALIZED · ON_PLAYER_STARTED · NOW_ONAIR_CHECKED · ON_CAMPAIGN_STATUS_CHANGED · ON_CHANGED_VIEWER_STAT · ON_PLAYER_MODAL_SHOWN · ON_PLAYER_MODAL_HIDDEN · ON_LIVE_MINI_PREVIEW_SHOWN · ON_LIVE_MINI_PREVIEW_HIDDEN · ON_CLICK_CLOSE_LIVE_MINI_PREVIEW · ON_PRODUCT_LIST_SHOWN · ON_CHANGED_CAMPAIGN_PRODUCT_LIST · ON_FILTERED_CHAT · ON_RECEIVED_CHAT · ON_ERASED_CHAT · ON_CHAT_INPUT_FOCUS_IN · ON_CHAT_INPUT_FOCUS_OUT · ON_UID_ISSUED — 発生タイミングと payload はミッション 3 · 通知だけを受け取るイベントにあります。

コマンドへの応答としてのみ届くイベント — CURRENT_PLAYBACK_TIME は GET_CURRENT_PLAYBACK_TIME を送ったときにだけ届きます。自分から発生することはありません。

有効化が必要な機能のイベント

機能イベント
ブランドのお気に入りON_CHANGED_BRAND_FAVORITE · ON_CLICK_BRAND_FAVORITE_BUTTON
カートCLICK_PRODUCT_CART ·(Shopify)CLICK_SHOPIFY_CART · ADD_TO_SHOPIFY_CART · REMOVE_TO_SHOPIFY_CART · REDIRECT_TO_SHOPIFY_CART_PAGE
配信リマインドON_CLICK_REMIND_CAMPAIGN
オークションON_AUCTION_WINNER_CHECKOUT_CLICKED · ON_AUCTION_READY · ON_AUCTION_STARTED · ON_AUCTION_ENDED · ON_BID_STATUS_CHANGED · ON_BID_RESULT_RECEIVED · ON_AUCTION_BID_TIME_EXTENDED · ON_AUCTION_WINNER_DETERMINED · ON_AUCTION_SELF_WON · CAN_BID_REQUIRED
ON_CLICK_BUY_BUTTON はオークション専用ではなく商品リストの購入ボタンです

行動ログ — EVENT_LOG

プレイヤー内のボタンのタップや表示を 1 つのイベントにまとめて受け取ります。51 個すべての名前はミッション 3 · ユーザー行動のログにあります。

この文書にないイベント名が届いた場合は、モバイル SDK の WebView や Shoplive の運用ツールが使う内部イベント、または特定の顧客と個別に取り決めた機能のイベントです。通常の Web 連携では処理する必要はありません。

前へ ← 設定オブジェクト フィールド辞典次へ → プレイヤー コマンド辞典

リファレンス

プレイヤー コマンド辞典

getPlayer().sendMessage(コマンド, payload) で送れるコマンドです。使い方はミッション 5 にあります。画面列の番号は画面の用語ガイドの図に対応します。

コマンドpayload動作画面
removeCouponなしクーポン ポップアップを削除⑨
removeBannerなしバナー ポップアップを削除⑪
removeNoticeなしお知らせ ポップアップを削除⑩
mute · unmuteなしミュートのオン · オフ⑧
playVideo · pauseVideoなし再生 · 一時停止①
videoRefreshなし映像を読み込み直す①
hideControls · showControlsなしコントロール UI の非表示 · 表示⑦
dismissGoodsListなし商品リストのポップアップを閉じる⑥
showDialog{ title, message } + cancelText · confirmText · confirmTextColor · confirmBackgroundColorダイアログを表示(ミッション 5)—
showToast{ message } + duration · positionトーストを表示(ミッション 5)—
GET_CURRENT_PLAYBACK_TIMEなし現在の再生位置を問い合わせる → CURRENT_PLAYBACK_TIME イベントで応答(ミッション 5)—
SEND_COMMAND_MESSAGE{ command, payload }下のサブコマンドを運ぶ封筒—

SEND_COMMAND_MESSAGE のサブコマンド

有効化が必要な機能で状態を返すときに使います。

commandpayload使う場面
SET_BRAND_FAVORITE{ identifier, favorite }ブランドのお気に入り — 現在のユーザーのお気に入り状態を知らせます
SET_PRODUCT_CART_ON{ products: [{ sku, isCartOn }] }カート — 入っている状態を知らせてボタンの見た目を変えます
const player = cloud.shoplive.getPlayer();

player.sendMessage('SEND_COMMAND_MESSAGE', {
  command: 'SET_PRODUCT_CART_ON',
  payload: { products: [{ sku: 'PRODUCT_SKU', isCartOn: true }] }
});

この表にないコマンド名をコードで見かけた場合は、モバイル SDK の WebView や Shoplive の運用ツールが使う内部コマンドです。Web 連携では使いません。

前へ ← イベント辞典次へ → トラブルシューティングと FAQ

リファレンス

トラブルシューティングと FAQ

プレイヤーが表示されません

まずブラウザのコンソールを確認してください。次の警告が出ていれば原因がすぐ分かります。

コンソールのメッセージ原因
Invalid containerIdコンテナ div の id が setPlayer に渡した値と一致していない
Invalid AccessKey or CampaignKeysetPlayer に渡した campaignKey が空、または欠けている
Invalid AccessKeysetOverall · setLivePreview などで accessKey が見つからない。initPlugin から受けた値も、関数に直接渡した値もない場合です
Empty AccessKeyinitPlugin の accessKey が空
Invalid WebClientSettingsaccessKey が誤っているか、初期設定の取得に失敗 — 下の注意を参照
Invalid WebClientSettings が見えたら、そのあとの呼び出しはすべて消えます 初期化は設定をサーバーから受け取ったあとに完了します。その前に呼んだ setPlayer · setOverall · sendConversionEvent はいったんキューに溜まり、初期化が終わる瞬間にまとめて実行されますが、設定の取得に失敗すると初期化が終わらないため、キューは永遠に実行されません。自動リトライもありません。
そのため症状は「エラーも出ず、何も起きない」ように見えます。ほかに警告がないのにプレイヤーもコンバージョン イベントも動かない場合は、まずこの行がコンソールにあるか確認してください。accessKey のタイプミスと、ネットワーク・ファイアウォールによる遮断が主な原因です。

コンソールに警告がない場合は、その配信が Admin で公開設定になっているか確認してください — 新規の配信は既定で非公開のため、プラグイン・API の公開設定をオンにしないと campaignKey が正しくてもプレイヤーは表示されません。

なお initPlugin() より setPlayer() を先に呼んでも(順序が入れ替わっても)内部で待機して自動的に処理されるので、スクリプトの順序自体が原因になることはまれです。

商品をタップしても何も起きません

CLICK_PRODUCT を上書きしなければ、既定では新しいウィンドウで商品 URL が開きます。同じウィンドウで遷移させたい場合はコールバックを上書きしてください(ミッション 3)。

プレイヤーの内部(チャット・商品リストなど)の位置を変えられますか?

単なる位置調整にとどまらず、貴社の BI・CI とスタイルガイドを反映した専用デザインのカスタム開発も可能です。ご希望の際は Shoplive 担当者までお問い合わせください。

ただし自社側のコードで直接調整することはできません。下のようにプレイヤーは iframe の中で別ページとして動作するため、ページに適用した CSS は内部には届かないからです。

自社の Web ページ
  └─ Player SDK(スクリプト)
        └─ <iframe>
              └─ Shoplive Player(別ページとして動作)

プレイヤーを収めるコンテナ(div)の位置・サイズはページの CSS で調整できますが、iframe の内部(チャット・商品リストなど)はその境界の中で Shoplive Player 自身のレイアウトに従います。

ミニプレビュー バナーが出したくないページにも表示されます

配信中は initPlugin() を呼んだすべてのページに自動で出るのが既定の動作です。出すページを選びたい場合は、初期化で自動表示をオフにして、出したいページでだけ自分で呼び出してください。

cloud.shoplive.initPlugin({
  accessKey: 'YOUR_ACCESS_KEY',
  useAutoPreview: false      // 自動表示をオフ
});

// 出したいページでだけ
cloud.shoplive.showLiveMiniPreview();

詳しい条件と表示位置はミッション 4 · ミニプレビューにあります。

同じ場所に別の配信で setPlayer をもう一度呼んでも大丈夫ですか?

はい。同じコンテナ id で setPlayer をもう一度呼ぶと、既存のプレイヤーを片付けて新しいプレイヤーに差し替えます。React などでページ遷移なしにコンポーネントが再レンダリングされる場面でも安全に呼び直せます。

ただしコンポーネントが画面から完全に消える(コンテナごと削除される)場合は事情が異なります。SDK がこのタイミングを自動で検知できず、内部的にプレイヤーが有効なまま残り、そのためミニプレビューが正しく表示されないことがあります。コンテナを削除する前に cloud.shoplive.destroyPlayer("コンテナ id") を先に呼んでください。

配信が終わったらアーカイブ(リプレイ)はどう開きますか? campaignKey を変える必要はありますか?

いいえ、campaignKey はそのまま使います。同じキャンペーンが ONAIR → CLOSED にステータスだけ変わるもので、Admin でその配信の「リプレイ公開」設定がオンになっていれば、終了後も同じ campaignKey でアーカイブが正常に再生されます。

映像が自動再生されず、静止画のままです

ブラウザが音声付き映像の自動再生をブロックするためです。SDK はミュート状態で再生を試みますが、端末や設定によってはそれも阻まれ、視聴者が一度タップする必要があります。コードで回避できる領域ではありません。

iOS で特定の端末だけ静止画になる場合は、その端末の設定 → アクセシビリティ → 動作 →「ビデオプレビューの自動再生」がオフになっていないか確認してください。低電力モードやデータ節約モードも同じ結果になります。

自社アプリの WebView で開いたページの場合は原因が異なります — WebView の設定によるものなので、アプリのコードで直せます。付録 D をご覧ください。

CSP(Content-Security-Policy)を使っています。どのドメインを許可すればよいですか?

プレイヤーは iframe の中で別ページとして動作します。そのため自社ページの CSP が関わるのは SDK スクリプトと iframe を表示するところまでで、映像やチャットのように iframe の内部で行われる通信は自社 CSP の適用対象ではありません。

ディレクティブ許可するオリジン用途
script-srchttps://static.shoplive.cloud
https://cdnjs.cloudflare.com
SDK 本体 · hls.js — SDK が映像再生用の hls.js を自社ページに直接読み込むため、Shoplive のドメインではないこのオリジンも必要です。漏らすと SDK は表示されるのに映像だけ再生されません
style-srchttps://static.shoplive.cloud · 'unsafe-inline'SDK のスタイルシート · アカウントのカスタム スタイル(インライン)
frame-srchttps://static.shoplive.cloudプレイヤーの iframe — 漏らすとプレイヤーの場所が空のまま残ります
connect-srchttps://config.shoplive.cloud · https://capi.shoplive.cloud · https://api.shoplive.cloud · https://*.shoplive.cloudアカウント設定 · 配信リスト API · コンバージョン イベント · イベントログ
img-srchttps://image.shoplive.cloud · https://*.shoplive.cloudポスター · サムネイル · プロフィール画像

正確な API ホストはアカウント設定により異なる場合があるので、リリース前にネットワークタブでご確認ください。

外部スクリプトを CDN から取得することがポリシー上禁止されている場合は、ページで先に hls.js を読み込んで window.Hls を用意しておけば、SDK はそのオブジェクトをそのまま使います(付録 E)。

プレイヤーの UI 言語を変えられますか?

プレイヤー内の文言は視聴者のブラウザの言語設定(navigator.language)に従います。19 言語に対応しており、コードから強制的に指定する公開オプションはありません。

特定の言語に固定する必要がある場合は Shoplive 担当者までお問い合わせください — アカウント・テーマの設定で対応できる場合があります。

initPlugin を 2 回呼んだら、2 回目の設定が反映されません

初期化はページごとに 1 回だけ処理されます。2 回目の initPlugin() の呼び出しは警告もなく静かに無視され、そこに渡した accessKey · messageCallback · useAutoPreview も一緒に捨てられます。

React の StrictMode のようにコンポーネントが 2 回マウントされる環境や、SPA でルーティングのたびに初期化を呼ぶ構造でよく踏みます。初期化はアプリのエントリーポイントで 1 回だけ呼び、ページごとに変わるものは setPlayer 側で処理してください(付録 C)。

コールバックをあとから変えたい場合は、初期化を呼び直すのではなく setPlayer の messageCallback を使ってください — こちらは配信ごとに個別に渡せて、初期化時に渡したものより優先されます。

PIP が動作しません

PIP には 2 種類あり、原因も異なります。付録 B に条件をまとめているので、まずどちらなのかを確認してください。

  • Web PIP — 遷移先のページが3 つの条件(同一オリジン · X-Frame-Options · frame-ancestors)のいずれかに反すると、画面が空になるか PIP が消えます。決済 · ログインのページでは意図的に抜けるようになっています。
  • ブラウザ PIP — 視聴者が直接押す操作がないと始まらず、Android の WebView では限定的です。

どちらもアカウントで利用できるよう設定されている必要があるので、条件をすべて満たしても動かない場合は Shoplive 担当者までお問い合わせください。

購入コンバージョンが計測されません

sendConversionEvent() も初期化が終わる前に呼ぶとキューに溜まり、初期化完了の時点で実行されます。そのため初期化が失敗するとコンバージョン イベントも一緒に消えます — コンソールに Invalid WebClientSettings がないかまず確認してください(上のプレイヤーが表示されませんを参照)。

決済完了ページのようにプレイヤーがないページでも、initPlugin() を先に呼ばないとコンバージョンは送信されません。送る場所とフィールドはミッション 6、視聴記録と結び付く基準はステップ 3 にあります。

TypeScript プロジェクトですが、型定義はありますか?

公式に提供している型定義(.d.ts)はありません。window.cloud.shoplive を any として宣言するか、この文書に記載のフィールドをもとに必要な分だけ自分で型を宣言してお使いください。

ほかにご不明な点があれば サイドバーの検索(または Ctrl+K / Cmd+K)でこのガイド内を探せます。検索でも解決しない場合は Shoplive 担当者までお問い合わせください。