Native Custom Layout
Fuse App SDK supports native ads and provides a built-in default layout for them. You can override the default native ad layout by registering a custom ad handler.
A custom ad handler lets you create your own UI for native ads, with full control over the layout, colors and fonts.
Keep in mind that native ads have optional elements, so your custom layout should adapt to handle optional elements (more information).
Google supports two different native ad formats - native and custom native. Make sure you register your custom ad handler for the correct native ad format.
When registering a custom ad handler, the Fuse App SDK will provide you with a zone code and an ad object.
Android — native ads
Build your layout, fill it from the ad, and return a FuseNativeAdBinding describing which view holds which asset. The SDK attaches your template and registers it, so clicks and impressions are attributed. Return null to decline the ad, which falls back to the SDK’s built-in layout.
FuseSDK.addNativeAdHandler { context, code, ad ->
if (code != "<zone_code>") return@addNativeAdHandler null
val template = LayoutInflater.from(context)
.inflate(R.layout.my_native_template, null) as ViewGroup
val headlineView = template.findViewById<TextView>(R.id.headline)
val bodyView = template.findViewById<TextView>(R.id.body)
val ctaView = template.findViewById<TextView>(R.id.cta)
val iconView = template.findViewById<ImageView>(R.id.icon)
headlineView.text = ad.headline
bodyView.text = ad.body
ctaView.text = ad.callToAction
ad.icon?.let { iconView.setImageDrawable(it) }
FuseNativeAdBinding(template).apply {
headline = headlineView
body = bodyView
callToAction = ctaView
icon = iconView
mediaSlot = template.findViewById(R.id.media)
adChoicesSlot = template.findViewById(R.id.ad_choices)
}
}
For a layout you can copy and adapt, see Native Template Example.
FuseNativeAd carries headline, body, callToAction, advertiser, store, starRating, icon, hasVideo, mediaImage and mediaAspectRatio.
FuseNativeAdBinding describes your template. All fields are optional — set only what your template shows.
| Field | What it is |
|---|---|
headline, body, callToAction, icon, advertiser, starRating, store |
Views you populated. Pass them so clicks are attributed to them. |
mediaSlot, adChoicesSlot |
Empty containers the SDK fills. Anything already inside is removed. |
mediaScaleType |
How the media asset is scaled. |
Android — custom native ads
Custom native assets are fetched by the names you defined on the format in Google Ad Manager. Return the view you built.
FuseSDK.addCustomNativeAdHandler { context, code, ad ->
if (code != "<zone_code>") return@addCustomNativeAdHandler null
val template = LayoutInflater.from(context)
.inflate(R.layout.my_custom_template, null) as ViewGroup
template.findViewById<TextView>(R.id.headline).apply {
text = ad.text("Headline")
setOnClickListener { ad.click("Headline") }
}
val media = template.findViewById<FrameLayout>(R.id.media)
if (ad.hasVideo) {
ad.createVideoView(context)?.let { media.addView(it) }
} else {
media.addView(
ImageView(context).apply {
setImageDrawable(ad.image("MainImage"))
setOnClickListener { ad.click("MainImage") }
},
)
}
template
}
Call click(assetName) only from a genuine user interaction. The SDK records the impression itself.
Android — legacy API
addGamNativeAdHandler and addGamCustomNativeAdHandler pass the ad as the linked Google Mobile Ads SDK models it, and your handler registers it with that SDK itself. These are deprecated — we recommend migrating to the newer native ads API above.
They remain available for existing integrations. Google’s Android guides describe this API: Native Ad Format, Custom Native Ad Format, Native Video Ads.
import com.publift.fuseappsdk.gma.legacy.addGamNativeAdHandler
FuseSDK.addGamNativeAdHandler { context, code, ad ->
when (code) {
"<zone_code>" -> MyNativeAdView(context, ad) // ad is the Google NativeAd
else -> null
}
}
To migrate, swap the Google types in your handler for the Fuse ones, and return a FuseNativeAdBinding instead of registering the ad yourself:
| Google Mobile Ads | Fuse |
|---|---|
nativeAd.headline, .body, .callToAction |
ad.headline, ad.body, ad.callToAction |
nativeAd.icon?.drawable |
ad.icon |
nativeAd.mediaContent?.aspectRatio |
ad.mediaAspectRatio |
nativeAd.mediaContent?.hasVideoContent() |
ad.hasVideo |
customAd.getText("X") / .getImage("X") |
ad.text("X") / ad.image("X") |
customAd.performClick("X") |
ad.click("X") |
NativeAdAssetNames.ASSET_ADCHOICES_CONTAINER_VIEW |
ad.adChoicesAssetName |
view.headlineView = … then view.setNativeAd(ad) |
FuseNativeAdBinding(template).apply { headline = … } |
In your layout, NativeAdView, MediaView and AdChoicesView become plain containers — the SDK supplies what goes into the media and ad-choices slots.
iOS
The iOS SDK passes the Google Mobile Ads object, and your handler returns the rendered view.
FuseSDK.shared.addNativeAdHandler { code, ad in
if code == "<zone_code>" {
return MyNativeAdView(nativeAd: ad)
} else {
return nil
}
}
FuseSDK.shared.addCustomNativeAdHandler { code, ad in
if code == "<zone_code>" {
return MyCustomAdView(customNativeAd: ad)
} else {
return nil
}
}
The Flutter and React Native SDKs do not support direct access to custom native layout. This is handled internally by the Fuse App SDK.
Additional Information
- Custom native format asset names are defined in Google Ad Manager — these are the names you
pass to
ad.text(…)andad.image(…)(Android, iOS) - The iOS SDK passes Google Mobile Ads types, so Google’s iOS guides apply directly: Native Ad Format, Native Video Ads