Skip to main content
Version: 3.3.0-beta

Native

Native ad is a flexible type of advertising. You can adapt the display to your UI by preparing a template.

info

Appodeal provides 4 options to implement the layout of native ads 3 templates + your custom implementation All of them are inherited from the same NativeAdView class.

NativeAdView consists of the following components:

  1. NativeIconView - Icon of the native ad.
  2. AdAttributionView - Advertising Indicator. This is a TextView labeled "Ad".
  3. TitleVIew - Title of the native ad.
  4. DescriptionView - Text descriptionView of the native ad.
  5. RatingBarView - Rating of the app in [0-5] range.
  6. NativeMediaView - Media content of the native ad.
  7. CallToActionView - Button for click.
  8. AdChoiceView - Special ad icon provided by ad network.

Templates implementation:

To display them, all you need to do is:

  1. Create programmatically or in your layout file one of View template classes

Native template views classes:

  • NativeAdViewNewsFeed
  • NativeAdViewAppWall
  • NativeAdViewContentStream

NativeAdView for custom implementation:

To display it, all you need to do is:

  1. Create a NativeAdVIew class programmatically or in your layout file
  2. Inside the created NativeAdView, arrange all the View/IconView/MediaView you need for displaying it in any style you prefer
  3. Bind programmatically or in your layout file all necessary View/IconView/MediaView.

Native view for a Custom Implementation:

  • NativeAdView

You can use our demo app as a reference project.

Native Demo

Integration guide

  1. Create programmatically or in your layout file one of View template classes:
<com.appodeal.ads.nativead.NativeAdViewNewsFeed
android:id="@+id/native_news_feed"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

<com.appodeal.ads.nativead.NativeAdViewAppWall
android:id="@+id/native_app_wall"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

<com.appodeal.ads.nativead.NativeAdViewContentStream
android:id="@+id/native_content_stream"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
  1. Get a view instance from layout OR add a programmatically created ViewTemplate to your View hierarchy:
val newsFeedView = findViewById<NativeAdViewNewsFeed>(R.id.native_news_feed);
val appWallView = findViewById<NativeAdViewAppWall>(R.id.native_app_wall);
val contentStreamView = findViewById<NativeAdViewContentStream>(R.id.native_content_stream);

rootView.addView(newsFeedView)
rootView.addView(appWallView)
rootView.addView(contentStreamView)
  1. When the NativeAd is loaded just register it
if (Appodeal.isLoaded(Appodeal.NATIVE)) {
newsFeedView.registerView(Appodeal.getNativeAdCount(1))
}
  1. When the display has been terminated and you no longer plan to use the NativeAdView, you should call the destroy method:
nativeAdView.destroy()

Check If Ad Is Loaded

To check if at least 1 instance of NativeAd is loaded, use the method:

Appodeal.isLoaded(Appodeal.NATIVE)

To get how many NativeAd instances are loaded, use the method:

val nativeAmount = Appodeal.getAvailableNativeAdsCount()
note

By default, the Appodeal SDK with AutoCahce enabled loads 2 instances of NativeAd each

tip

We recommend you always check whether an ad is available before trying to show it.

Get Loaded Native Ads

To get loaded native ads, use the following method:

val nativeAds: List<NativeAd> = Appodeal.getNativeAds(amount)
danger

Once you get the ads, they are removed from our SDK cache.

Display

To display NativeAd, you need to call the following code:

NativeAdView.registerView(nativeAd: NativeAd)
danger

SDK can't show ads without a network connection!

NativeAdView.registerView() returns a boolean value indicating whether the show method call was passed to the appropriate SDK.

info

Before the registerView(nativeAd) method is called, NativeAdView is in the visibility == GONE state. After the call, the state will automatically change to visibility == VISIBLE.

You don't need to change the visibility state, Appodeal SDK does it automatically.

After calling destroy(), the state will automatically change to visibility == GONE.

tip

NativeAdView and its successors have a built-in attribute tools:visibility="visible" so the view will be displayed in your IDE markup during development.

Placements

Appodeal SDK allows you to tag each impression with different placement. To use placements, you need to create placements in Appodeal Dashboard. Read more about placements.

To show an ad with placement, you have to call show method:

NativeAdView.registerView(nativeAd: NativeAd, yourPlacementName: String)
info

If the loaded ad can’t be shown for a specific placement, nothing will be shown.

If auto caching is enabled, sdk will start to cache another ad, which can affect display rate. To save the loaded ad for future use (for instance, for another placement) check if the ad can be shown before calling the show method:

if (NativeAd.canShow(context: Context, yourPlacementName: String)) {
NativeAdView.registerView(nativeAd: NativeAd, yourPlacementName: String)
}

You can configure your impression logic for each placement.

info

If you have no placements, or call NativeAdView.registerView with a placement that does not exist, the impression will be tagged with 'default' placement and its settings will be applied.

note

Placement settings affect ONLY ad presentation, not loading or caching.

UnregisterView

To unregister the view from displaying the currently registered native ad use the method:

NativeAdView.unregisterView()
note

UnregisterView method does not hide the NativeAdView. It suspends the NativeAd display tracking.

tip

UnregisterView makes sense to use, for example, if the NativeAdView is out of the screen while scrolling in the list, or is temporarily overlapped by another View/Fragment/Activity

Destroy

To destroy the native ad view and perform any necessary cleanup, and hide NativeAdView use the method:

NativeAdView.destroy()
info

This method should be called when the native ad is no longer needed.

Also, when destroy() is called, the unregisterView logic is triggered.

Callbacks

Appodeal.setNativeCallbacks(object : NativeCallbacks {
override fun onNativeLoaded() {
// Called when native ads are loaded
}
override fun onNativeFailedToLoad() {
// Called when native ads are failed to load
}
override fun onNativeShown(nativeAd: NativeAd) {
// Called when native ad is shown
}
override fun onNativeShowFailed(nativeAd: NativeAd) {
// Called when native ad show failed
}
override fun onNativeClicked(nativeAd: NativeAd) {
// Called when native ads is clicked
}
override fun onNativeExpired() {
// Called when native ads is expired
}
})
info

All callbacks are called on the main thread.

Cache Manually

To disable automatic caching for native ads, use the code below before the SDK initialization:

Appodeal.setAutoCache(Appodeal.NATIVE, false)

Read more on manual caching in our ** FAQ**.

Cache

To cache native ads, use:

Appodeal.cache(this, Appodeal.NATIVE)

To cache multiple native ads, use:

Appodeal.cache(this, Appodeal.NATIVE, 3)
note

You may request a maximum of 5 NativeAd

The number of cached ads is not guaranteed and could be less than requested.

Check If Ad Is Initialized

To check if NativeAd was initialized, you can use the method:

Appodeal.isInitialized(Appodeal.NATIVE)

Returnstrue, if the NativeAd was initialized.

Check If Autocache Is Enabled

To check if autocache is enabled for NativeAd, you can use the method:

Appodeal.isAutoCacheEnabled(Appodeal.NATIVE)

Returns true, if autocache is enabled for native.

Get Predicted eCPM

To get the predicted eCPM from the next block in the caching queue, use the method:

NativeAd.predictedEcpm

Configuration

Set preferred media content type

You can tell the Appodeal SDK your preferred content type for NativeAd. To do this, use the method:

// both static image and video native ads will be loaded
Appodeal.setPreferredNativeContentType(NativeMediaViewContentType.Auto)
// only static image native ads will be loaded
Appodeal.setPreferredNativeContentType(NativeMediaViewContentType.NoVideo)
// only video native ads will be loaded.
Appodeal.setPreferredNativeContentType(NativeMediaViewContentType.Video)
info

Setting a video type does not guarantee that it will be loaded, but only indicates the preferred type.

To check if the downloaded advertisement contains video you can use the method:

NativeAd.containsVideo()

Return true if NativeAd contains video

Use the method to retrieve the preferred content type:

Appodeal.getPreferredNativeContentType()
note

Only affects content inside the NativeMediaView. Therefore, it makes sense to use it only in case of NativeAdViewContentStream template or your out custom implementation of NativeAdView.

Content for NativeIconView is always a static image

Set adChoice position

You can specify a position in one of the corners of the NativeAdView:

app:adChoicePosition="end_top"
info

As a Position you can specify one of 4 options:

START_TOP - matches to the upper left corner of NativeAdView;

START_BOTTOM - matches to the lower left corner of NativeAdView;

END_TOP - matches the upper right corner of NativeAdView;

END_BOTTOM - matches the bottom right corner of NativeAdView.

AdAttributionView settings

You may set text color and background color for AdAttributionView in NativeAdView:

app:adAttributionBackgroundColor="@color/red"
app:adAttributionTextColor="@color/black"
info

Color should have ColorInt format. See android.graphics.Color.

note

For custom NativeAdView, you may do the same via your xml markup using attributes android:textColor and android:background for adAttribution TextView.

Works with lists

To use NativeAd in RecyclerView, you can use the following example:

  1. Create an ListItem entity that will serve to define the itemViewType in RecyclerView.ListAdapter:
sealed interface ListItem {
fun getItemId(): Int

class NativeAdItem(val getNativeAd: () -> NativeAd?) : ListItem {
override fun getItemId() = NATIVE_AD_ITEM

companion object {
const val NATIVE_AD_ITEM = 3
}
}

data class YourDataItem(val userData: Int) : ListItem {
override fun getItemId() = USER_ITEM

companion object {
const val USER_ITEM = 2
}
}
}
  1. Create a DiffUtil.ItemCallback<ListItem> entity that will show the ListAdapter the differences between items:
internal class DiffUtils : DiffUtil.ItemCallback<ListItem>() {
override fun areItemsTheSame(oldItem: ListItem, newItem: ListItem) =
oldItem.getItemId() == newItem.getItemId()

override fun areContentsTheSame(oldItem: ListItem, newItem: ListItem) =
oldItem.hashCode() == newItem.hashCode()
}
  1. Create a ListAdapter entity, which will be an adapter for RecyclerView:
class NativeListAdapter : ListAdapter<ListItem, ListHolder>(DiffUtils()) {

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListHolder {
return when (viewType) {
NATIVE_AD_ITEM -> { DynamicAdViewHolder(NativeAdViewContentStream(parent.context)) }
else -> {
YourViewHolder(
YourDataItemBinding.inflate(LayoutInflater.from(parent.context),
parent,
false
))
}
}
}

override fun onBindViewHolder(holder: ListHolder, position: Int) {
when (val item = getItem(position)) {
is ListItem.YourDataItem -> (holder as YourViewHolder).bind(item)
is ListItem.NativeAdItem -> (holder as DynamicAdViewHolder).bind(item)
}
}

override fun getItemViewType(position: Int): Int {
return when (currentList[position]) {
is ListItem.YourDataItem -> USER_ITEM
is ListItem.NativeAdItem -> NATIVE_AD_ITEM
}
}

sealed class ListHolder(root: View) : RecyclerView.ViewHolder(root) {
class YourViewHolder(private val binding: YourDataItemBinding) : ListHolder(binding.root) {
fun bind(item: ListItem.YourDataItem) {
binding.root.text = item.userData.toString()
}
}

class DynamicAdViewHolder(itemView: View) : ListHolder(itemView) {
fun bind(item: ListItem.NativeAdItem) {
val nativeAd = item.getNativeAd.invoke()
if (nativeAd != null) {
(itemView as NativeAdView).registerView(nativeAd)
}
}
}
}
}
info

NATIVE_AD_ITEM - NativeAdItem.NATIVE_AD_ITEM

  1. As the markup of your Activity/Fragment, we use the markup
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:attr/colorBackground">

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />

</FrameLayout>

We'll use the example as the markup of your YourDataItem:

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:textSize="64sp"
tools:text="1" />
  1. In your Activity/Fragment, add the following code
class NativeActivity : AppCompatActivity() {

private val getNativeAd: () -> NativeAd? = { Appodeal.getNativeAds(1).firstOrNull() }

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = ActivityNativeBinding.inflate(layoutInflater)
setContentView(binding.root)

val nativeListAdapter = NativeListAdapter()
binding.recyclerView.adapter = nativeListAdapter

setUpAppodealSDK()
}

private fun setUpAppodealSDK() {
Appodeal.setLogLevel(LogLevel.verbose)
Appodeal.setTesting(true)
Appodeal.initialize(this, APPODEAL_APP_KEY, Appodeal.NATIVE) { errors ->
val initResult = if (errors.isNullOrEmpty()) "successfully" else "with ${errors.size} errors"
Log.d("TAG", "onInitializationFinished: $initResult")
}
}

private fun obtainData(nativeListAdapter: NativeListAdapter) {
val yourDataItems = generateYourData()
nativeListAdapter.submitList(yourDataItems.addNativeAdItems())
}

private fun List<ListItem>.addNativeAdItems() =
this.foldIndexed(
initial = listOf(),
operation = { index: Int, acc: List<ListItem>, yourDataItem: ListItem ->
val shouldAdd = index % STEPS == 0 && index != 0
if (shouldAdd) {
acc + createNativeAdItem() + yourDataItem
} else {
acc + yourDataItem
}
}
)

private fun generateYourData(): List<ListItem> =
(1..USER_DATA_SIZE).toList().map { ListItem.YourDataItem(userData = it) }

private fun createNativeAdItem(): ListItem.NativeAdItem =
ListItem.NativeAdItem(getNativeAd = getNativeAd)
}
private const val USER_DATA_SIZE = 200
private const val STEPS = 5
info

STEPS - step through which the insertion of NativeAd will be repeated;

addNativeAdItems() - logic of inserting NativeAd into the list through a certain number of STEPS.

Done! When you want to insert native ads into RecyclerView, simply call the obtainData() method

Common Mistakes

  • No adAttributionView

The majority of ad networks require publishers to add a special mark to a native ad, so users don’t mistake them for content. That’s why you always need to make sure, that native ads in your app have the ad attribution (e.g., “Ad”) or the AdChoices icon.

  • Absence of the required native ad elements

Every native ad should contain:

  • titleView TextView;

  • callToActionView Button;

  • adAttribution TextView;

  • NativeIconView or NativeMedaiaView.

  • Native ad elements alteration

Advertisers expect that their ads will be displayed clearly and without any alteration. You can scale buttons and images, but you shouldn't crop, cover or distort them.

  • Overlaying elements of native ads on each other

Make sure, that all elements of a native ad are visible and not overlaid.

Native ads requirements:

  • All of the fields of native ad marked as mandatory must be displayed.
  • Image assets can be resized to fit your ad space but should not be significantly distorted or cropped.

Check Viewability

You can always check in logs if show was tracked and your ad is visible.

You will see the Native [Notify Shown] log if show was tracked successfully.

Appodeal  com.example.app  D Native [Notify Shown]