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

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

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

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

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

الإعداد

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

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

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

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

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

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

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

لإنشاء مُحوّل عروض أسعار لـ Google Mobile Ads SDK، يجب توسيع الفئة المجرّدة 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 تطلب في الوقت نفسه إشارات من جميع المحوّلات المشارِكة في عروض الأسعار. يُرجى عدم استدعاء سلسلة واجهة المستخدم خلال هذا الوقت. يجب إجراء أي عمل مكثّف يحتاج إليه المحوّل أو حزمة تطوير البرامج (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 المحوّل لتحميل الإعلان الفائز، مع تمرير أي بيانات ردّ عليها مقدّم عروض الأسعار وتحتاج إليها حزمة تطوير البرامج (SDK) لتحميل هذا الإعلان.

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

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

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

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

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

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

بعد أن تحمّل حزمة تطوير البرامج (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.
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 بأي أحداث دورة عرض، حتى يمكن إعادة توجيهها إلى الناشر. يتوقّع الناشر معاودات الاتصال هذه في أوقات محدّدة بغض النظر عن شبكة الإعلانات التي تعرض الإعلان، لذا من المهم استدعاء أكبر عدد ممكن من معاودات الاتصال هذه في الوقت المناسب، حتى تتمكّن Google Mobile Ads SDK من إعادة توجيهها إلى الناشر.

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

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

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

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

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

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 تسجِّل مرّة ظهور لإعلان مدمج مع المحتوى عندما يكون جزء من الإعلان مرئيًا، حتى لو كان جزءًا صغيرًا جدًا (1 بكسل). إذا كانت حزمة تطوير البرامج (SDK) التابعة لشبكة الإعلانات تتطلّب عرض مواد عرض معيّنة لتسجيل مرّة ظهور صالحة، يمكن لمقدّم عروض الأسعار الإشارة إلى مواد العرض المدمجة مع المحتوى المطلوبة هذه في الاستجابة لعرض السعر. بعد ذلك، تتحقّق Google Mobile Ads SDKمن عرض مواد العرض المدمجة مع المحتوى المطلوبة قبل تسجيل مرّة ظهور.

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

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

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

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

ومع ذلك، قد تكون هناك حالات يتعذّر فيها عرض إعلان. إذا تعذّر عرض الإعلان، يتم استدعاء 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, ...);
  }
}