Оптимизация eCPM для межстраничных объявлений в мобильных приложениях

Оптимизация eCPM для межстраничных объявлений в мобильных приложениях

7 февраля 2023 г.

У меня есть кроссплатформенное мобильное приложение, опубликованное в Google Play и Apple App Store. Для монетизации я использую полноэкранные рекламные блоки (интерститиалы) от рекламных провайдеров AdMob и Яндекс. На уровне приложения я контролирую, как часто я хочу показывать рекламу.

Например, я показываю его при переходе с одного экрана на другой, но не чаще, чем раз в N (например, 3-6) минут. Итак, при переходе с одного экрана на другой мы отслеживаем, сколько минут/секунд прошло с момента последнего показа, и если оно превышает N минут, я показываю рекламу, если она в данный момент загружена и мне есть что отображать.

Интеграция с поставщиками рекламы

Я не буду обсуждать технические вопросы интеграции, вы можете прочитать инструкции на официальных сайтах: Admob, < a href="https://yandex.ru/support/partner/inapp/integration.html">Яндекс.

Вы должны понимать, что для показа рекламы вашему приложению необходимо отправить запрос провайдеру, и через некоторое время провайдер уведомит вас об успешном или неудачном его получении в вашем приложении. Во втором случае вы можете отправлять повторные запросы, пока результат не будет успешным. Каждый запрос связан с идентификатором конкретного рекламного блока. Таким образом, в течение N минут мы периодически отправляем запросы к провайдерам (например, по таймеру или какому-то другому событию), пока не получим ответ об успешной загрузке рекламы. И когда наступает подходящий момент, показываем рекламу.

Важно подчеркнуть, что мы будем отправлять запросы на загрузку рекламы одновременно всем провайдерам и показывать только одну из загруженных реклам в соответствии с установленным нами приоритетом провайдеров (в моем случае это определяется порядком их следования в списке). массив провайдеров: чем ниже индекс провайдера, тем выше его приоритет).

Каждому межстраничному рекламному блоку можно задать минимальный порог eCPM или полагаться на оптимизацию самой рекламной сети. Что такое эффективная цена за тысячу показов, можно прочитать на странице support.google.com.

Ниже приведены скриншоты из панели управления, демонстрирующие внешний вид настройки эффективной цены за тысячу показов.

eCPM settings from Admob console

eCPM settings from Yandex console

Мы настроим в нашем приложении несколько межстраничных рекламных блоков с разной eCPM для каждого рекламного провайдера: один из них (назовем его Default) оставим с оптимизацией на уровне провайдера, а для остальных установим разные значения и придадим им смысл имена.

eCPM settings for interstitial Ad units from Yandex ads console

eCPM settings for interstitial Ad units from Admob console

На скриншоте консоли Admob этого не видно, но блоки eCPM настроены следующим образом:

| Рекламный блок | эффективная цена за тысячу показов | |----|----| | JCross-дроид-по умолчанию | Оптимизировано Google (Все цены) | | JCross-дроид-средний | Глобальный пол $ 1,00 | | JCross-дроид-высокий | Глобальная минимальная цена 2,50 доллара США |

Решение

Таким образом, наша задача оптимизации состоит в том, чтобы попытаться загрузить объявление с максимально возможной эффективной ценой за тысячу показов в течение N минут (т. е. от предыдущего времени показа до желаемого следующего времени показа).

Разделите временной интервал N минут на 3 неравных сегмента: High, Medium, Default. Сформулируйте алгоритм формирования запросов объявлений для одного провайдера:

  1. В первый отрезок времени мы отправляем запросы объявлений для рекламного блока Высокий (зеленый). Если нам удалось загрузить объявление за это время, перейдите к шагу 5.
  2. Если нам не удалось загрузить рекламу в сегменте Высокий, измените идентификатор рекламного блока на Средний и сформируйте для него запросы (желтый). Если нам удалось загрузить объявление за это время, перейдите к шагу 5.
  3. Если нам не удалось загрузить объявление во время сегмента Средний, измените идентификатор рекламного блока на По умолчанию и сформируйте для него запросы (синий). Если нам удалось загрузить объявление за это время, перейдите к шагу 5. Если нет, перейдите к шагу 4.
  4. Если нам не удалось загрузить объявление в момент N, продолжайте запрашивать рекламный блок по умолчанию, пока мы не получим успешный результат.
  5. Прекратите формировать запросы и дождитесь момента N, чтобы показать рекламу.

Splitted time interval

Как только реклама была показана в определенный момент, мы повторяем наш алгоритм с первого шага, чтобы получить рекламу для следующего показа.

Анализ эффективности

Я создам отчеты за последние 30 дней и сравню показатели эффективной цены за тысячу показов. Очевидно, что результирующая эффективная цена за тысячу показов (отмечена зеленым цветом) значительно превышает эффективную цену за тысячу показов по умолчанию (отмечена оранжевым цветом).

Admob Android

Admob iOS

Yandex Android

Yandex iOS

Реализация

Мое приложение написано на C++ с использованием моего SDK с открытым исходным кодом, который, в свою очередь, использует под капотом SDL2. Каталог, содержащий логику работы с рекламой, находится по адресу framework/ads.

Если вы хотите углубиться в реализацию, на упрощенных схемах ниже описаны основные объекты и их отношения:

Diagram 1

  1. Абстрактный класс Provider служит для описания интерфейса поставщика рекламы.
  2. AdmobAds и YandexAds реализуют этот интерфейс.
  3. Нам нужен класс ProviderCallback, который предназначен для передачи событий от провайдера к менеджеру. У каждого провайдера есть ссылка на объект класса ProviderCallback.
  4. Manager реализует интерфейс класса ProviderCallback и содержит список провайдеров (указателей на Provider).

Diagram 2

При инициализации приложения необходимо создать провайдеров и привязать их к Менеджеру:

adsMgr->SetIntersitialShowDelay(5 * 60); // N = 5 min between ad show
std::string InterstitialBlockID;

if (auto adMob = ads::AdMob::createProvider(adsMgr, ads::Format::Interstitial)) {
    GetAdMobAdIdentifier(InterstitialBlockID, 0);
    adMob->addInterstitialUnit(InterstitialBlockID, 20); // default

    GetAdMobAdIdentifier(InterstitialBlockID, 1);
    adMob->addInterstitialUnit(InterstitialBlockID, 60); // medium

    GetAdMobAdIdentifier(InterstitialBlockID, 2);
    adMob->addInterstitialUnit(InterstitialBlockID, 120); // high

    adsMgr->addProvider(adMob);
}

if (auto yandex = ads::Yandex::createProvider(adsMgr, ads::Format::Interstitial)) {
    GetYandexAdIdentifier(InterstitialBlockID, 0);
    yandex->addInterstitialUnit(InterstitialBlockID, 20); // default

    GetYandexAdIdentifier(InterstitialBlockID, 1);
    yandex->addInterstitialUnit(InterstitialBlockID, 60); // medium

    GetYandexAdIdentifier(InterstitialBlockID, 2);
    yandex->addInterstitialUnit(InterstitialBlockID, 120); // high

    adsMgr->addProvider(yandex);
}

Второй параметр функции addInterstitialUnit означает отметку времени (в секундах) начала сегмента относительно момента N. Для Самого высокого рекламного блока этот параметр игнорируется, а Самый высокий рекламный блок Рекламный блок всегда устанавливается немедленно, независимо от значения параметра.

Splitted time interval

При каком-то событии (например, таймере) должна быть вызвана функция tryLoadInterstitial, которая инициирует запрос на загрузку рекламы, если она еще не загружена.:

adsMgr->tryLoadInterstitial();

Затем, когда придет время, нужно будет вызвать метод показа рекламы:

adsMgr->showInterstitialIfAvailable();

Спасибо за внимание!


Оригинал
PREVIOUS ARTICLE
NEXT ARTICLE