Search code examples
androidfacebookmopubfacebook-audience-network

'No Ads Found' With MoPub Native Ads and Facebook


I'm attempting to understand why I'm receiving the 'No Ads Found' error message.

Expected

Native ads from the Facebook Audience Network (FAN) to show within the Android RecyclerView feed the same way the test ad units show in the screenshot below.

enter image description here

Setup

Android

I have followed the Android setup for native ads. The app is not live on the Play Store as it is still in testing.

AndroidManifest.xml

...
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="[app-package-here]">
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<application
    android:allowBackup="true"
    android:icon="@drawable/logo"
    android:label="@string/app_name"
    android:networkSecurityConfig="@xml/network_security_config"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <meta-data
        android:name="com.google.android.gms.version"
        android:value="@integer/google_play_services_version" />
        <activity android:name="[app-package-here].MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name="com.mopub.common.privacy.ConsentDialogActivity" android:configChanges="keyboardHidden|orientation|screenSize"/>
        <activity android:name="com.mopub.common.MoPubBrowser" android:configChanges="keyboardHidden|orientation|screenSize"/>
    </application>

</manifest>

network_security_config.xml

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted="true">
        <trust-anchors>
            <certificates src="system"/>
        </trust-anchors>
    </base-config>
    <domain-config cleartextTrafficPermitted="true">
        <domain includeSubdomains="true">127.0.0.1</domain>
        <domain includeSubdomains="true">example.com</domain>
        <domain includeSubdomains="true">cdn.example2.com</domain>
    </domain-config>
</network-security-config>

build.gradle (Module)

implementation('com.mopub:mopub-sdk-native-static:5.4.1@aar') {
    transitive = true
}
implementation 'com.facebook.android:audience-network-sdk:5.1.0'
implementation 'com.mopub.mediation:facebookaudiencenetwork:5.1.0.0'

build.gradle (App)

buildscript {
    ext.kotlin_version = '1.3.11'
    repositories {
        google()
        jcenter()
        mavenCentral()
        maven { url 'https://maven.google.com' }
        maven { url "https://s3.amazonaws.com/moat-sdk-builds" }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.2.1'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath 'com.google.gms:google-services:4.2.0'
        classpath "android.arch.navigation:navigation-safe-args-gradle-plugin:1.0.0-alpha09"
    }
}

allprojects {
    repositories {
        google()
        jcenter()
    maven { url "https://s3.amazonaws.com/moat-sdk-builds" }
    }
}

MainActivity

    val sdkConfiguration = SdkConfiguration.Builder([ad-unit-id-here])
            .build()
    MoPub.initializeSdk(this, sdkConfiguration, initSdkListener())

Activity/Fragment

private fun populateAdapterType() {
    moPubAdapter = MoPubRecyclerAdapter(activity!!, adapter,
                MoPubNativeAdPositioning.MoPubServerPositioning())
    val moPubStaticNativeAdRenderer = MoPubStaticNativeAdRenderer(
           ViewBinder.Builder(R.layout.native_ad_list_item)
                .titleId(R.id.native_title)
                .textId(R.id.native_text)
                .mainImageId(R.id.native_main_image)
                .iconImageId(R.id.native_icon_image)
                .callToActionId(R.id.native_cta)
                .privacyInformationIconImageId(R.id.native_privacy_information_icon_image)
                .build()
    )
    moPubAdapter.registerAdRenderer(moPubStaticNativeAdRenderer)
    contentRecyclerView.adapter = moPubAdapter
    moPubAdapter.loadAds([ad-unit-id-here])
}

MoPub Console

App

enter image description here

Ad Unit

enter image description here

Network

enter image description here

Segment

enter image description here

Actual

The test ad unit id 11a17b188668469fb0412708c3d16813 is showing successfully. However, live Facebook ads are not shown when using the ad unit id created in the MoPub console.

Error: "MoPubNetworkError: No ads found for ad unit"

Full Error

2019-01-11 18:46:12.312 29624-29624/[app-package-here] D/MoPub: MoPubNative Loading ad from: https://ads.mopub.com/m/ad?id=[ad-id-here]&nv=5.4.1&dn=Google%2CPixel%202%2Cwalleye&bundle=[app-package-here]&z=-0800&o=p&w=1080&h=1920&sc=2.625&mcc=310&mnc=260&cn=Google%20Fi&ct=2&av=0.15&udid=mp_tmpl_advertising_id&dnt=mp_tmpl_do_not_track&gdpr_applies=0&force_gdpr_applies=0&current_consent_status=unknown&MAGIC_NO=0

2019-01-11 18:46:12.689 29624-29624/[app-package-here] D/MoPub: Attempting to invoke custom event: com.mopub.nativeads.FacebookNative

2019-01-11 18:46:13.114 29624-29624/[app-package-here] D/MoPub: Successfully hit tracking endpoint: https://ads.mopub.com/m/attempt

2019-01-11 18:46:13.205 29624-29624/[app-package-here] W/MoPub: MoPubNative.onNativeAdLoaded com.mopub.nativeads.CustomEventNativeAdapter@708f83c

2019-01-11 18:46:13.206 29624-29624/[app-package-here] V/MoPub: Native Ad failed to load with error: A required renderer was not registered for the CustomEventNative..

2019-01-11 18:46:13.394 29624-29624/[app-package-here] D/MoPub: Native ad request failed.

com.mopub.network.MoPubNetworkError: No ads found for ad unit.

at com.mopub.network.MultiAdResponse.(MultiAdResponse.java:157)

at com.mopub.network.MultiAdRequest.parseNetworkResponse(MultiAdRequest.java:96)

at com.mopub.volley.NetworkDispatcher.processRequest(NetworkDispatcher.java:132)

at com.mopub.volley.NetworkDispatcher.run(NetworkDispatcher.java:87)

Potential Solutions

  1. Placement ID: In MoPub Facebook was added as a network, but the wrong placement id was added. I've updated the placement id with the one generated from Facebook's Monetization Manager under the Business Manager tools.

With the correct placement ID the Facebook Ad Request Debugger is showing requests being made by MoPub.

Facebook Monetization Manager

enter image description here

MoPub Network Settings > App and ad unit setup

enter image description here

Facebook Ad Request Debugger

enter image description here

  1. App Not Being Live: Currently the app is in test mode so it is not live on the Play Store. However, according to Facebook's documentation Your app won't be able to receive Audience Network ads until payout information has been added. Payout information has been added, but Facebook's documentation does not specify whether the app must be live as well in order to receive ads.

I've also added a test device with my phone's AAID per Facebook's testing documentation so not being live on the Play Store should not be an issue.


Solution

  • Under MoPub's Integrating 3rd Party Ad Networks it explains that a unique Ad Renderer is required for Facebook in addition to using a specific Facebook layout.

    FacebookAdRenderer facebookAdRenderer = new FacebookAdRenderer(
    new FacebookAdRenderer.FacebookViewBinder.Builder(R.layout.native_ad_list_item)
        .titleId(R.id.native_title)
        .textId(R.id.native_text)
        // Binding to new layouts from Facebook 4.99.0+
        .mediaViewId(R.id.native_main_image)
        .adIconViewId(R.id.native_icon_image)
        .adChoicesRelativeLayoutId(R.id.native_ad_choices_relative_layout)
        .advertiserNameId(R.id.native_title) // Bind either the titleId or advertiserNameId depending on the FB SDK version
        // End of binding to new layouts
        .callToActionId(R.id.native_cta)
        .build());
    

    To know which specific layout elements to use in your XML for the MediaView, AdIconView, and AdChoices RelativeLayout in the FacebookViewBinder, please reference this sample XML layout. Additionally, depending on the Facebook SDK version you are integrating, you will need to show only either the ad title or the advertiser name. For more information about Facebook’s implementation requriements, check out this article.

    Then, register your ad renderers, like below. Your classThatRegistersAdRenderers varies depending on which native ad integration you are using. Remember to register your MoPubStaticNativeAdRenderer instance last.

    // MoPubRecyclerAdapter
    MoPubRecyclerAdapter classThatRegistersAdRenderers = new MoPubRecyclerAdapter(...);
    
    // MoPubStreamAdPlacer
    MoPubStreamAdPlacer classThatRegistersAdRenderers = new MoPubStreamAdPlacer(...);
    
    // MoPubAdAdapter
    MoPubAdAdapter classThatRegistersAdRenderers = new MoPubAdAdapter(...);
    
    // MoPubNative
    MoPubNative classThatRegistersAdRenderers = new MoPubNative(...); 
    
    classThatRegistersAdRenderers.registerAdRenderer(
       googlePlayServicesAdRenderer);
    
    classThatRegistersAdRenderers.registerAdRenderer(
      flurryNativeAdRenderer);
    
    classThatRegistersAdRenderers.registerAdRenderer(facebookAdRenderer);
    
    classThatRegistersAdRenderers.registerAdRenderer(staticAdRender);