Feature/ad and adbreak custom data bridging - #866
Conversation
Co-Authored-By: william.vanhaevre <william.vanhaevre@dolby.com>
Co-Authored-By: william.vanhaevre <william.vanhaevre@dolby.com>
| /** Additional integration-specific data associated with this ad.*/ | ||
| var customData: [String: Any]? = nil |
There was a problem hiding this comment.
🟡 Custom ad data sent from JavaScript is dropped when rebuilding ads on iOS
The new custom-data field on ads and ad breaks is never filled in when an ad is rebuilt from JavaScript data (customData at ios/ads/THEOplayerRCTAdsNative.swift:34), so for custom ad integrations the extra data always comes back empty.
Impact: Apps using a custom ad integration lose any custom data they attach to ads or ad breaks once the ad passes back through the native layer.
Initializers never assign the newly declared customData property
NativeAd.init (ios/ads/THEOplayerRCTAdsNative.swift:36-50) and NativeAdBreak.init (ios/ads/THEOplayerRCTAdsNative.swift:142-150) take no customData parameter and never assign the property, so it stays nil. Correspondingly THEOplayerRCTAdAdapter.toAd (ios/ads/THEOplayerRCTAdAdapter.swift:136-158) and toAdBreak (ios/ads/THEOplayerRCTAdAdapter.swift:194-215) never read adData[PROP_CUSTOM_DATA], even though fromAd/fromAdBreak now write it. These converted ads are used for custom-integration ad events (ios/ads/THEOplayerRCTAdEventAdapter.swift:14-20), so the JS→native direction silently discards custom data. Android has the same gap in AdAdapter.parseAd where getCustomData() returns null (android/src/main/java/com/theoplayer/ads/AdAdapter.kt:219-222).
Prompt for agents
The PR adds a customData property to NativeAd (ios/ads/THEOplayerRCTAdsNative.swift) and NativeAdBreak, and writes customData into the bridge payload in THEOplayerRCTAdAdapter.fromAd/fromAdBreak. However, the initializers of NativeAd, NativeLinearAd, NativeLinearGoogleImaAd and NativeAdBreak do not accept or assign customData, and THEOplayerRCTAdAdapter.toAd/toAdBreak never read the customData key from the incoming dictionary. As a result, for custom ad integrations (which build native ads from JS-provided data, see ios/ads/THEOplayerRCTAdEventAdapter.swift), the custom data is always nil. Consider threading customData through the initializer chain and reading adData[PROP_CUSTOM_DATA] in toAd/toAdBreak, or explicitly document that the JS->native direction is unsupported (Android's AdAdapter.parseAd currently returns null for getCustomData with a 'Not supported yet' comment).
Was this helpful? React with 👍 or 👎 to provide feedback.
| val customData = ad.customData | ||
| if (customData is JSONObject) { | ||
| adPayload.putMap(PROP_CUSTOM_DATA, BridgeUtils.fromJSONObjectToBridge(customData)) | ||
| } else if (customData is Map<*, *>) { | ||
| adPayload.putMap(PROP_CUSTOM_DATA, BridgeUtils.fromJSONObjectToBridge(JSONObject(customData))) | ||
| } |
There was a problem hiding this comment.
🔍 Nested maps/lists inside a Map-typed customData may be silently dropped
When the native ad's custom data comes back as a plain Map, it is wrapped with JSONObject(customData). On Android, JSONObject(Map) casts keys to String (throwing ClassCastException/NullPointerException for non-String or null keys) and relies on JSONObject.wrap() for values; any value type that wrap() leaves as a raw object (or Float, custom objects, etc.) will not match any branch in BridgeUtils.fromJSONObjectToBridge (android/src/main/java/com/theoplayer/util/BridgeUtils.kt:28-37) and is silently omitted from the bridged map. Worth confirming what shapes the SDK actually returns for customData for the supported integrations.
Was this helpful? React with 👍 or 👎 to provide feedback.
Uh oh!
There was an error while loading. Please reload this page.