Skip to main content

Native Template Ads

Starting from NAM SDK version 8.5.0, you can easily implement native ads through the Native Simple Ad format without complex configurations and additional work. This guide explains the Native Template option, which is a method for loading and displaying native ads in the Native Simple Ad format.

Native Templates are designed to allow faster implementation and easier customization of native ads. Using Native Templates, you can implement even your first native ad in minutes and quickly customize the design and style with minimal code.

To effectively apply this guide, you should be familiar with implementing native ads.


Before You Start

Refer to the Native Simple Ads guide to learn how to load and display Native Simple Ads.


Native Template Options

When loading and displaying native ads through the Native Simple Ad format, you can declare the use of native templates using the GfpNativeSimpleAdOptions.Builder().setNativeTemplateOptions() method.

If you don't set GfpNativeTemplateOptions while building GfpNativeSimpleAdOptions, the Native Simple Ad loaded with that GfpNativeSimpleAdOptions is considered not to use Native Template Ads. In this case, only the Native Simple Ad loading is performed, same as regular Native Simple Ad usage.

The example below shows how to apply Native Templates using default GfpNativeTemplateOptions values.

val nativeTemplateOptions = GfpNativeTemplateOptions.Builder().build()
val nativeSimpleAdOptions = GfpNativeSimpleAdOptions.Builder()
.setNativeTemplateOptions(nativeTemplateOptions)
.build()
val adLoader = GfpAdLoader.Builder(this, adParam)
...
.withNativeSimpleAd(nativeSimpleAdOptions) { nativeSimpleAd ->
...
}
.build()

Custom Native Templates

When applying default GfpNativeTemplateOptions as shown in the example above, native ads will be rendered through the default template built into the SDK as shown in the image below.

image

If you want to design the native ad layout from scratch while using Native Templates, please follow the example below.

1. Define Native Template Layout

Define the native ad layout as shown in the example below.

info

When defining an ad layout for Native Templates, the defined top-level ViewGroup is automatically added as a child view of GfpNativeAdView by the SDK. Therefore, unlike existing native ad layouts, you don't need to directly include ad assets inside GfpNativeAdView.

custom_native_template.xml
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:ignore="ContentDescription,RtlHardcoded,SpUsage,RtlSymmetry"
tools:parentTag="com.naver.example.CustomNativeTemplateAdView">

<LinearLayout
android:id="@+id/ad_top_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingLeft="10dp"
android:paddingTop="10dp"
android:paddingRight="10dp"
android:paddingBottom="10dp">

<ImageView
android:id="@+id/ad_icon"
android:layout_width="35dp"
android:layout_height="35dp" />

<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:paddingLeft="5dp"
android:paddingRight="5dp">

<TextView
android:id="@+id/ad_advertiser"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:lines="1"
android:textColor="@android:color/black"
android:textSize="15dp" />

<TextView
android:id="@+id/ad_badge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:lines="1"
android:text="AD"
android:textColor="@android:color/darker_gray"
android:textSize="12dp" />

</LinearLayout>

<com.naver.gfpsdk.GfpAdChoicesView
android:id="@+id/ad_choices"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

</LinearLayout>

<com.naver.gfpsdk.GfpMediaView
android:id="@+id/ad_media"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/ad_top_container"
android:gravity="center" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/ad_media"
android:orientation="horizontal"
android:padding="5dp">

<TextView
android:id="@+id/ad_body"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="3"
android:ellipsize="end"
android:gravity="center_vertical"
android:lines="2"
android:textColor="@android:color/black"
android:textSize="12dp" />

<Button
android:id="@+id/ad_call_to_action"
android:layout_width="100dp"
android:layout_height="30dp"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:background="#4286F4"
android:paddingLeft="3dp"
android:paddingRight="3dp"
android:textColor="@android:color/white"
android:textSize="12sp" />

</LinearLayout>
</merge>

2. Define Native Template View

Define a custom native template view using the layout defined above.

CustomNativeTemplateAdView.kt
package com.naver.example

import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.widget.Button
import android.widget.ImageView
import android.widget.RelativeLayout
import android.widget.TextView
import com.naver.example.R
import com.naver.gfpsdk.GfpAdChoicesView
import com.naver.gfpsdk.GfpMediaView
import com.naver.gfpsdk.GfpNativeAdView
import com.naver.gfpsdk.mediation.NativeAssetProvider
import com.naver.gfpsdk.mediation.NativeTemplateAdView

class CustomNativeTemplateAdView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : RelativeLayout(context, attrs, defStyleAttr), NativeTemplateAdView {
class Factory : NativeTemplateAdView.Factory {
override fun create(context: Context): NativeTemplateAdView {
return CustomNativeTemplateAdView(context)
}
}

private val iconView: ImageView
private val advertiserView: TextView
private val bodyView: TextView
private val callToActionView: Button
private val adChoicesView: GfpAdChoicesView
private val mediaView: GfpMediaView

init {
LayoutInflater.from(context).inflate(R.layout.custom_native_template_ad_view, this)
iconView = findViewById(R.id.ad_icon)
advertiserView = findViewById(R.id.ad_advertiser)
adChoicesView = findViewById(R.id.ad_choices)
mediaView = findViewById(R.id.ad_media)
bodyView = findViewById(R.id.ad_body)
callToActionView = findViewById(R.id.ad_call_to_action)
}

override fun bind(
nativeAdView: GfpNativeAdView,
nativeAssetProvider: NativeAssetProvider,
renderingOptions: NativeTemplateAdView.RenderingOptions
) {
val icon = nativeAssetProvider.icon
if (icon != null) {
iconView.visibility = View.VISIBLE
iconView.setImageDrawable(icon.drawable)
nativeAdView.iconView = iconView
} else {
iconView.visibility = View.GONE
}

val advertiser = nativeAssetProvider.advertiserName
if (advertiser != null) {
advertiserView.visibility = View.VISIBLE
advertiserView.text = advertiser
nativeAdView.advertiserView = advertiserView
} else {
advertiserView.visibility = View.GONE
}

val body = nativeAssetProvider.body
if (body != null) {
bodyView.visibility = View.VISIBLE
bodyView.text = body
nativeAdView.bodyView = bodyView
} else {
bodyView.visibility = View.GONE
}

val callToAction = nativeAssetProvider.callToAction
if (callToAction != null) {
callToActionView.visibility = View.VISIBLE
callToActionView.text = callToAction
nativeAdView.callToActionView = callToActionView
} else {
callToActionView.visibility = View.GONE
}

nativeAdView.adChoicesView = adChoicesView
nativeAdView.mediaView = mediaView
}

override fun onUserShowInterestChanged(
showInterest: Boolean,
nativeAssetProvider: NativeAssetProvider,
renderingOptions: NativeTemplateAdView.RenderingOptions
) {
// do nothing
}
}

Each task is as follows:

1. Create Custom View Inheriting NativeTemplateAdView

When creating a view for custom templates, you must implement NativeTemplateAdView as shown in the example below. Also, create the view using the layout created earlier.

class CustomNativeTemplateAdView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : RelativeLayout(context, attrs, defStyleAttr),
NativeTemplateAdView {
...

private val iconView: ImageView
private val advertiserView: TextView
private val bodyView: TextView
private val callToActionView: Button
private val adChoicesView: GfpAdChoicesView
private val mediaView: GfpMediaView

init {
LayoutInflater.from(context).inflate(R.layout.custom_native_template_ad_view, this)
iconView = findViewById(R.id.ad_icon)
advertiserView = findViewById(R.id.ad_advertiser)
adChoicesView = findViewById(R.id.ad_choices)
mediaView = findViewById(R.id.ad_media)
bodyView = findViewById(R.id.ad_body)
callToActionView = findViewById(R.id.ad_call_to_action)
}
}

2. Map Ad Assets to Each View in bind() Method

Override the bind() method of NativeTemplateAdView to bind ad assets provided by NativeAssetProvider to each View.

info
  • GfpAdChoicesView and GfpMediaView: Simply register them to GfpNativeAdView without separate settings.
  • Other Ad Assets: Set images or text first, then register them to GfpNativeAdView.
class CustomNativeTemplateAdView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : RelativeLayout(context, attrs, defStyleAttr),
NativeTemplateAdView {
...

override fun bind(
nativeAdView: GfpNativeAdView,
nativeAssetProvider: NativeAssetProvider,
renderingOptions: NativeTemplateAdView.RenderingOptions
) {
val icon = nativeAssetProvider.icon
if (icon != null) {
iconView.visibility = View.VISIBLE
iconView.setImageDrawable(icon.drawable)
nativeAdView.iconView = iconView
} else {
iconView.visibility = View.GONE
}

val advertiser = nativeAssetProvider.advertiserName
if (advertiser != null) {
advertiserView.visibility = View.VISIBLE
advertiserView.text = advertiser
nativeAdView.advertiserView = advertiserView
} else {
advertiserView.visibility = View.GONE
}

...

nativeAdView.adChoicesView = adChoicesView
nativeAdView.mediaView = mediaView
}
}

3. Create Factory Class

To create a custom native template view, you must create a Factory class that inherits from NativeTemplateAdView.Factory. The created Factory object can be registered to GfpNativeTemplateOptions for use as a custom native template view.

class CustomNativeTemplateAdView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : RelativeLayout(context, attrs, defStyleAttr),
NativeTemplateAdView {
...

class Factory : NativeTemplateAdView.Factory {
override fun create(context: Context): NativeTemplateAdView {
return CustomNativeTemplateAdView(context)
}
}
}

4. (Optional) onUserShowInterestChanged() Method

The onUserShowInterestChanged() method of NativeTemplateAdView is called when the user's ad interest level changes.

Call Timing:

  • Interest Start: When 50% or more of the ad area is exposed for 1 second, showInterest value is passed as true.
  • Interest End: When the ad area is no longer exposed, showInterest value is passed as false.

Usage Example: Dynamic UI processing such as changing the color of the Call to Action button when the user shows interest to increase ad visibility is possible.

class CustomNativeTemplateAdView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : RelativeLayout(context, attrs, defStyleAttr),
NativeTemplateAdView {
...

override fun onUserShowInterestChanged(
showInterest: Boolean,
nativeAssetProvider: NativeAssetProvider,
renderingOptions: NativeTemplateAdView.RenderingOptions
) {
if (showInterest) {
callToActionView.setBackgroundColor(highlightedBgColor)
} else {
callToActionView.setBackgroundColor(defaultBgColor)
}
}
}

3. Register Native Template

To use a custom native template view, you must register it to GfpNativeTemplateOptions.

Register the Factory as follows:

  • Use addNativeTemplateAdViewFactory() method
  • Set GfpNativeTemplateOptions.DEFAULT_VISUAL_KEY as the visual key
  • Pass the custom native template view Factory object created earlier
val nativeTemplateOptions = GfpNativeTemplateOptions.Builder()
.addNativeTemplateAdViewFactory(
GfpNativeTemplateOptions.DEFAULT_VISUAL_KEY, CustomNativeTemplateAdView.Factory()
)
.build()
val nativeSimpleAdOptions = GfpNativeSimpleAdOptions.Builder()
.setNativeTemplateOptions(nativeTemplateOptions)
...
.build()
val adLoader = GfpAdLoader.Builder(this, adParam)
...
.withNativeSimpleAd(nativeSimpleAdOptions) { nativeSimpleAd ->
...
}
.build()

4. Ad Request and Rendering

Once you have completed the above process, the subsequent ad request, rendering, and ad resource cleanup processes are the same as existing Native Simple Ads. However, when using Native Templates, since native ads are processed through the Native Simple Ad format, the following processing required for native ad loading should not be included when building GfpAdLoader.

val nativeTemplateOptions = GfpNativeTemplateOptions.Builder()
.addNativeTemplateAdViewFactory(
GfpNativeTemplateOptions.DEFAULT_VISUAL_KEY, CustomNativeTemplateAdView.Factory()
)
.build()
val nativeSimpleAdOptions = GfpNativeSimpleAdOptions.Builder()
.setNativeTemplateOptions(nativeTemplateOptions)
...
.build()
val adLoader = GfpAdLoader.Builder(this, adParam)
...
.withNativeSimpleAd(nativeSimpleAdOptions) { nativeSimpleAd ->
...
}
.withNativeAd { nativeAd ->
// withNativeAd() should not be included when using Native Templates.
}
.build()