상품 클릭 연동
플레이어에서 상품을 클릭했을 때 sauceflexMoveProduct 이벤트가 전송됩니다. 이벤트를 수신하여 현재 창 이동, 새 창 열기, 상품 코드 기반 커스텀 라우팅 등 자사몰에 맞는 동작을 자유롭게 정의할 수 있습니다.
플레이어 상품 목록
▲ 플레이어의 상품 목록 — 상품을 클릭하면 sauceflexMoveProduct 이벤트가 전송됩니다
이벤트 데이터
sauceflexMoveProduct 이벤트 수신 시 jsonData.params에 아래 필드가 담겨 전달됩니다. 상황에 맞는 필드를 선택하여 활용하세요.
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
| linkUrl | String | 필수 | 어드민에 등록된 상품 페이지 링크 URL |
| broadcastIdx | String | 필수 | 이벤트가 발생한 라이브 ID |
| price | String | Number | 필수 | 상품 가격 |
| externalProductId | String | null | 선택 | 자사몰에서 등록한 상품 코드. 커스텀 라우팅에 활용합니다. |
| isSoldout | Boolean | 필수 | 품절 여부. true이면 품절 상태입니다. |
구현 방법
자사몰의 상품 이동 방식에 맞는 탭을 선택하세요. 세 가지 패턴 중 하나를 선택하거나 조합하여 사용할 수 있습니다.
🧭 어떤 방식을 선택해야 하나?
단순한 쇼핑몰이라면 현재 창 이동이 가장 간단합니다. 라이브를 보면서 상품을 구경하게 하려면 새 창 열기를 선택하세요. 자사몰의 라우팅 URL 체계가 있고, 어드민에서 외부 상품 코드를 등록했다면 상품코드 기반 라우팅이 가장 유연합니다.
단순한 쇼핑몰이라면 현재 창 이동이 가장 간단합니다. 라이브를 보면서 상품을 구경하게 하려면 새 창 열기를 선택하세요. 자사몰의 라우팅 URL 체계가 있고, 어드민에서 외부 상품 코드를 등록했다면 상품코드 기반 라우팅이 가장 유연합니다.
현재 창에서 상품 페이지로 이동합니다. 가장 기본적인 패턴으로, 어드민에 등록된
linkUrl을 그대로 사용합니다.
JavaScript
window.addEventListener('message', (e) => { if (typeof e.data !== 'string') return const jsonData = JSON.parse(e.data) switch (jsonData.key) { case 'sauceflexMoveProduct': { const { linkUrl } = jsonData.params if (!linkUrl) return // 현재 창에서 상품 페이지로 이동 window.location.href = linkUrl break } } })
새 창(탭)에서 상품 페이지를 엽니다. 라이브 시청을 끊지 않고 상품을 확인할 때 유용합니다.
JavaScript
window.addEventListener('message', (e) => { if (typeof e.data !== 'string') return const jsonData = JSON.parse(e.data) switch (jsonData.key) { case 'sauceflexMoveProduct': { const { linkUrl } = jsonData.params if (!linkUrl) return // 새 창(탭)에서 상품 페이지 열기 window.open(linkUrl, '_blank') break } } })
자사몰의 상품 코드(
externalProductId)를 기반으로 원하는 URL을 직접 구성합니다. 자사몰 라우팅 규칙에 따라 URL을 동적으로 생성할 때 사용합니다.
JavaScript
window.addEventListener('message', (e) => { if (typeof e.data !== 'string') return const jsonData = JSON.parse(e.data) switch (jsonData.key) { case 'sauceflexMoveProduct': { const { externalProductId } = jsonData.params // externalProductId가 없으면 처리하지 않음 if (!externalProductId) return // 상품 코드를 이용해 자사몰 URL 구성 window.location.href = `/products/${externalProductId}` break } } })
💡 품절 상품 처리:
isSoldout이 true인 경우 별도 안내 메시지를 표시하거나 클릭을 차단하려면 if (jsonData.params.isSoldout) return 조건을 추가하세요.
실전 예시 — 조건 분기 처리
externalProductId가 있으면 자사몰 라우팅을, 없으면 linkUrl로 폴백하는 방어적 패턴입니다. 실제 서비스에서 가장 많이 사용하는 구현 방식입니다.
JavaScript — 조건 분기 + 폴백
window.addEventListener('message', (e) => { if (typeof e.data !== 'string') return const jsonData = JSON.parse(e.data) switch (jsonData.key) { case 'sauceflexMoveProduct': { const { linkUrl, externalProductId, isSoldout } = jsonData.params // 품절 상품 클릭 시 얼리 리턴 if (isSoldout) { alert('현재 품절된 상품입니다.') return } // externalProductId가 있으면 자사몰 라우팅 우선 if (externalProductId) { window.location.href = `/products/${externalProductId}` } else if (linkUrl) { // 없으면 어드민 등록 linkUrl로 폴백 window.location.href = linkUrl } break } } })
Kotlin — SauceflexBridge.kt
class SauceflexBridge( private val context: Context, private val activity: Activity?, private val webView: WebView ) { @JavascriptInterface fun sauceflexMoveProduct(payload: String?) { val params = JSONObject(payload ?: "{}") val isSoldout = params.optBoolean("isSoldout", false) val externalId = params.optString("externalProductId", "") val linkUrl = params.optString("linkUrl", "") // 품절 상품 — 안내 후 리턴 if (isSoldout) { activity?.runOnUiThread { Toast.makeText(context, "현재 품절된 상품입니다.", Toast.LENGTH_SHORT).show() } return } val targetUrl = if (externalId.isNotEmpty()) { "https://myshop.com/products/$externalId" // 자사몰 라우팅 } else { linkUrl // 폴백 } if (targetUrl.isEmpty()) return activity?.runOnUiThread { val intent = Intent(Intent.ACTION_VIEW, Uri.parse(targetUrl)) context.startActivity(intent) } } }
Kotlin — WebView 등록
webView.addJavascriptInterface(SauceflexBridge(context, activity, webView), "sauceflex")
Swift — WKWebView 등록
contentController.add(self, name: "sauceflexMoveProduct")
Swift — ViewController.swift
func userContentController( _ userContentController: WKUserContentController, didReceive message: WKScriptMessage ) { switch message.name { case "sauceflexMoveProduct": guard let body = message.body as? String, let data = body.data(using: .utf8), let params = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else { return } let isSoldout = params["isSoldout"] as? Bool ?? false let externalId = params["externalProductId"] as? String ?? "" let linkUrl = params["linkUrl"] as? String ?? "" // 품절 상품 — 얼리 리턴 if isSoldout { DispatchQueue.main.async { let alert = UIAlertController(title: nil, message: "현재 품절된 상품입니다.", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "확인", style: .default)) self.present(alert, animated: true) } return } let targetUrl = !externalId.isEmpty ? "https://myshop.com/products/\(externalId)" // 자사몰 라우팅 : linkUrl // 폴백 guard !targetUrl.isEmpty(), let url = URL(string: targetUrl) else { return } DispatchQueue.main.async { UIApplication.shared.open(url) } default: break } }
⚡ externalProductId 등록: 소스라이브 어드민에서 상품 추가 시 자사몰의 상품 코드를 외부 상품 코드 필드에 입력하면
externalProductId가 전달됩니다.
Updated about 24 hours ago