customAttributesMapping

Callback to map custom attributes to interstitial-relevant information such as tracking information. See InterstitialCustomAttributesMappingRegistry for supported mappings.

This callback is invoked once for each level that contains custom attributes. Depending on the interstitial type, it may be called multiple times per interstitial:

  • X-ASSET-URI:

  • Called once with InterstitialMappingData.Interstitial containing custom attributes from the EXT-X-DATERANGE tag.

  • X-ASSET-LIST:

  • Called up to three times per interstitial asset (only when attributes are present at each level):

  1. InterstitialMappingData.Interstitial for attributes from the EXT-X-DATERANGE tag

  2. InterstitialMappingData.AssetList for attributes from the root of the Asset List JSON

  3. InterstitialMappingData.Asset for attributes from an individual asset entry within the Asset List JSON

The callback is only invoked for levels that contain custom attributes. If a level has no custom attributes, the callback is not invoked for that level.

Notes:

Limitations:

  • Asynchronous resolving of tracking URLs (e.g. using the $remote property from the SVTA spec) is currently not supported.

Example:

val customAttributesMapping = CustomAttributesMappingHandler { mappingData, mappingRegistry ->
val jsonString = mappingData.customAttributes[AD_CREATIVE_SIGNALING_KEY]
?: return@CustomAttributesMappingHandler
val rootObj = runCatching { json.parseToJsonElement(jsonString).jsonObject }.getOrNull()
?: return@CustomAttributesMappingHandler

val firstPayload = rootObj["payload"]
?.jsonArray
?.firstOrNull()
?.jsonObject
?: return

firstPayload["clickThrough"]
?.jsonPrimitive
?.contentOrNull
?.takeIf { it.isNotBlank() }
?.let { url -> mappingRegistry.clickThroughUrl = url }

val trackingArray: JsonArray = firstPayload["tracking"]?.jsonArray ?: JsonArray(emptyList())
for (entry: JsonElement in trackingArray) {
val obj: JsonObject = entry as? JsonObject ?: continue
val type = obj["type"]?.jsonPrimitive?.contentOrNull?.lowercase() ?: continue

val urls: List<String> = obj["urls"]
?.jsonArray
?.mapNotNull { it.jsonPrimitive.contentOrNull?.takeIf(String::isNotBlank) }
.orEmpty()

if (urls.isEmpty()) continue

val trigger = when (type) {
"impression" -> InterstitialTrackingEventTrigger.Impression
"clicked" -> InterstitialTrackingEventTrigger.Clicked
else -> null
} ?: continue

mappingRegistry.tracking.register(
trackingEvent = InterstitialTrackingEvent(
urls = urls,
),
eventTrigger = trigger
)
}
}
PlayerConfig(hlsConfig = HlsConfig(interstitialConfig = InterstitialsConfig(customAttributesMapping)))