تطوير محوِّل عروض الأسعار

هذا الدليل مخصّص لشبكات الإعلانات التي تسعى إلى إنشاء محوّل عروض أسعار للمشاركة في عروض الأسعار في الوقت الفعلي (RTB) ضمن ميزة التوسّط من Google. إذا كنت ناشرًا، يمكنك الاطّلاع على تعليمات توسّط الناشرين.

محوّل عروض الأسعار هو الجزء من عملية الدمج الذي يتم من جهة العميل. يتيح المحوّل لحزمة تطوير البرامج (SDK) لشبكة الإعلانات التواصل مع Google Mobile Ads SDK (Legacy) لتحميل الإعلانات التي يعرضها مقدّم عرض السعر.

لكي تعمل عروض الأسعار بشكل صحيح، يجب أن يتعامل المحوّل مع عمليات الإعداد وجمع الإشارات وتحميل الإعلانات ونقل أحداث دورة حياة الإعلانات. في هذا الدليل، سنشرح لك كيفية تنفيذ المحوّل للتعامل مع هذه العمليات.

سير عمل محوّل عروض الأسعار

الإعداد

في ما يلي مسار تفصيلي لدورة حياة الطلب والاستجابة والعرض الكاملة للمحوّل:

يكون المحوّل مسؤولاً عن الأجزاء التالية من سير العمل:

  • الخطوات من 4 إلى 7: عليك إعداد المحوّل واستدعاء Google Mobile Ads SDK (Legacy) بعد اكتمال الإعداد.

  • الخطوات من 10 إلى 13: جمع الإشارات من حزمة تطوير البرامج (SDK) لشبكة الإعلانات لإرسالها إلى مقدِّم عرض السعر للمشاركة في طلب عرض الأسعار في الوقت الفعلي (RTB)، وإعادة توجيهها إلى حزمة SDK لإعلانات Google على الأجهزة الجوّالة.

  • الخطوات من 18 إلى 21: إذا أرسل مقدّم عرض السعر عرض السعر الفائز، يتم تحميل الإعلان وفقًا للاستجابة من مقدّم عرض السعر. بعد تحميل الإعلان، يتم إعلام Google Mobile Ads SDK (Legacy) بأنّه تم تحميل الإعلان.

  • الخطوة 23 وما بعدها: أثناء عرض إعلانك، أرسِل إشعارًا إلى "SDK لإعلانات Google على الأجهزة الجوّالة" بشأن أحداث مرّات الظهور والنقرات، بالإضافة إلى أحداث الإعلانات الأخرى التي تقع خلال مراحل نشاط عرض إعلانك.

تنفيذ محوِّل عروض الأسعار

لإنشاء محوِّل عروض أسعار لـ "Google Mobile Ads SDK (Legacy)"، عليك توسيع الفئة المجرّدة "RtbAdapter". توضّح الأقسام التالية كل طريقة مجرّدة في RtbAdapter.

getSDKVersionInfo()

هنا يجب عرض إصدار حزمة SDK. يتم تمرير هذا الإصدار إلى مقدّم عرض السعر كجزء من طلب OpenRTB.

تتطلّب هذه الطريقة إرجاع VersionInfo. يوضّح المثال أدناه كيفية تحويل إصدار السلسلة في حزمة SDK إلى VersionInfo.

@Override
public VersionInfo getSDKVersionInfo() {
  // Get your SDK's version as a string. E.g. "1.2.3"
  // String versionString = YourSdk.getVersion();
  String splits[] = versionString.split("\\.");
  if (splits.length >= 3) {
      int major = Integer.parseInt(splits[0]);
      int minor = Integer.parseInt(splits[1]);
      int micro = Integer.parseInt(splits[2]);
      return new VersionInfo(major, minor, micro);
   }

   String logMessage = String.format("Unexpected SDK version format: %s." +
           "Returning 0.0.0 for SDK version.", sdkVersion);
   Log.w(TAG, logMessage);
   return new VersionInfo(0, 0, 0);
}

getVersionInfo()

هنا يجب عرض إصدار المحوّل. يتم تمرير هذا الإصدار إلى مقدّم عرض السعر كجزء من طلب OpenRTB.

تستخدم المحوّلات المفتوحة المصدر والمزوّدة بإصدارات من Google نظام إصدار محوّل مكوّن من 4 أرقام، ولكن لا تسمح "VersionInfo" إلا باستخدام 3 أرقام. لحلّ هذه المشكلة، ننصح بدمج آخر رقمَين في إصدار التصحيح، كما هو موضّح أدناه.

@Override
public VersionInfo getVersionInfo() {
  // Get your adapters's version as a string. E.g. "1.2.3.0"
  String versionString = BuildConfig.VERSION_NAME;
  String splits[] = versionString.split("\\.");
  if (splits.length >= 4) {
      int major = Integer.parseInt(splits[0]);
      int minor = Integer.parseInt(splits[1]);
      int micro = Integer.parseInt(splits[2]) * 100 + Integer.parseInt(splits[3]);
      return new VersionInfo(major, minor, micro);
    }

    String logMessage = String.format("Unexpected adapter version format: %s." +
                "Returning 0.0.0 for adapter version.", versionString);
    Log.w(TAG, logMessage);
    return new VersionInfo(0, 0, 0);
}

initialize()

مهلة الانتظار: 30 ثانية

الطريقة initialize() هي الطريقة الأولى التي يتم طلبها في المحوّل. ويتم استدعاؤها مرة واحدة فقط لكل جلسة. توفّر لك هذه الطريقة قائمة بعناصر MediationConfiguration التي تمثّل القائمة الكاملة لمواضع الإعلانات في هذا التطبيق والتي تم ضبطها لشبكتك الإعلانية. يمكنك تكرار هذه القائمة لتحليل بيانات الاعتماد لكل موضع إعلان، وإرسال البيانات ذات الصلة إلى حزمة تطوير البرامج (SDK) لبدء الإعداد.

بعد إعداد حزمة تطوير البرامج (SDK) وتجهيزها لتلقّي طلبات عرض الإعلانات، يمكنك استدعاء الطريقة onInitializationSucceeded() من InitializationCompleteCallback. تتم إعادة توجيه هذه الإشارة إلى ناشري التطبيقات لكي يعرفوا أنّه بإمكانهم البدء بتحميل الإعلانات.

@Override
public void initialize(Context context,
    InitializationCompleteCallback initializationCompleteCallback,
    List<MediationConfiguration> mediationConfigurations) {
  // Initialize your ad network's SDK.
  ...

  // Invoke the InitializationCompleteCallback once initialization completes.
  initializationCompleteCallback.onInitializationSucceeded();
}

collectSignals()

مهلة الانتظار: ثانية واحدة

في كل مرة يطلب فيها الناشر إعلانًا، يتم إنشاء مثيل جديد من RtbAdapter ويتم استدعاء طريقة collectSignals(). سيتم استخدام هذه النسخة من RtbAdapter طوال مدة طلب عرض الإعلان والاستجابة له وعرضه. تتيح طريقة collectSignals() للمحوّل تقديم إشارات من الجهاز ليتم إرسالها إلى مقدّم عرض السعر في طلب OpenRTB.

يتم استدعاء collectSignals() في سلسلة محادثات في الخلفية. Google Mobile Ads SDK (Legacy) يطلب الإشارات من جميع المحوّلات المشاركة في عروض الأسعار في الوقت نفسه. يُرجى احترام ذلك والحد من المكالمات إلى سلسلة واجهة المستخدم خلال هذه الفترة. يجب تنفيذ أي عمل ثقيل يحتاج المحوّل أو حزمة تطوير البرامج (SDK) إلى تنفيذه لجمع الإشارات في طريقة initialize() وتخزينه مؤقتًا.

بعد تجهيز الإشارات، يمكنك استدعاء دالة الاستدعاء onSuccess() باستخدام الإشارات المرمّزة.

في ما يلي مثال على التنفيذ:

@Override
public void collectSignals(RtbSignalData rtbSignalData,
                           SignalCallbacks signalCallbacks) {
  String signals = YourSdk.getSignals();
  signalCallbacks.onSuccess(signals);
}

إذا تعذّر على المحوِّل جمع الإشارات، يمكنك استدعاء signalCallbacks.onFailure() باستخدام سلسلة تشرح الخطأ الذي حدث.

تنفيذ طرق تحميل الإعلانات

مهلة الانتظار: 10 ثوانٍ

إذا عرض مقدِّم عرض السعر عرض السعر الفائز، يتصل Google Mobile Ads SDK (Legacy) بالمحوِّل لتحميل الإعلان الفائز، مع تمرير أي بيانات عرضها مقدِّم عرض السعر الذي تحتاجه حزمة تطوير البرامج (SDK) لتحميل هذا الإعلان.

تعتمد طريقة التحميل الدقيقة التي يتم استدعاؤها على شكل الإعلان الذي يتم تقديم هذا الطلب من أجله:

شكل الإعلان طريقة التحميل
بانر loadBannerAd()
إعلان بيني loadInterstitialAd()
تمت المكافأة loadRewardedAd()

نفِّذ هذه الطرق لأشكال الإعلانات التي يتوافق معها المحوِّل.

يتم استدعاء طريقة التحميل في سلسلة واجهة المستخدم، في مثيل المحوّل نفسه الذي قدّمت منه الإشارات. توفّر لك هذه الطريقة المَعلمات التالية:

  • ‫MediationAdConfiguration، يحتوي على المَعلمات التي تحتاجها حزمة SDK لتحميل الإعلان لعرض السعر الفائز، مثل الاستجابة لعرض السعر وأي بيانات اعتماد ضبطها الناشر في واجهة مستخدم AdMob.

  • كائن MediationAdLoadCallback يُستخدَم لإعلام Google Mobile Ads SDK (Legacy) بنجاح التحميل أو تعذّره

بعد أن تحمّل حزمة SDK الإعلان، يمكنك طلب mediationAdLoadCallback.onSuccess(). في حال تعذّر تحميل الإعلان، يمكنك استدعاء mediationAdLoadCallback.onFailure() مع سلسلة توضّح الخطأ الذي حدث.

تتطلّب طريقة mediationAdLoadCallback.onSuccess() تمرير عنصر يتوافق مع إحدى واجهات "الإعلانات" التي تحدّدها حزمة "SDK لإعلانات Google على الأجهزة الجوّالة". تطلب منك واجهات الإعلانات هذه تقديم بعض المعلومات عن الإعلان.

يحتوي MediationAdConfiguration أيضًا على طريقة getWatermark() لإرجاع سلسلة بترميز base64 تمثّل صورة PNG. يجب أن تكون هذه الصورة مُقسَّمة في تراكب شفاف على إعلاناتك. يمكنك التواصل مع Google للحصول على إرشادات إضافية حول كيفية عرض العلامة المائية. وتحتوي على بيانات وصفية حول الإعلان الذي يتم عرضه ليستخدمها الناشرون في تحديد مصدر الإعلانات المعروضة.

بالنسبة إلى إعلانات البانر، سيُطلب منك تقديم طريقة عرض البانر. بالنسبة إلى "الإعلانات البينية" و"الإعلانات مقابل مكافأة"، سيُطلب منك تنفيذ طريقة show() لعرض الإعلان في وقت لاحق. كأفضل ممارسة، ننصحك بجعل الفئة التي تنفّذ تحميل الإعلان مسؤولة أيضًا عن تنفيذ طرق الإعلان هذه.

في ما يلي نموذج لتنفيذ loadBannerAd(). يُرجى العِلم أنّ تنفيذ المحوّل سيختلف، لأنّ المحوّل يتكامل مع حزمة تطوير برامج (SDK) مختلفة.

public final class SampleRtbAdapter extends RtbAdapter {
  ...

  @Override
  public void loadBannerAd(
      MediationBannerAdConfiguration adConfiguration,
      MediationAdLoadCallback<MediationBannerAd, MediationBannerAdCallback> callback) {

      SampleBannerRenderer bannerRenderer =
          new SampleBannerRenderer(adConfiguration, callback);
      bannerRenderer.render();
    }
}

// Renders a banner ad, and forwards callbacks to Google Mobile Ads SDK (Legacy).
public class SampleBannerRenderer implements MediationBannerAd {
  private MediationBannerAdConfiguration adConfiguration;
  private final MediationAdLoadCallback<MediationBannerAd, MediationBannerAdCallback> adLoadCallback;
  private AdView adView;
  private MediationBannerAdCallback callback;

  public SampleRtbBannerRenderer(
      MediationBannerAdConfiguration adConfiguration,
      MediationAdLoadCallback<MediationBannerAd, MediationBannerAdCallback> adLoadCallback) {
    this.adConfiguration = adConfiguration;
    this.adLoadCallback = adLoadCallback;
  }

  public void render() {
    adView = new AdView(adConfiguration.getContext());
    adView.setAdSize(adConfiguration.getAdSize());
    // serverParameters are the parameters entered in the AdMob UI for your network.
    adView.setAdUnitId(adConfiguration.getServerParameters().getString("adUnitId"));

    // Map the callbacks from your SDK to Google's SDK.
    adView.setAdListener(new AdListener() {
      // See the next step for more information on callback mapping.
      // ...
    });

    // Get the bid response and watermark from the ad configuration and
    // pass the relevant information to your SDK.
    String ad = adConfiguration.getBidResponse();
    String watermark = adConfiguration.getWatermark();
    Bundle extras = new Bundle();
    extras.putString("bid", ad);
    extras.putString("watermark", watermark);
    AdRequest request = new AdRequest.Builder()
        .addNetworkExtrasBundle(AdMobAdapter.class, extras)
        .build();
    adView.loadAd(request);
  }

  // MediationBannerAd implementation

  @NonNull
  @Override
  public View getView() {
    return adView;
  }
}

إرسال أحداث يتم في مراحل نشاط عرض الإعلانات

تتمثّل المسؤولية النهائية للمحوّل في إرسال إشعار إلى Google Mobile Ads SDK (Legacy) بشأن أي حدث يتم في مراحل نشاط العرض، حتى يمكن إعادة توجيهها إلى الناشر. يتوقّع الناشر تلقّي عمليات الاستدعاء هذه في أوقات محدّدة بغض النظر عن شبكة الإعلانات التي تعرض الإعلان، لذا من المهم استدعاء أكبر عدد ممكن من عمليات الاستدعاء هذه وفي الوقت المناسب، حتى يتمكّن Google Mobile Ads SDK (Legacy) من إعادة توجيهها إلى الناشر.

يجب أن تستدعي المحوّلات الأحداث التالية عند الاقتضاء:

ميزات مشتركة بين جميع التنسيقات
الطريقة متى يجب الاتصال؟
reportAdClicked() تم النقر على الإعلان.
reportAdImpression() عرض الإعلان مرّة ظهور.
onAdOpened() عرض الإعلان بملء الشاشة
onAdClosed() تم إغلاق عرض الإعلان بملء الشاشة.
onAdLeftApplication() أدّى الإعلان إلى مغادرة المستخدم للتطبيق.
الإعلانات مقابل مكافأة
onRewarded() يتم منح المستخدم مكافأة.
عمليات معاودة الاتصال بالفيديو (الإعلانات المدمجة مع المحتوى والإعلانات مقابل مكافأة)
onVideoStarted() بدأ فيديو الإعلان.
onVideoCompleted() اكتمل فيديو الإعلان.

يحصل المحوّل على عنصر MediationAdLoadCallback<MediationAdT, MediationAdCallbackT> عند استدعاء mediationAdLoadCallback.onSuccess(). من المتوقّع أن تحتفظ المحوّلات بهذا العنصر وتستخدمه لاستدعاء أحداث العرض التي تحدث في إعلانك.

عادةً ما يتم تشغيل معظم هذه الأحداث من خلال حزمة تطوير البرامج (SDK) لشبكة إعلاناتك. يتمثّل دور المحوّل ببساطة في ربط عمليات الاستدعاء من حزمة تطوير البرامج (SDK) لشبكة الإعلانات بـ Google Mobile Ads SDK (Legacy).

يوضّح المثال التالي كيفية إعادة توجيه عمليات معاودة الاتصال من أداة معالجة الإعلانات في حزمة تطوير البرامج (SDK) إلى Google Mobile Ads SDK (Legacy):

adView.setAdListener(new AdListener() {
    public void onAdLoaded() {
        callback = adLoadCallback.onSuccess(SampleBannerRenderer.this);
    }

    public void onAdImpression() {
        if (callback != null) {
            callback.reportAdImpression();
        }
    }

    public void onAdFailedToLoad(LoadAdError adError) {
        adLoadCallback.onFailure("Error: " + adError.toString());
    }

    public void onAdClosed() {
        if (callback != null) {
            callback.onAdClosed();
        }
    }

    public void onAdOpened() {
        if (callback != null) {
            callback.onAdOpened();
            callback.reportAdClicked();
        }
    }

    public void onAdLeftApplication() {
        if (callback != null) {
            callback.onAdLeftApplication();
        }
    }
});

مواد العرض المطلوبة لتتبُّع مرّات ظهور "الإعلانات المدمجة مع المحتوى"

تسجّل Google Mobile Ads SDK (Legacy) مرّة ظهور لـ "إعلان مدمج مع المحتوى" عندما يكون بكسل واحد من الإعلان مرئيًا. إذا كانت حزمة تطوير البرامج (SDK) لشبكة إعلانات تتطلّب عرض مواد عرض معيّنة من أجل عرض مرّة ظهور صالحة، يمكن لمقدِّم عرض السعر الإشارة إلى مواد العرض المدمجة مع المحتوى المطلوبة هذه في الاستجابة لعرض السعر. بعد ذلك، تتحقّق Google Mobile Ads SDK (Legacy) من عرض مواد العرض المطلوبة للإعلانات المدمجة مع المحتوى قبل تسجيل ظهور الإعلان.

يمكنك الاطّلاع على مستندات مواد العرض المطلوبة للإعلانات المدمجة مع المحتوى للحصول على مزيد من المعلومات حول كيفية تحديد مواد عرض إضافية مطلوبة في الاستجابة لعرض السعر.

عرض أخطاء الإعلانات

بالنسبة إلى أشكال الإعلانات بملء الشاشة، مثل "الإعلانات البينية" و"الإعلانات مقابل مكافأة"، عليك توفير تنفيذ لـ MediationInterstitialAd أو MediationRewardedAd في دالة الاستدعاء لنجاح التحميل، وذلك كي يتمكّن Google Mobile Ads SDK (Legacy) من طلب عرض الإعلان من المحوّل.

يتوقّع Google Mobile Ads SDK (Legacy) أنّه إذا حمّل المحوّل إعلانًا بنجاح، يكون الإعلان جاهزًا للعرض عندما يطلب الناشر عرضه. هذا يعني أنّ كل طلب عرض يجب أن يؤدي إلى ظهور إعلان.

ومع ذلك، قد تكون هناك حالات استثنائية يتعذّر فيها عرض إعلان. إذا لم تتمكّن من عرض الإعلان، يمكنك استدعاء دالة ردّ الاتصال onAdFailedToShow() لإلغاء مرّة الظهور.

يوضّح الجدول أدناه تأثير عمليات معاودة الاتصال للعرض في تسجيل مرات الظهور لأشكال الإعلانات بملء الشاشة:

معاودة الاتصال النتيجة
onAdOpened() Impression recorded
onAdFailedToShow() Impression failure1
لا شيء مما سبق لعدة ثوانٍ Impression recorded

‫1 بالنسبة إلى مرات الظهور التي تعذّر عرضها، لا يتم تحصيل رسوم من شبكة الإعلانات مقابل مرات الظهور، ولكن يؤثر ذلك في تعديل معدل الأحداث القابلة للفوترة. لمزيد من المعلومات، يمكنك الاطّلاع على إشارات طلبات عروض الأسعار.

يوضّح المثال النموذجي التالي دورة حياة التحميل/العرض حيث قد يؤدي طلب عرض الإعلان إلى حدوث خطأ.

final class SampleRtbAdapter extends RtbAdapter implements MediationRewardedAd {

 private MediationRewardedAdCallback callback;
 private RewardedAd rewardedAd;

 ...

  @Override
  public void loadRewardedAd(
      MediationRewardedAdConfiguration adConfiguration,
      final MediationAdLoadCallback<MediationRewardedAd, MediationRewardedAdCallback> loadCallback) {

    // Load an ad. This mock example uses Google's SDK, but in practice
    // your adapter will load the ad using your ad network's SDK.
    RewardedAd.load(adConfiguration.getContext(),
        "ca-app-pub-3940256099942544/5224354917",
        new AdRequest.Builder().build(),
        new RewardedAdLoadCallback() {
          @Override
          public void onAdLoaded(@NonNull RewardedAd rewardedAd) {
            // When the ad loads, invoke the load success callback.
            callback = loadCallback.onSuccess(SampleRtbAdapter.this);
          }
        });
  }

  @Override
  public void showAd(Context context) {
    // In this mock example, your ad network requires an activity context, but
    // didn't receive one, making you unable to show the ad.
    if (!(context instanceof Activity)) {
      AdError error = new AdError(1, "Context must be an activity",
          "com.google.ads.mediation.sample");
      callback.onAdFailedToShow(error);
    }

    // This example shows Google SDK's callbacks, but it's likely your SDK
    // has similar presentation callbacks.
    rewardedAd.setFullScreenContentCallback(new FullScreenContentCallback() {
      @Override
      public void onAdShowedFullScreenContent() {
        // Your ad network SDK successfully showed the ad. Call onAdOpened().
        callback.onAdOpened();
      }

      @Override
      public void onAdFailedToShowFullScreenContent(AdError adError) {
        // Your ad network SDK failed to show the ad, invoke onAdFailedToShow.
        // In practice, you will map your SDK's error to an AdError.
        AdError error = new AdError(adError.getCode(), adError.getMessage(),
            adError.getDomain());
        callback.onAdFailedToShow(adError);
      }
    });


    rewardedAd.show((Activity) context, ...);
  }
}