Skip to main content

Product hydration

Product hydration allows your app to supply enriched product data (pricing, images, variants, stock) to the Bambuser live player at runtime. When a live show starts, the player fires a provide-product-data event listing all products it needs data for. Your app looks up each product by SKU and pushes the data back into the player using viewActions.invoke("updateProductWithData", ...).

Prerequisites

currency and locale must be set in your player configuration — product hydration will not work without them.

application.globalBambuserSDK.GetLiveView(
modifier = Modifier.fillMaxSize(),
videoConfiguration = BambuserVideoConfiguration(
events = listOf("*"),
configuration = mapOf(
"currency" to "USD", // Required for product hydration
"locale" to "en-US" // Required for product hydration
),
videoType = BambuserVideoAsset.Live(showId)
),
videoPlayerDelegate = videoPlayerDelegate
)

Handle the provide-product-data Event

The player fires provide-product-data at show start, and again whenever a new product needs to be displayed. Handle it in your BambuserVideoPlayerDelegate:

videoPlayerDelegate = object : BambuserVideoPlayerDelegate {
override fun onNewEventReceived(
playerId: String,
event: BambuserEventPayload,
viewActions: ViewActions
) {
when (event.event) {
"provide-product-data" -> {
(event.data["products"] as? List<Map<String, Any>>)?.let { products ->
products.forEach { product ->
val productId = product["id"]?.toString() ?: return@forEach
val sku = product["ref"]?.toString() ?: return@forEach

lifecycleScope.launch {
viewActions.invoke(
function = "updateProductWithData",
arguments = buildHydrationArguments(productId, sku)
)
}
}
}
}
}
}
}

The event payload products array has:

FieldTypeDescription
idStringBambuser-generated product ID — pass this back to the player
refStringYour product SKU — use this to look up your own data
urlStringProduct URL as set in the Bambuser dashboard

Send Product Data Back to the Player

The arguments string must start with the Bambuser product id in single quotes, followed by a comma and the product object as a JavaScript object literal:

fun buildHydrationArguments(productId: String, sku: String): String {
// Look up your product data by SKU
val product = YourProductService.findBySku(sku) ?: return "'$productId', {}"

return """
'$productId', {
sku: '${product.sku}',
name: '${product.name}',
brandName: '${product.brand}',
introduction: '${product.shortDescription}',
description: '${product.description}',
variations: [
{
sku: '${product.variationSku}',
name: '${product.variationName}',
colorName: '${product.colorName}',
imageUrls: ['${product.imageUrl}'],
sizes: [
{
sku: '${product.sizeSku}',
currency: 'USD',
current: ${product.price},
original: ${product.originalPrice},
name: '${product.sizeName}',
inStock: ${product.stock}
}
]
}
]
}
""".trimIndent()
}

Full Product Data Structure

Product

FieldTypeRequiredDescription
skuStringYesYour product SKU / identifier
nameStringYesProduct display name
brandNameStringYesBrand name
introductionStringNoShort introductory text
descriptionStringNoFull description — supports HTML
variationsArrayYesList of product variations (colors/styles)

Variation

FieldTypeRequiredDescription
skuStringYesVariation SKU
nameStringYesVariation display name
colorNameStringYesColor name shown in the variation selector
colorHexCodeStringNoHex color code e.g. "#000000"
imageUrls[String]YesOrdered list of image URLs for this variation
sizesArrayYesList of sizes/SKUs for this variation

Size

FieldTypeRequiredDescription
skuStringYesSize-level SKU
nameStringYesSize name e.g. "Small", "XL"
currentDoubleYesCurrent (sale) price
originalDoubleNoOriginal price — shown as strike-through
currencyStringYesThree-letter currency code e.g. "USD"
inStockIntYesAvailable stock quantity (0 = out of stock)
perUnitDoubleNoPrice per unit (for bundle/multi-pack pricing)
unitAmountIntNoQuantity per unit
unitDisplayNameStringNoUnit label e.g. "kg", "L", "st"

Complete Example

fun buildHydrationArguments(productId: String) = """
'$productId', {
sku: '7777',
name: 'Bambuser Hoodie',
brandName: 'Bambuser',
introduction: 'A nice hoodie that keeps you warm',
description: "<div><h2>World's best hoodie</h2><p>Comes in all sizes!</p></div>",
variations: [
{
sku: '1111-black',
name: 'Black Bambuser Hoodie',
colorName: 'black',
imageUrls: [
'https://demo.bambuser.shop/wp-content/uploads/2021/07/black-hoodie-front.png',
'https://demo.bambuser.shop/wp-content/uploads/2021/07/black-hoodie-back.jpeg',
],
sizes: [
{
sku: '1111-black-small',
currency: 'USD',
current: 120,
original: 120,
name: 'Small',
inStock: 9,
},
{
sku: '1111-black-xlarge',
currency: 'USD',
current: 100,
original: 120,
name: 'X-Large',
inStock: 3,
},
],
},
{
sku: '1111-white',
name: 'White Bambuser Hoodie',
colorName: 'white',
imageUrls: [
'https://demo.bambuser.shop/wp-content/uploads/2021/07/white-hoodie-front.png',
'https://demo.bambuser.shop/wp-content/uploads/2021/07/white-hoodie-back.jpeg',
],
sizes: [
{
sku: '1111-white-small',
currency: 'USD',
current: 100,
original: 120,
name: 'Small',
inStock: 8,
},
{
sku: '1111-white-xlarge',
currency: 'USD',
current: 100,
original: 120,
name: 'X-Large',
inStock: 0,
},
],
},
],
}
"""

Notes

  • The player may fire provide-product-data multiple times during a show as products are highlighted. Your handler must be idempotent.
  • Fields not provided in your hydration response fall back to data previously scraped or manually set in the Bambuser dashboard.
  • Builder functions are available for iOS only (see the iOS SDK example app). Android requires raw string construction.
  • viewActions.invoke is a suspend function — always call it inside a coroutine scope (lifecycleScope.launch {}).