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-DATERANGEtag.X-ASSET-LIST:Called up to three times per interstitial asset (only when attributes are present at each level):
InterstitialMappingData.Interstitial for attributes from the
EXT-X-DATERANGEtagInterstitialMappingData.AssetList for attributes from the root of the Asset List JSON
InterstitialMappingData.Asset for attributes from an individual asset entry within the Asset List JSON
If there are multiple assets within an Asset List, the data for InterstitialMappingData.Interstitial and InterstitialMappingData.AssetList will be the same for each.
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:
The default value is
null.To enable automatic support for the SVTA
X-AD-CREATIVE-SIGNALINGspecification, set this property to CustomAttributesMappingPresets.adCreativeSignaling.You can also provide a custom implementation of CustomAttributesMappingHandler to extend or replace the default behavior.
Limitations:
Asynchronous resolving of tracking URLs (e.g. using the
$remoteproperty 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)))