Native ads
Native ads are an ad format where the appearance of ads can be determined on the app side. Use this feature to adjust the visual style and placement of ads so that they match the design of your app.
Note
Examples showing how all the format types work are available in the demo project.
|
Entity |
Description |
|
|
If |
|
|
In request parameters, you can specify the ad unit ID ( |
|
|
Use:
|
Example of creating a native ad
Define the CustomNative class and create NativeAdView.xml:
class CustomNativeAdActivity : AppCompatActivity(), NativeAdEventListener {
private val nativeAdView get() = binding.nativeAd.root
private val additionalContainer get() = binding.additionalContainer
private val adUnitId = "demo-native-app-yandex" // Use R-M-XXXXXX-Y or demo-block (look for the description below)
private var nativeAdLoader: NativeAdLoader? = null
private lateinit var binding: ActivityCustomNativeAdBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityCustomNativeAdBinding.inflate(layoutInflater)
binding.btnShowBanner.setOnClickListener {
loadNative()
}
setContentView(binding.root)
}
private fun loadNative() {
createNative()
additionalContainer.removeAllViews()
nativeAdView.isVisible = false
nativeAdLoader?.loadAd(buildAdRequestConfiguration())
}
private fun createNative() {
nativeAdLoader = NativeAdLoader(this).apply {
setNativeAdLoadListener(object : NativeAdLoadListener {
override fun onAdLoaded(ad: NativeAd) {
bindNative(ad)
}
override fun onAdFailedToLoad(error: AdRequestError) {}
})
}
}
private fun buildAdRequestConfiguration(): NativeAdRequestConfiguration {
return NativeAdRequestConfiguration
.Builder(adUnitId)
.setShouldLoadImagesAutomatically(true)
.build()
}
private fun bindNative(nativeAd: NativeAd) {
val nativeAdViewBinder = binding.nativeAd.run {
NativeAdViewBinder.Builder(nativeAdView)
.setAgeView(age)
.setBodyView(body)
.setCallToActionView(callToAction)
.setDomainView(domain)
.setFaviconView(favicon)
.setFeedbackView(feedback)
.setIconView(icon)
.setMediaView(media)
.setPriceView(price)
.setRatingView(rating)
.setReviewCountView(reviewCount)
.setSponsoredView(sponsored)
.setTitleView(title)
.setWarningView(warning)
.build()
}
try {
nativeAd.bindNativeAd(nativeAdViewBinder)
nativeAd.info?.let { processAdditionalText(it) }
nativeAd.setNativeAdEventListener(this@CustomNativeAdActivity)
nativeAdView.isVisible = true
} catch (exception: NativeAdException) {
println("Error binding native ad: ${exception.message}")
}
}
private fun processAdditionalText(rawJson: String) {
try {
val jsonObject = JSONObject(rawJson)
val contentJSONArray = jsonObject.getJSONArray("content")
repeat(contentJSONArray.length()) { index ->
val elementName = contentJSONArray.getString(index)
val elementConfiguration = jsonObject.getJSONObject(elementName)
when (elementName) {
"text" -> addTextToLayout(elementConfiguration, index)
"button" -> addButtonToLayout(elementConfiguration, index)
}
}
} catch (e: JSONException) {
println("Error processing additional text: ${e.message}")
}
}
private fun addTextToLayout(textConfiguration: JSONObject, index: Int) {
val textView = TextView(this).apply {
setPadding(16)
text = textConfiguration.getString("value")
}
additionalContainer.addView(textView, index)
}
private fun addButtonToLayout(buttonConfiguration: JSONObject, index: Int) {
val buttonView = Button(this).apply {
setPadding(16)
text = buttonConfiguration.getString("label")
val colorHex = buttonConfiguration.getString("backgroundColor")
setBackgroundColor(Color.parseColor(colorHex))
setOnClickListener {
val link = buttonConfiguration.getString("link")
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(link))
startActivity(intent)
}
}
additionalContainer.addView(buttonView, index)
}
override fun onDestroy() {
nativeAdLoader?.setNativeAdLoadListener(null)
nativeAdLoader = null
super.onDestroy()
}
override fun onAdClicked() {}
override fun onImpression(impressionData: ImpressionData?) {}
override fun onLeftApplication() {}
override fun onReturnedToApplication() {}
}
public class CustomNativeAdActivity extends AppCompatActivity implements NativeAdEventListener {
private ActivityCustomNativeAdBinding binding;
private NativeAdLoader nativeAdLoader;
private NativeAdViewBinder nativeAdViewBinder;
private final String adUnitId = "demo-native-app-yandex"; // Use R-M-XXXXXX-Y or demo-block (look for the description below)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityCustomNativeAdBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
binding.btnShowBanner.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
loadNative();
}
});
}
private void loadNative() {
createNative();
binding.additionalContainer.removeAllViews();
binding.nativeAd.getRoot().setVisibility(View.GONE);
if (nativeAdLoader != null) {
nativeAdLoader.loadAd(buildAdRequestConfiguration());
}
}
private void createNative() {
nativeAdLoader = new NativeAdLoader(this);
nativeAdLoader.setNativeAdLoadListener(new NativeAdLoadListener() {
@Override
public void onAdLoaded(NativeAd ad) {
bindNative(ad);
}
@Override
public void onAdFailedToLoad(AdRequestError error) {}
});
}
private NativeAdRequestConfiguration buildAdRequestConfiguration() {
return new NativeAdRequestConfiguration.Builder(adUnitId)
.setShouldLoadImagesAutomatically(true)
.build();
}
private void bindNative(NativeAd nativeAd) {
NativeAdLayoutBinding adBinding = binding.nativeAd;
// Manual binding creation (or if ViewBinding is auto-generated)
nativeAdViewBinder = new NativeAdViewBinder.Builder(adBinding.getRoot())
.setAgeView(adBinding.age)
.setBodyView(adBinding.body)
.setCallToActionView(adBinding.callToAction)
.setDomainView(adBinding.domain)
.setFaviconView(adBinding.favicon)
.setFeedbackView(adBinding.feedback)
.setIconView(adBinding.icon)
.setMediaView(adBinding.media)
.setPriceView(adBinding.price)
.setRatingView(adBinding.rating)
.setReviewCountView(adBinding.reviewCount)
.setSponsoredView(adBinding.sponsored)
.setTitleView(adBinding.title)
.setWarningView(adBinding.warning)
.build();
try {
nativeAd.bindNativeAd(nativeAdViewBinder);
String infoJson = nativeAd.getInfo();
if (infoJson != null) {
processAdditionalText(infoJson);
}
nativeAd.setNativeAdEventListener(this);
adBinding.getRoot().setVisibility(View.VISIBLE);
} catch (NativeAdException exception) {
System.out.println("Error binding native ad: " + exception.getMessage());
}
}
private void processAdditionalText(String rawJson) {
try {
JSONObject jsonObject = new JSONObject(rawJson);
JSONArray contentJSONArray = jsonObject.getJSONArray("content");
for (int i = 0; i < contentJSONArray.length(); ++i) {
String elementName = contentJSONArray.getString(i);
JSONObject elementConfiguration = jsonObject.getJSONObject(elementName);
switch (elementName) {
case "text":
addTextToLayout(elementConfiguration, i);
break;
case "button":
addButtonToLayout(elementConfiguration, i);
break;
}
}
} catch (JSONException e) {
System.out.println("Error processing additional text: " + e.getMessage());
}
}
private void addTextToLayout(JSONObject textConfiguration, int index) {
TextView textView = new TextView(this);
textView.setPadding(16, 16, 16, 16);
try {
textView.setText(textConfiguration.getString("value"));
} catch (JSONException ignored) { }
binding.additionalContainer.addView(textView, index);
}
private void addButtonToLayout(final JSONObject buttonConfiguration, int index) {
Button buttonView = new Button(this);
buttonView.setPadding(16, 16, 16, 16);
try {
buttonView.setText(buttonConfiguration.getString("label"));
String colorHex = buttonConfiguration.getString("backgroundColor");
buttonView.setBackgroundColor(Color.parseColor(colorHex));
buttonView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
String link = buttonConfiguration.getString("link");
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(link));
startActivity(intent);
} catch (JSONException ignored) { }
}
});
} catch (JSONException ignored) { }
binding.additionalContainer.addView(buttonView, index);
}
@Override
protected void onDestroy() {
if (nativeAdLoader != null) {
nativeAdLoader.setNativeAdLoadListener(null);
nativeAdLoader = null;
}
super.onDestroy();
}
@Override
public void onAdClicked() {}
@Override
public void onImpression(@Nullable ImpressionData impressionData) {}
@Override
public void onLeftApplication() {}
@Override
public void onReturnedToApplication() {}
}
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/coordinatorLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".CustomNativeAdActivity">
<Button
android:id="@+id/btnShowBanner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Load NativeAd"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
<include
android:id="@+id/native_ad"
layout="@layout/native_ad_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:visibility="gone"
app:layout_constraintVertical_weight="1"
app:layout_constraintBottom_toTopOf="@+id/additional_container"/>
<LinearLayout
android:id="@+id/additional_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<com.yandex.mobile.ads.nativeads.NativeAdView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/native_ad_container"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="4dp">
<androidx.constraintlayout.widget.Group
android:id="@+id/components"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="age,sponsored,feedback,title" />
<TextView
android:id="@+id/age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:textColor="#7f7f7f"
app:layout_constraintBottom_toTopOf="@id/barrier_top"
app:layout_constraintEnd_toStartOf="@id/sponsored"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="18+"
tools:visibility="visible" />
<TextView
android:id="@+id/sponsored"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:textColor="#7f7f7f"
android:textSize="11sp"
app:layout_constraintBottom_toTopOf="@id/barrier_top"
app:layout_constraintEnd_toStartOf="@id/feedback"
app:layout_constraintStart_toEndOf="@id/age"
app:layout_constraintTop_toTopOf="parent"
tools:text="Yandex.Direct"
tools:visibility="visible" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/feedback"
android:layout_width="16dp"
android:layout_height="16dp"
app:layout_constraintBottom_toTopOf="@id/barrier_top"
android:src="@drawable/close_button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/sponsored"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier_top"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="bottom"
app:constraint_referenced_ids="age,sponsored,feedback" />
<ImageView
android:id="@+id/icon"
android:layout_width="80dp"
android:layout_height="80dp"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
android:layout_marginTop="4dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toTopOf="@id/barrier_body"
app:layout_constraintEnd_toStartOf="@id/barrier_icon"
app:layout_constraintTop_toBottomOf="@id/barrier_top"
tools:visibility="visible" />
<TextView
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:maxLines="2"
android:textSize="15sp"
style="@style/TextAppearance.Material3.TitleSmall"
app:layout_constraintBottom_toTopOf="@id/body"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/barrier_icon"
app:layout_constraintTop_toBottomOf="@id/barrier_top"
app:layout_constraintVertical_chainStyle="packed"
tools:text="Yandex.Browser for iPhone and Android"
tools:visibility="visible" />
<TextView
android:id="@+id/body"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:maxLines="3"
android:textSize="13sp"
style="@style/TextAppearance.Material3.BodySmall"
app:layout_constraintBottom_toTopOf="@id/barrier_domain"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/barrier_icon"
app:layout_constraintTop_toBottomOf="@id/title"
tools:text="Your bookmarks and favorite sites are available to you on any device with Yandex.Browser. You will never lose them, even if you lose your device or break it."
tools:visibility="visible" />
<ImageView
android:id="@+id/favicon"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_marginEnd="4dp"
android:layout_marginRight="4dp"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
app:layout_constraintBottom_toTopOf="@id/barrier_domain"
app:layout_constraintEnd_toStartOf="@id/domain"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toEndOf="@id/barrier_icon"
app:layout_constraintTop_toBottomOf="@id/body"
tools:visibility="visible" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier_domain"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="top"
app:constraint_referenced_ids="domain,favicon" />
<TextView
android:id="@+id/domain"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:textColor="#7f7f7f"
android:textSize="13sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="@id/barrier_body"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toEndOf="@id/favicon"
app:layout_constraintTop_toBottomOf="@id/body"
tools:text="https://browser.yandex.com"
tools:visibility="visible" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier_body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="bottom"
app:constraint_referenced_ids="title,icon,body,domain,favicon" />
<TextView
android:id="@+id/price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toTopOf="@id/rating"
app:layout_constraintEnd_toStartOf="@id/barrier_rating"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toEndOf="@id/barrier_icon"
app:layout_constraintTop_toBottomOf="@id/barrier_body"
tools:text="Free"
tools:visibility="visible" />
<com.example.myapplication.RatingView
android:id="@+id/rating"
style="?android:attr/ratingBarStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="4dp"
android:numStars="5"
android:stepSize="0.5"
app:layout_constraintBottom_toTopOf="@id/review_count"
app:layout_constraintEnd_toStartOf="@id/barrier_rating"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintStart_toEndOf="@id/barrier_icon"
app:layout_constraintTop_toBottomOf="@id/price"
tools:visibility="visible" />
<TextView
android:id="@+id/review_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:textColor="#7f7f7f"
android:textSize="13sp"
app:layout_constraintBottom_toTopOf="@id/barrier_footer"
app:layout_constraintEnd_toStartOf="@id/barrier_rating"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toEndOf="@id/barrier_icon"
app:layout_constraintTop_toBottomOf="@id/rating"
tools:text="review count"
tools:visibility="visible" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="end"
app:constraint_referenced_ids="icon" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier_rating"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="end"
app:constraint_referenced_ids="rating,price,review_count" />
<Button
android:id="@+id/call_to_action"
style="@style/Widget.AppCompat.Button.Borderless"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/call_to_action_background"
android:maxLines="1"
android:minHeight="36dp"
android:textAllCaps="false"
android:textSize="13sp"
app:layout_constraintBottom_toTopOf="@id/barrier_footer"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/barrier_rating"
app:layout_constraintTop_toBottomOf="@id/barrier_body"
app:layout_constraintHorizontal_bias="1"
app:layout_constraintVertical_bias="1"
tools:text="Install"
tools:visibility="visible" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier_footer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="bottom"
app:constraint_referenced_ids="price,domain,call_to_action,review_count" />
<com.yandex.mobile.ads.nativeads.MediaView
android:id="@+id/media"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constrainedHeight="true"
app:layout_constrainedWidth="true"
android:layout_marginTop="4dp"
android:layout_marginBottom="4dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/barrier_footer"
app:layout_constraintBottom_toTopOf="@id/warning"
tools:visibility="visible" />
<TextView
android:id="@+id/warning"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#f5f5f5"
android:paddingLeft="8dp"
android:paddingTop="4dp"
android:paddingRight="8dp"
android:textColor="#7f7f7f"
android:textSize="13sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/media"
android:visibility="gone"
tools:text="We strongly recommend avoiding this type of website and not clicking the Ignore this warning button!"
tools:visibility="visible" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.yandex.mobile.ads.nativeads.NativeAdView>
Checking integration
Build and run your project. You can check if the integration is successful by searching the YandexAds keyword in Logcat:
[Integration] Ad type native was integrated successfully