ساخت APK رایگان

API پل جاوااسکریپت

تبلیغات

نمایش تبلیغ میان‌صفحه‌ای یا پاداشی با اشارهٔ خودتان، و اطلاع دادن به پوسته که ناوبری کی شروع و کی تمام می‌شود تا آن را قطع نکند.

AppMintAds.appOpen کمک‌کننده#

window.AppMintAds.appOpen.setEnabled(on)

نمونه

تبلیغ باز شدن اپلیکیشن را متوقف یا از سر می‌گیرد؛ تبلیغ تمام‌صفحه‌ای که هنگام راه‌اندازی و بازگشت کاربر از اپلیکیشن دیگر نمایش داده می‌شود.

مقدار بازگشتی: هیچ. نیازها: کنترل تبلیغات ← کنترل‌شده توسط توسعه‌دهنده و شناسهٔ واحد تبلیغ باز شدن اپلیکیشن.

وقتی کاربر عمداً برای لحظه‌ای کوتاه از اپلیکیشن بیرون می‌رود (اپلیکیشن پرداخت، دوربین، منوی اشتراک‌گذاری)، آن را متوقف کنید تا با بازگشت او تبلیغی نمایش داده نشود:

var ads = window.AppMintAds;

async function payWithUpi(link) {
  if (ads) ads.appOpen.setEnabled(false);
  try {
    await openPaymentApp(link);           // your own code; the user switches apps and returns
  } finally {
    if (ads) ads.appOpen.setEnabled(true);
  }
}

بررسی کنید که ساخت اصلاً واحد تبلیغ باز شدن اپلیکیشن دارد یا نه:

var hasAppOpen = !!(window.AppMintAds && window.AppMintAds.config().formats.app_open);

وقتی کاربر عکسی انتخاب می‌کند آن را متوقف کنید، چون انتخاب‌گر عکس سیستم او را لحظه‌ای از اپلیکیشن بیرون می‌برد:

var ads = window.AppMintAds;
var input = document.getElementById('photo-input');   // <input type="file" accept="image/*" hidden>
var pausedForPicker = false;

document.getElementById('pick-photo').addEventListener('click', function () {
  if (ads) { ads.appOpen.setEnabled(false); pausedForPicker = true; }
  input.click();
});

input.addEventListener('change', function () {
  if (input.files[0]) uploadPhoto(input.files[0]);      // your own code
});

// Back in the app (a photo was picked or the picker was cancelled): turn it on again.
document.addEventListener('visibilitychange', function () {
  if (document.hidden || !pausedForPicker) return;
  pausedForPicker = false;
  setTimeout(function () { ads.appOpen.setEnabled(true); }, 1000);
});

نکته‌ها: به‌طور پیش‌فرض روشن است. در راه‌اندازی سرد، تبلیغ وقتی صفحه آماده است یا وقتی ظرف ۱۵ ثانیه بارگذاری‌اش تمام شود نمایش داده می‌شود؛ بارگذاری‌ای که دیرتر برسد برای دفعهٔ بعد نگه داشته می‌شود. تبلیغ باز شدن اپلیکیشن قدیمی‌تر از ۴ ساعت هرگز نمایش داده نمی‌شود. می‌توانید خودتان هم یکی را نمایش دهید با AppMintAds.show('app_open').

AppMintAds.banner کمک‌کننده#

window.AppMintAds.banner.attach(target, opts) / .detach(slotOrElement)

نمونه

یک بنر یا تبلیغ مستطیل متوسط ۳۰۰×۲۵۰ را در هر جای صفحه‌تان، روی عنصری که انتخاب می‌کنید، قرار می‌دهد.

مقدار بازگشتی: attach پس از بارگذاری تبلیغ یک Promise از {ok:true, slot, width, height} (پیکسل CSS) برمی‌گرداند، یا {ok:false, slot?, code, message?}. detach چیزی برنمی‌گرداند. نیازها: کنترل تبلیغات ← کنترل‌شده توسط توسعه‌دهنده و شناسهٔ واحد تبلیغ بنر (یا مستطیل متوسط).

این عنصر فقط فضا را رزرو می‌کند. تبلیغ روی آن کشیده می‌شود و با اسکرول یا تغییر اندازهٔ صفحه آن را دنبال می‌کند:

<div id="ad-slot"></div>

<script>
var ads = window.AppMintAds;
var slotEl = document.getElementById('ad-slot');

if (ads) {
  ads.banner.attach(slotEl, { size: 'banner' }).then(function (res) {
    // On success the helper sets slotEl.style.minHeight to res.height (pass keepHeight:true to stop that).
    if (!res.ok) {                         // no_fill, network, too_many_slots, ...
      if (res.slot) ads.banner.detach(res.slot);   // a failed slot still counts toward the limit of two
      slotEl.hidden = true;
    }
  });
} else {
  slotEl.hidden = true;                    // browser: no ads here
}
</script>

مستطیل متوسط (هر بار یکی) و برداشتن دوبارهٔ یک بنر:

var box = document.querySelector('.article-end-ad');
var mrecSlot = null;

if (window.AppMintAds) {
  window.AppMintAds.banner.attach(box, { size: 'medium_rectangle' }).then(function (res) {
    if (res.ok) mrecSlot = res.slot;
    else { if (res.slot) window.AppMintAds.banner.detach(res.slot); box.hidden = true; }
  });
}

function leaveArticle() {
  if (window.AppMintAds && mrecSlot) window.AppMintAds.banner.detach(mrecSlot);   // or detach(box)
  mrecSlot = null;
}

وقتی تبلیغی در دسترس نبود، جایگاه را بعداً دوباره امتحان کنید و ابتدا جایگاه ناموفق را آزاد کنید تا یکی از آن دو را مصرف نکند:

function fillSlot(el, triesLeft) {
  var ads = window.AppMintAds;
  if (!ads) { el.hidden = true; return; }             // browser: no ads here
  ads.banner.attach(el, { size: 'banner' }).then(function (res) {
    if (res.ok) return;
    if (res.slot) ads.banner.detach(res.slot);
    if ((res.code === 'no_fill' || res.code === 'network') && triesLeft > 0) {
      setTimeout(function () { fillSlot(el, triesLeft - 1); }, 60000);
    } else {
      el.hidden = true;                                 // ad_free, disabled, consent, ...
    }
  });
}

fillSlot(document.getElementById('footer-ad'), 2);

نکته‌ها: target یک عنصر یا انتخاب‌گر CSS است؛ size برابر 'banner' (پیش‌فرض، عرض تطبیقی، حداکثر ۹۰ dp ارتفاع)، 'medium_rectangle' یا 'mrec' است. حداکثر دو جایگاه هم‌زمان، و جایگاهی که بارگذاری تبلیغش شکست خورده تا وقتی جدایش نکنید همچنان حساب می‌شود. detach به عنصر یا شناسهٔ جایگاهی که attach برگردانده نیاز دارد، نه یک انتخاب‌گر. برداشتن عنصر از DOM هم آن را جدا می‌کند. کدها: no_element, duplicate_slot, too_many_slots, detached, no_fill, network, invalid_unit, ad_free, disabled, consent, automatic_mode, internal.

AppMintAds.config کمک‌کننده#

window.AppMintAds.config()

نمونه

به صفحه می‌گوید ساخت از کدام حالت کنترل تبلیغات استفاده می‌کند و چه قالب‌های تبلیغی را می‌تواند ارائه دهد.

مقدار بازگشتی: یک شیء، همگام: {control: 'automatic' | 'developer', formats: {banner, mrec, interstitial, rewarded, rewarded_interstitial, app_open}} (هر قالب true / false). در خطای داخلی {control:'automatic', formats:{}} برمی‌گرداند. نیازها: هیچ؛ window.AppMintAds فقط درون اپلیکیشن نصب‌شده وجود دارد.

فقط رابط تبلیغی را نشان دهید که این ساخت واقعاً می‌تواند ارائه دهد:

var ads = window.AppMintAds;               // undefined in a browser
var cfg = ads ? ads.config() : null;

var developer = !!(cfg && cfg.control === 'developer');
document.getElementById('watch-ad').hidden = !(developer && cfg.formats.rewarded);
document.getElementById('ad-slot').hidden  = !(developer && cfg.formats.banner);

قالب پاداشی‌ای را که ساخت برای دکمهٔ «پاداش» دارد انتخاب کنید و اگر هیچ‌کدام را ندارد دکمه را پنهان کنید:

var ads = window.AppMintAds;
var cfg = ads ? ads.config() : null;
var bonusBtn = document.getElementById('bonus');

var bonusType = null;
if (cfg && cfg.control === 'developer') {
  if (cfg.formats.rewarded) bonusType = 'rewarded';
  else if (cfg.formats.rewarded_interstitial) bonusType = 'rewarded_interstitial';
}
bonusBtn.hidden = !bonusType;

bonusBtn.addEventListener('click', async function () {
  var res = await ads.show(bonusType);                  // inside the tap: plays at once
  if (res.earned) addCoins(res.reward.amount);
});

اندازهٔ تبلیغ پایان مقاله را انتخاب کنید: اگر ساخت مستطیل متوسط دارد همان، وگرنه بنر:

var ads = window.AppMintAds;
var cfg = ads ? ads.config() : null;
var box = document.getElementById('article-end-ad');

var size = null;
if (cfg && cfg.control === 'developer') {
  size = cfg.formats.mrec ? 'medium_rectangle' : (cfg.formats.banner ? 'banner' : null);
}

if (!size) box.hidden = true;
else ads.banner.attach(box, { size: size }).then(function (res) {
  if (!res.ok) { if (res.slot) ads.banner.detach(res.slot); box.hidden = true; }
});

نکته‌ها: وقتی تبلیغات روشن باشند و ساخت برای یک قالب شناسهٔ واحد تبلیغ داشته باشد، آن قالب true است. در حالت خودکار (control: 'automatic') هر فراخوانی load / show / banner.attach با code: 'automatic_mode' پاسخ می‌دهد؛ در آنجا از WebToApk.showRewardedAd() / showInterstitialAd() استفاده کنید. برای کنترل تبلیغات از صفحه، در جادوگر ساخت کنترل تبلیغات ← کنترل‌شده توسط توسعه‌دهنده را انتخاب کنید.

AppMintAds.isReady کمک‌کننده#

window.AppMintAds.isReady(type)

نمونه

می‌گوید آیا یک تبلیغ تمام‌صفحه از این نوع بارگذاری شده و همین حالا قابل نمایش است.

مقدار بازگشتی: true / false، همگام. type: 'interstitial'، 'rewarded'، 'rewarded_interstitial' یا 'app_open'. نیازها: کنترل تبلیغات ← کنترل‌شده توسط توسعه‌دهنده و شناسهٔ واحد تبلیغ برای آن نوع.

با رویداد وضعیت appmint:ad، دکمهٔ «تماشای تبلیغ» را با تبلیغ هماهنگ نگه دارید:

var ads = window.AppMintAds;
var btn = document.getElementById('watch-ad');

function refresh() { btn.disabled = !(ads && ads.isReady('rewarded')); }

if (ads) {
  refresh();
  window.addEventListener('appmint:ad', function (e) {
    if (e.detail.type === 'rewarded') refresh();    // phases: loaded, failed, closed, ...
  });
} else {
  btn.hidden = true;                                // browser: no ads here
}

«سکه‌هایتان را دو برابر کنید» را در صفحهٔ نتایج فقط وقتی پیشنهاد دهید که یک تبلیغ پاداشی از قبل منتظر است:

function showResults(coins) {
  var ads = window.AppMintAds;
  var offer = document.getElementById('double-coins');
  renderResults(coins);                                 // your own screen
  offer.hidden = !(ads && ads.isReady('rewarded'));
  offer.onclick = async function () {
    offer.hidden = true;
    var res = await ads.show('rewarded');               // inside the tap: plays at once
    addCoins(res.earned ? coins : 0);                   // the bonus: the same amount again
  };
}

در یک دکمهٔ راهنما، هر قالب پاداشی‌ای را که همین حالا بارگذاری شده پخش کنید:

document.getElementById('hint').addEventListener('click', async function () {
  var ads = window.AppMintAds;
  if (!ads) return;                                     // browser: no ads here
  var type = ads.isReady('rewarded') ? 'rewarded'
           : ads.isReady('rewarded_interstitial') ? 'rewarded_interstitial'
           : null;
  if (!type) { showMessage('No hint video right now. Try again in a minute.'); return; }
  var res = await ads.show(type);
  if (res.earned) revealHint();
});

نکته‌ها: banner و mrec همیشه با false پاسخ می‌دهند (آن‌ها متصل می‌شوند، نمایش داده نمی‌شوند). تبلیغ میان‌صفحه‌ای در خنک‌شدن ۶۰ ثانیه‌ای با false پاسخ می‌دهد؛ تبلیغ باز شدن اپلیکیشن قدیمی‌تر از ۴ ساعت با false. در حالت خودکار این همیشه false.

AppMintAds.load کمک‌کننده#

window.AppMintAds.load(type)

نمونه

یک تبلیغ تمام‌صفحه را بارگذاری می‌کند تا show(type) بعدی بتواند فوراً آن را پخش کند.

مقدار بازگشتی: یک Promise که (هرگز reject نمی‌شود) با {ok:true} تکمیل می‌شود، {ok:true, cached:true} وقتی یکی از قبل منتظر است، یا {ok:false, code, reason, message?, adCode?}. نیازها: کنترل تبلیغات ← کنترل‌شده توسط توسعه‌دهنده و شناسهٔ واحد تبلیغ برای آن نوع (interstitial, rewarded, rewarded_interstitial, app_open).

var ads = window.AppMintAds;
var btn = document.getElementById('watch-ad');
btn.disabled = true;

async function prepareRewarded() {
  if (!ads) { btn.hidden = true; return; }          // browser: no ads
  var res = await ads.load('rewarded');
  if (res.ok) { btn.disabled = false; return; }
  if (res.code === 'no_fill' || res.code === 'network') setTimeout(prepareRewarded, 30000);
  else console.log('rewarded ad unavailable:', res.code, res.message);
}
prepareRewarded();

تمام عمر هر درخواست روی رویداد appmint:ad هم جریان می‌یابد:

window.addEventListener('appmint:ad', function (e) {
  var a = e.detail;   // {type, phase, slot?, code?, adCode?, message?, width?, height?, reward?, earned?}
  // phase: loading, loaded, failed, opened, impression, clicked, closed, rewarded, show_failed, opt_in, declined
  if (a.phase === 'failed') console.log(a.type, 'failed to load:', a.code, a.adCode, a.message);
});
// The same object also goes to window.onAppMintAd, if you define that function.
window.onAppMintAd = function (a) { console.log('ad', a.type, a.phase); };

تبلیغ میان‌صفحه‌ای را وقتی مرحله شروع می‌شود بارگذاری کنید تا وقتی مرحله تمام می‌شود آماده باشد، و وقتی کاربر تبلیغات را حذف کرد درخواست را متوقف کنید:

var ads = window.AppMintAds;
var interstitialsOff = false;

async function startLevel(n) {
  runLevel(n);                                          // your own game
  if (!ads || interstitialsOff) return;
  var res = await ads.load('interstitial');
  if (!res.ok && (res.code === 'ad_free' || res.code === 'disabled' || res.code === 'automatic_mode')) {
    interstitialsOff = true;                            // no interstitials in this app session
  }
}

async function levelEnded() {
  if (ads && !interstitialsOff && ads.isReady('interstitial')) await ads.show('interstitial');
  showLevelSummary();
}

نکته‌ها: کدها: no_fill، network، invalid_unit، internal (از AdMob)، automatic_mode، unknown_type، ad_free، disabled، consent و use_slot برای banner / mrec (از AppMintAds.banner.attach استفاده کنید). اپلیکیشن همین حالا هر نوع تمام‌صفحه‌ای را که شناسهٔ واحد دارد از پیش بارگذاری می‌کند و پس از هر نمایش، بعدی را بارگذاری می‌کند؛ بنابراین load بیشتر برای دانستن زمانی است که می‌توان دکمه را فعال کرد.

AppMintAds.show کمک‌کننده#

window.AppMintAds.show(type)

نمونه

یک تبلیغ تمام‌صفحهٔ بارگذاری‌شده را نمایش می‌دهد: interstitial، rewarded، rewarded_interstitial یا app_open.

مقدار بازگشتی: یک Promise که (هرگز reject نمی‌شود) وقتی تبلیغ بسته شد تکمیل می‌شود: {ok:true, shown:true, earned, reward?} (reward = {type, amount} برای قالب‌های پاداشی)، یا {ok:false, shown:false, code, reason, message?} وقتی چیزی نمایش داده نشد. نیازها: کنترل تبلیغات ← کنترل‌شده توسط توسعه‌دهنده و شناسهٔ واحد تبلیغ برای آن نوع.

پاداشی: آن را درون لمس خود کاربر فراخوانی کنید. آن لمس موافقت کاربر است، پس تبلیغ فوراً پخش می‌شود. فقط وقتی earned درست باشد پاداش بدهید:

var ads = window.AppMintAds;

document.getElementById('watch-ad').addEventListener('click', async function () {
  if (!ads) return;                                  // browser: no ads here
  var res = await ads.show('rewarded');
  if (res.earned) addCoins(res.reward.amount);
  else if (res.reason === 'ad_free') addCoins(50);   // user paid to remove ads: reward anyway
  else if (res.shown) showMessage('Watch to the end to get the reward.');
  else if (res.reason !== 'declined') showMessage('No ad available right now.');
});

تبلیغ میان‌صفحه‌ای: در یک وقفهٔ طبیعی. با هر پاسخی ادامه دهید:

async function levelFinished() {
  if (window.AppMintAds && window.AppMintAds.isReady('interstitial')) {
    await window.AppMintAds.show('interstitial');    // resolves when the ad closes
  }
  showNextLevel();
}

میان‌صفحه‌ای پاداشی پشت صفحهٔ معرفی خودتان با یک «نه، ممنون» روشن. لمس «تماشا» همان موافقت است:

var ads = window.AppMintAds;
var intro = document.getElementById('free-life-intro');   // your own dialog: Watch / No thanks

function offerFreeLife() {
  if (ads && ads.isReady('rewarded_interstitial')) intro.hidden = false;
  else gameOver();
}

document.getElementById('free-life-watch').addEventListener('click', async function () {
  intro.hidden = true;
  var res = await ads.show('rewarded_interstitial');
  if (res.earned) continueWithExtraLife();
  else gameOver();
});

document.getElementById('free-life-skip').addEventListener('click', function () {
  intro.hidden = true;
  gameOver();
});

نکته‌ها: یک show() پاداشی یا میان‌صفحه‌ای پاداشی که از لمس کاربر نیامده باشد (تایمر، بارگذاری صفحه، تغییر مسیر) ابتدا صفحهٔ «تبلیغ ببینید؟ / نه، ممنون» را نشان می‌دهد و «نه، ممنون» با declined پاسخ داده می‌شود. هرگز قالب‌های پاداشی را این‌طور راه‌اندازی نکنید. کدهای دیگر: automatic_mode، unknown_type، ad_free، disabled، consent، not_full_screen، showing، cooldown (۶۰ ثانیه بین تبلیغ‌های میان‌صفحه‌ای)، not_loaded (بارگذاری جدید برای دفعهٔ بعد شروع می‌شود)، show_failed، internal. در حالت خودکار از WebToApk.showRewardedAd().

adsAppOpenEnable پل#

window.WebToApk.adsAppOpenEnable(enabled: Boolean)

به صفحه اجازه می‌دهد هنگام بازگشت از اپلیکیشن دیگر، تبلیغ باز شدن اپلیکیشن را متوقف/از سر بگیرد (وقتی یک واحد تنظیم شده باشد، به‌طور پیش‌فرض روشن است).

نمونه

نیمهٔ بومی AppMintAds.appOpen.setEnabled(on): تبلیغ باز شدن اپلیکیشن را متوقف یا از سر می‌گیرد. صفحه‌ها از AppMintAds.appOpen.setEnabled.

مقدار بازگشتی: هیچ. نیازها: کنترل تبلیغات ← کنترل‌شده توسط توسعه‌دهنده و شناسهٔ واحد تبلیغ باز شدن اپلیکیشن.

function setAppOpenAds(on) {
  if (window.AppMintAds) window.AppMintAds.appOpen.setEnabled(on);
}

// Pause while the user is in the middle of something, resume afterwards.
function startCheckout() { setAppOpenAds(false); showCheckout(); }
function checkoutDone()  { setAppOpenAds(true); }

انتخاب عکس اپلیکیشن را برای انتخاب‌گر سیستم ترک می‌کند و بازگشت به‌عنوان یک برگشت شمرده می‌شود. تبلیغ باز شدن اپلیکیشن را در اطراف آن متوقف کنید:

var input = document.getElementById('photo');

function appOpenAds(on) {
  if (window.AppMintAds) window.AppMintAds.appOpen.setEnabled(on);
}

input.addEventListener('click', function () { appOpenAds(false); });
function pickerDone() { setTimeout(function () { appOpenAds(true); }, 1000); }
input.addEventListener('change', pickerDone);
input.addEventListener('cancel', pickerDone);

اعضای طرح پولی خودتان هرگز آن را نمی‌بینند. این کلید ذخیره نمی‌شود، پس در هر راه‌اندازی زود تنظیمش کنید:

// Runs from a <head> script: window.AppMintAds is already there at document start.
var plan = null;
try { plan = localStorage.getItem('plan'); } catch (e) {}

if (window.AppMintAds && plan === 'pro') {
  window.AppMintAds.appOpen.setEnabled(false);
}

نکته‌ها: امضای خام adsAppOpenEnable(enabled). وقتی یک واحد تبلیغ باز شدن اپلیکیشن تنظیم شده باشد، به‌طور پیش‌فرض روشن است. تبلیغ باز شدن اپلیکیشن در راه‌اندازی سرد (اگر ظرف ۱۵ ثانیه بارگذاری شود) و وقتی کاربر از اپلیکیشن دیگری برمی‌گردد نمایش داده می‌شود؛ تبلیغ قدیمی‌تر از ۴ ساعت هرگز نمایش داده نمی‌شود.

adsConfig پل#

window.WebToApk.adsConfig(): String

`{control, formats:{banner, mrec, interstitial, rewarded, rewarded_interstitial, app_open}}` - قالب‌های تبلیغی که این ساخت می‌تواند ارائه دهد.

نمونه

می‌خواند این ساخت چه قالب‌های تبلیغی را ارائه می‌دهد و از کدام حالت کنترل تبلیغات استفاده می‌کند. صفحه‌ها معمولاً AppMintAds.config() را فراخوانی می‌کنند که این را برایتان تجزیه می‌کند.

مقدار بازگشتی: یک رشتهٔ JSON: {"control":"automatic"|"developer","formats":{"banner":bool,"mrec":bool,"interstitial":bool,"rewarded":bool,"rewarded_interstitial":bool,"app_open":bool}}. وقتی تبلیغات روشن باشند و ساخت برای یک قالب شناسهٔ واحد تبلیغ داشته باشد، آن قالب true است. نیازها: هیچ.

ابتدا API عمومی:

if (window.AppMintAds) {
  var cfg = window.AppMintAds.config();      // already parsed; {control:'automatic', formats:{}} on error
  if (cfg.control === 'developer' && cfg.formats.rewarded) {
    document.getElementById('watch-ad').hidden = false;
  }
}

فراخوانی خام، اگر استفاده نمی‌کنید از AppMintAds:

var b = window.WebToApk;
if (b && typeof b.adsConfig === 'function') {
  try {
    var cfg = JSON.parse(b.adsConfig());
    console.log(cfg.control, cfg.formats);
  } catch (e) { console.log('could not read ad config', e); }
}

فضا را فقط برای قالب‌هایی رزرو کنید که این ساخت واقعاً دارد و در غیر این صورت کادر خالی را به صفحه پس بدهید:

var box = document.getElementById('sidebar-ad');
var cfg = window.AppMintAds ? window.AppMintAds.config() : { control: 'automatic', formats: {} };

if (cfg.control === 'developer' && cfg.formats.mrec) {
  window.AppMintAds.banner.attach(box, { size: 'mrec' });
} else if (cfg.control === 'developer' && cfg.formats.banner) {
  window.AppMintAds.banner.attach(box, { size: 'banner' });
} else {
  box.remove();                                   // browser, Automatic mode, or no unit: no empty gap
}

نکته‌ها: در حالت خودکار formats هنوز می‌گوید کدام واحدها وجود دارند، اما AppMintAds.load/show با code: 'automatic_mode' پاسخ می‌دهند؛ در آنجا از WebToApk.showRewardedAd() / showInterstitialAd() استفاده کنید.

adsIsReady پل#

window.WebToApk.adsIsReady(type: String): Boolean

درست است وقتی یک [type] تمام‌صفحه بارگذاری شده و همین حالا قابل نمایش است.

نمونه

می‌گوید آیا یک تبلیغ تمام‌صفحه از یک نوع بارگذاری شده و همین حالا قابل نمایش است (تبلیغات کنترل‌شده توسط توسعه‌دهنده). صفحه‌ها معمولاً AppMintAds.isReady(type).

مقدار بازگشتی: true / false، همگام. type برابر 'interstitial'، 'rewarded'، 'rewarded_interstitial' یا 'app_open' است؛ 'banner' / 'mrec' همیشه با false پاسخ می‌دهند. نیازها: کنترل تبلیغات ← کنترل‌شده توسط توسعه‌دهنده و شناسهٔ واحد تبلیغ برای آن نوع.

ابتدا API عمومی:

var watchBtn = document.getElementById('watch-ad');
function refresh() {
  watchBtn.disabled = !(window.AppMintAds && window.AppMintAds.isReady('rewarded'));
}
refresh();
window.addEventListener('appmint:ad', refresh);     // loaded / closed / failed all change readiness

فراخوانی خام:

var b = window.WebToApk;
var ready = !!(b && typeof b.adsIsReady === 'function' && b.adsIsReady('interstitial'));

در پایان مرحله فقط وقتی تبلیغ میان‌صفحه‌ای نمایش دهید که یکی منتظر است، و وقتی نیست هرگز بازیکن را معطل نکنید:

function onLevelComplete() {
  var ads = window.AppMintAds;
  if (ads && ads.isReady('interstitial')) {
    // resolves after the ad closes, or at once with {ok:false, code} if it could not show
    ads.show('interstitial').then(startNextLevel);
  } else {
    startNextLevel();                             // not loaded yet, or inside the 60-second cooldown
  }
}

نکته‌ها: تبلیغ میان‌صفحه‌ای در مدت ۶۰ ثانیهٔ خنک‌شدنش با false پاسخ می‌دهد. تبلیغ باز شدن اپلیکیشن قدیمی‌تر از ۴ ساعت با false پاسخ می‌دهد (Google می‌گوید آن را نمایش ندهید). در حالت خودکار این همیشه false است؛ در آنجا از WebToApk.isRewardedAdReady() استفاده کنید.

adsLoad پل#

window.WebToApk.adsLoad(type: String, callbackId: String)

یک [type] تمام‌صفحه را بارگذاری می‌کند؛ promise مربوط به [callbackId] با نتیجه تکمیل می‌شود.

نمونه

نیمهٔ بومی AppMintAds.load(type): بارگذاری یک تبلیغ تمام‌صفحه را شروع می‌کند و به callback شیم پاسخ می‌دهد. صفحه‌ها از AppMintAds.load(type) استفاده می‌کنند که یک Promise برمی‌گرداند؛ مستقیم این را فراخوانی نکنید.

مقدار بازگشتی: (از طریق AppMintAds.load) یک Promise از {ok:true}، {ok:true, cached:true} وقتی یکی از قبل بارگذاری شده، یا {ok:false, code, reason, message?, adCode?}. نیازها: کنترل تبلیغات ← کنترل‌شده توسط توسعه‌دهنده و شناسهٔ واحد تبلیغ برای آن نوع.

var watchBtn = document.getElementById('watch-ad');
watchBtn.disabled = true;

if (window.AppMintAds) {
  window.AppMintAds.load('rewarded').then(function (res) {
    if (res.ok) watchBtn.disabled = false;
    else console.log('rewarded ad not loaded:', res.code, res.message);
  });
} else {
  watchBtn.hidden = true;                       // browser: there are no ads here
}

بارگذاری‌ای را که به دلیلی گذرا شکست خورده دوباره امتحان کنید و برای دلایلی که تلاش مجدد حلشان نمی‌کند، متوقف شوید:

function loadWithRetry(type, attempt) {
  attempt = attempt || 0;
  return window.AppMintAds.load(type).then(function (res) {
    if (res.ok) return res;
    if ((res.code === 'no_fill' || res.code === 'network') && attempt < 3) {
      return new Promise(function (wait) { setTimeout(wait, 5000 * (attempt + 1)); })
        .then(function () { return loadWithRetry(type, attempt + 1); });
    }
    return res;                                   // invalid_unit, consent, ad_free, disabled ...
  });
}

if (window.AppMintAds) {
  loadWithRetry('rewarded').then(function (res) {
    document.getElementById('watch-ad').disabled = !res.ok;
  });
}

پیش از شروع جلسهٔ بازی دو قالب را آماده کنید و وقتی کاربر اصلاً تبلیغی ندارد همهٔ دکمه‌های تبلیغ را پنهان کنید:

if (window.AppMintAds) {
  Promise.all([
    window.AppMintAds.load('interstitial'),
    window.AppMintAds.load('rewarded_interstitial')
  ]).then(function (results) {
    var noAds = results.some(function (r) { return r.code === 'ad_free' || r.code === 'disabled'; });
    if (noAds) hideAllAdButtons();                // paid to remove ads, or ads are off in this build
    results.forEach(function (r) {
      if (!r.ok && r.adCode !== undefined) console.log('ad load failed', r.code, r.adCode, r.message);
    });
  });
}

نکته‌ها: کدهای شکست: no_fill، network، invalid_unit، internal (از AdMob، با adCode) و automatic_mode، unknown_type، ad_free، disabled، consent و use_slot برای banner / mrec (آن‌ها با AppMintAds.banner.attach بارگذاری می‌شوند). اپلیکیشن همین حالا هر نوع تمام‌صفحه‌ای را که شناسهٔ واحد دارد از پیش بارگذاری می‌کند و پس از هر نمایش دوباره بارگذاری می‌کند. امضای خام adsLoad(type, callbackId) است؛ پاسخش به یک resolver داخلی می‌رود، پس فراخوانی مستقیم نتیجه‌ای به شما نمی‌دهد.

adsShow پل#

window.WebToApk.adsShow(type: String, callbackId: String, userGesture: Boolean)

یک [type] تمام‌صفحهٔ بارگذاری‌شده را نمایش می‌دهد؛ وقتی بسته شد تکمیل می‌شود، با earned/reward برای قالب‌های پاداشی. [userGesture] مقدار `navigator.userActivation` شیم است - قالب پاداشی‌ای که بدون آن درخواست شود ابتدا صفحهٔ معرفی AdMob را می‌گیرد (به DeveloperAds.offerRewarded مراجعه کنید).

نمونه

نیمهٔ بومی AppMintAds.show(type): یک تبلیغ تمام‌صفحهٔ بارگذاری‌شده را نمایش می‌دهد و وقتی بسته شد پاسخ می‌دهد. صفحه‌ها از AppMintAds.show(type) استفاده می‌کنند؛ مستقیم این را فراخوانی نکنید.

مقدار بازگشتی: (از طریق AppMintAds.show) پس از بسته شدن تبلیغ یک Promise از {ok:true, shown:true, earned, reward?} (reward = {type, amount} برای قالب‌های پاداشی)، یا {ok:false, shown:false, code, reason, message?}. نیازها: کنترل تبلیغات ← کنترل‌شده توسط توسعه‌دهنده و شناسهٔ واحد تبلیغ برای آن نوع.

آن را از لمس کاربر فراخوانی کنید. شیم navigator.userActivation.isActive را به‌عنوان آرگومان سوم می‌فرستد (userGesture):

document.getElementById('watch-ad').addEventListener('click', function () {
  if (!window.AppMintAds) return;
  window.AppMintAds.show('rewarded').then(function (res) {
    if (res.earned) addCoins(res.reward.amount);
    else if (res.reason === 'ad_free') addCoins(50);      // paid to remove ads: reward anyway
    else if (res.reason !== 'declined') showMessage('No ad available right now.');
  });
});

از لمس خود کاربر روی «پاداشم را دو برابر کن» یک تبلیغ میان‌صفحه‌ای پاداشی پیشنهاد دهید و با هر پاسخی ادامه دهید:

document.getElementById('double-bonus').addEventListener('click', function () {
  if (!window.AppMintAds) return goToNextLevel();
  window.AppMintAds.show('rewarded_interstitial').then(function (res) {
    if (res.earned) doubleLevelBonus();
    else if (!res.shown && res.code !== 'declined') console.log('no ad:', res.code);
    goToNextLevel();                              // shown or not, the player keeps going
  });
});

موسیقی بازی‌تان را تا وقتی هر تبلیغ تمام‌صفحه روی صفحه است، با جریان appmint:ad متوقف کنید:

window.addEventListener('appmint:ad', function (e) {
  var d = e.detail;                               // {type, phase, code?, adCode?, message?, earned?, reward?}
  if (d.type === 'banner' || d.type === 'mrec') return;
  if (d.phase === 'opened') music.pause();
  if (d.phase === 'closed' || d.phase === 'show_failed') music.play();
});

function onChapterSaved() {
  if (window.AppMintAds) window.AppMintAds.show('interstitial');   // a natural break
}

نکته‌ها: امضای خام adsShow(type, callbackId, userGesture). وقتی userGesture برای rewarded یا rewarded_interstitial برابر false باشد، اپلیکیشن ابتدا می‌پرسد «تبلیغ ببینید؟ / نه، ممنون» و پاسخ «نه» برابر declined است. کدهای دیگر: automatic_mode، unknown_type، ad_free، disabled، consent، not_full_screen، showing، cooldown (تبلیغ میان‌صفحه‌ای، ۶۰ ثانیه)، not_loaded (برای دفعهٔ بعد بارگذاری شروع می‌شود)، show_failed, internal.

adsSlotAttach پل#

window.WebToApk.adsSlotAttach(slotId: String, type: String, widthCss: Int, callbackId: String)

برای جایگاه [slotId] صفحه یک پوشش banner/mrec می‌سازد، با اندازهٔ [widthCss]؛ پس از بارگذاری، با اندازهٔ تبلیغ تکمیل می‌شود.

نمونه

نیمهٔ بومی AppMintAds.banner.attach(element, {size}): یک تبلیغ بنر یا مستطیل متوسط روی یک عنصر صفحه می‌سازد. صفحه‌ها از AppMintAds.banner.attach استفاده می‌کنند؛ مستقیم این را فراخوانی نکنید.

مقدار بازگشتی: (از طریق AppMintAds.banner.attach) پس از بارگذاری تبلیغ یک Promise از {ok:true, slot, width, height} به پیکسل CSS، یا {ok:false, slot, code, message?}. نیازها: کنترل تبلیغات ← کنترل‌شده توسط توسعه‌دهنده و شناسهٔ واحد تبلیغ بنر (یا مستطیل متوسط).

<div id="ad-slot"></div>

<script>
if (window.AppMintAds) {
  window.AppMintAds.banner.attach('#ad-slot', { size: 'banner' }).then(function (res) {
    if (!res.ok) console.log('no banner:', res.code);   // e.g. no_fill, network, too_many_slots
  });
}
</script>

یک مستطیل متوسط در صفحهٔ نتایج که اگر تبلیغی نیاید، فضایش را پس می‌دهد:

var box = document.getElementById('result-ad');

if (window.AppMintAds) {
  window.AppMintAds.banner.attach(box, { size: 'mrec' }).then(function (res) {
    if (res.ok) return;                           // the box now has min-height = res.height
    window.AppMintAds.banner.detach(res.slot);    // free the slot for another banner
    box.hidden = true;
    if (res.code === 'too_many_slots') console.log('detach a banner first:', res.message);
  });
} else {
  box.hidden = true;
}

نمایش‌ها و کلیک‌ها را برای هر جایگاه از جریان appmint:ad بشمارید، با کلید شناسهٔ جایگاهی که attach برگردانده است:

var slotNames = {};

if (window.AppMintAds) {
  window.AppMintAds.banner.attach('#footer-ad', { size: 'banner' }).then(function (res) {
    if (res.ok) slotNames[res.slot] = 'footer';
  });
}

window.addEventListener('appmint:ad', function (e) {
  var d = e.detail;                               // banner events carry {type, phase, slot}
  if (d.slot && (d.phase === 'impression' || d.phase === 'clicked')) {
    track('ad_' + d.phase, slotNames[d.slot] || d.slot);
  }
});

نکته‌ها: امضای خام adsSlotAttach(slotId, type, widthCss, callbackId)؛ type برابر 'banner' یا 'mrec' است. WebView نمی‌تواند یک view بومی را درون صفحه نگه دارد، پس تبلیغ روی عنصر شما کشیده می‌شود و با اسکرول و تغییر اندازه آن را دنبال می‌کند (به adsSlotRect مراجعه کنید). حداکثر دو جایگاه هم‌زمان، و فقط یک مستطیل متوسط. کدهای اضافه: duplicate_slot، too_many_slots، detached، internal، به‌علاوهٔ کدهای بارگذاری (no_fill, network, invalid_unit, ad_free, disabled, consent, automatic_mode).

adsSlotDetach پل#

window.WebToApk.adsSlotDetach(slotId: String)

پوشش بنر را برمی‌دارد.

نمونه

نیمهٔ بومی AppMintAds.banner.detach(slotOrElement): پوشش بنر را برمی‌دارد و جایگاهش را آزاد می‌کند. صفحه‌ها از AppMintAds.banner.detach.

مقدار بازگشتی: هیچ. نیازها: کنترل تبلیغات ← کنترل‌شده توسط توسعه‌دهنده.

بنر را پیش از صفحه‌ای که تبلیغ در آن جایی ندارد (پخش‌کنندهٔ ویدیو، تسویه‌حساب) بردارید:

var slotEl = document.getElementById('ad-slot');

function openPlayer() {
  if (window.AppMintAds) window.AppMintAds.banner.detach(slotEl);   // the element, or the slot id from attach()
  showPlayer();
}

function closePlayer() {
  hidePlayer();
  if (window.AppMintAds) window.AppMintAds.banner.attach(slotEl, { size: 'banner' });
}

در یک اپلیکیشن تک‌صفحه‌ای، وقتی مسیری که بنر را دارد از بین می‌رود آن را آزاد کنید. attach عنصر را بلافاصله علامت می‌زند، پس جدا کردن با عنصر حتی وقتی تبلیغ هنوز در حال بارگذاری است کار می‌کند:

function onRouteChange(route) {
  if (!window.AppMintAds) return renderRoute(route);
  var old = document.getElementById('article-ad');
  if (old) window.AppMintAds.banner.detach(old);
  renderRoute(route);
  if (route === '/articles') {
    window.AppMintAds.banner.attach('#article-ad', { size: 'banner' });
  }
}

پس از خرید «حذف تبلیغات» پوشش‌ها رفته‌اند؛ جایگاه‌ها را هم جدا کنید و فضایی را که رزرو کرده بودند حذف کنید:

window.addEventListener('appmint:premium', function (e) {
  if (!e.detail.premium || !window.AppMintAds) return;
  document.querySelectorAll('[data-appmint-ad-slot]').forEach(function (el) {
    window.AppMintAds.banner.detach(el);
    el.remove();
  });
});

نکته‌ها: امضای خام adsSlotDetach(slotId). detach عنصر یا رشتهٔ slot را می‌گیرد که attach برگردانده است، نه یک انتخاب‌گر CSS. یک Promise از attach که هنوز منتظر تبلیغش است با {ok:false, code:'detached'} پاسخ می‌دهد. برداشتن عنصر از DOM هم جایگاه را جدا می‌کند.

adsSlotRect پل#

window.WebToApk.adsSlotRect(slotId: String, x: Float, y: Float, w: Float, h: Float, visible: Boolean)

داخلی: مستطیل viewport فعلی عنصر جایگاه (پیکسل CSS) - پوشش را جابه‌جا می‌کند.

نمونه

داخلی: پوشش بنر را به موقعیت فعلی عنصرش منتقل می‌کند. کمک‌کنندهٔ AppMintAds.banner آن را هنگام اسکرول، تغییر اندازه، تغییر نمایان‌بودن و هر ۵۰۰ میلی‌ثانیه فراخوانی می‌کند؛ صفحه‌ها از AppMintAds.banner.attach استفاده می‌کنند و هرگز این را فراخوانی نمی‌کنند.

مقدار بازگشتی: هیچ. نیازها: کنترل تبلیغات ← کنترل‌شده توسط توسعه‌دهنده و یک جایگاه که با AppMintAds.banner.attach.

تنها کاری که صفحه می‌کند این است که به عنصر جایگاه یک مکان در چیدمان بدهد. کمک‌کننده آن را اندازه می‌گیرد و تبلیغ را روی آن نگه می‌دارد:

<main>
  <article id="story">…</article>
  <div id="ad-slot" style="margin: 16px 0"></div>   <!-- the ad follows this box while scrolling -->
</main>

<script>
if (window.AppMintAds) window.AppMintAds.banner.attach('#ad-slot', { size: 'banner' });
</script>

یک بنر داخل لیست قابل اسکرول، نه صفحه: کمک‌کننده در فاز capture به scroll گوش می‌دهد، پس تبلیغ محفظهٔ درونی را هم دنبال می‌کند:

<div id="feed" style="height: 100vh; overflow-y: auto">
  <div class="card">…</div>
  <div class="card">…</div>
  <div id="feed-ad" style="margin: 12px 0"></div>
  <div class="card">…</div>
</div>

<script>
if (window.AppMintAds) window.AppMintAds.banner.attach('#feed-ad', { size: 'banner' });
</script>

تبلیغ بالای صفحه کشیده می‌شود، پس کادر گفتگوی خودتان زیر آن قرار می‌گیرد. تا وقتی کادر گفتگو باز است، جایگاه را پنهان کنید:

var slotEl = document.getElementById('ad-slot');
var dialog = document.getElementById('settings-dialog');

function openSettings() {
  slotEl.style.visibility = 'hidden';             // the helper hides the overlay on its next tick
  dialog.showModal();
}

dialog.addEventListener('close', function () {
  slotEl.style.visibility = '';                   // and puts it back over the box
});

نکته‌ها: امضای خام adsSlotRect(slotId, x, y, w, h, visible)، به پیکسل CSS نسبت به viewport. تا وقتی عنصر بیرون از صفحه باشد، اندازهٔ صفر داشته باشد، visibility: hidden داشته باشد، یا صفحه در پس‌زمینه باشد، پوشش پنهان است. اگر عنصر از DOM خارج شود، کمک‌کننده خودش جایگاه را جدا می‌کند.

isInterstitialAdReady پل#

window.WebToApk.isInterstitialAdReady(): Boolean

درست است وقتی یک تبلیغ میان‌صفحه‌ای بارگذاری شده و از خنک‌شدنش گذشته است (دقیقاً با آنچه showInterstitialAd() می‌پذیرد منطبق است - «آماده»ای که بعد از نمایش سر باز بزند وجود ندارد).

نمونه

می‌گوید آیا تبلیغ میان‌صفحه‌ای بارگذاری شده و از خنک‌شدن ۶۰ ثانیه‌ای‌اش گذشته است یا نه، تا showInterstitialAd() همین حالا آن را نمایش دهد (کنترل خودکار تبلیغات).

مقدار بازگشتی: true / false، همگام. نیازها: تبلیغات روشن و تبلیغ تمام‌صفحه ← تبلیغ میان‌صفحه‌ای.

function onLevelDone() {
  var b = window.WebToApk;
  if (b && typeof b.isInterstitialAdReady === 'function' && b.isInterstitialAdReady()) {
    b.showInterstitialAd();               // wait for 'appmint:ad-closed' before continuing
  } else {
    startNextLevel();                     // nothing ready: never block the user
  }
}

window.addEventListener('appmint:ad-closed', function (e) {
  if (e.detail.adType === 'interstitial') startNextLevel();
});

پس از هر سومین آزمون تمام‌شده یک تبلیغ نمایش دهید، و فقط وقتی که واقعاً نمایش داده می‌شود:

var finished = 0;

function onQuizFinished() {
  finished++;
  var b = window.WebToApk;
  var ready = !!(b && typeof b.isInterstitialAdReady === 'function' && b.isInterstitialAdReady());
  if (finished % 3 === 0 && ready) b.showInterstitialAd();
  showResults();                                  // the results are there when the ad closes
}

فقط وقتی تبلیغی آماده است، اعلان کوتاه «تبلیغ تا ۳…» را نشان دهید، سپس وقتی بسته شد یا نمایش داده نشد ادامه دهید:

var afterAd = null;

function adBreakThen(next) {
  var b = window.WebToApk;
  if (!b || typeof b.isInterstitialAdReady !== 'function' || !b.isInterstitialAdReady()) return next();
  var note = document.getElementById('ad-break'), n = 3;
  note.hidden = false; note.textContent = 'Ad in 3…';
  var t = setInterval(function () {
    if (--n > 0) { note.textContent = 'Ad in ' + n + '…'; return; }
    clearInterval(t); note.hidden = true;
    afterAd = next;
    b.showInterstitialAd();
  }, 1000);
}

function runAfterAd(e) {
  if (e.detail.adType !== 'interstitial' || !afterAd) return;
  var next = afterAd; afterAd = null; next();
}
window.addEventListener('appmint:ad-closed', runAfterAd);
window.addEventListener('appmint:ad-unavailable', runAfterAd);

نکته‌ها: true در اینجا یعنی نمایش به‌دلیل not_loaded یا cooldown رد نمی‌شود. رضایت یا خرید «حذف تبلیغات» هنوز می‌تواند آن را متوقف کند (appmint:ad-unavailable). در ساخت‌های کنترل‌شده توسط توسعه‌دهنده از AppMintAds.isReady('interstitial').

isRewardedAdReady پل#

window.WebToApk.isRewardedAdReady(): Boolean

درست است وقتی تبلیغ پاداشی بارگذاری شده و همین حالا قابل نمایش است. اجازه دهید صفحه دکمهٔ «تماشای تبلیغ»ش را بر اساس این فعال/غیرفعال کند (پیش از نمایش، poll کنید یا فراخوانی کنید).

نمونه

می‌گوید آیا تبلیغ پاداشی بارگذاری شده و همین حالا قابل نمایش است یا نه (کنترل خودکار تبلیغات).

مقدار بازگشتی: true / false، همگام. نیازها: تبلیغات روشن و تبلیغ تمام‌صفحه ← تبلیغ پاداشی.

دکمهٔ «تماشای تبلیغ» را فقط وقتی فعال کنید که تبلیغی منتظر است:

var btn = document.getElementById('earn');

function refreshWatchButton() {
  var b = window.WebToApk;
  var ready = !!(b && typeof b.isRewardedAdReady === 'function' && b.isRewardedAdReady());
  btn.disabled = !ready;
  btn.textContent = ready ? 'Watch an ad for 10 coins' : 'Loading ad…';
}
refreshWatchButton();
setInterval(refreshWatchButton, 2000);                 // an ad can finish loading at any time
window.addEventListener('appmint:ad-closed', refreshWatchButton);

در پایان بازی، «ادامه» را فقط وقتی پیشنهاد دهید که تبلیغی منتظر است، تا دکمه هرگز به جایی نرسد:

var continueBtn = document.getElementById('continue-with-ad');

function onGameOver() {
  var b = window.WebToApk;
  continueBtn.hidden = !(b && typeof b.isRewardedAdReady === 'function' && b.isRewardedAdReady());
  showGameOverPanel();                            // "Restart" is always there
}

continueBtn.addEventListener('click', function () {   // the user's own tap
  continueBtn.hidden = true;
  window.WebToApk.showRewardedAd();
});

window.addEventListener('appmint:reward', function () { revivePlayer(); });

در لحظهٔ لمس بررسی کنید و به‌جای اجرای نمایشی که رد می‌شود، به کاربر بگویید چه خبر است:

document.getElementById('hint').addEventListener('click', function () {
  var b = window.WebToApk;
  if (!b || typeof b.isRewardedAdReady !== 'function') return showMessage('Hints need the app.');
  if (typeof b.isPremium === 'function' && b.isPremium()) return revealHint();   // paid to remove ads
  if (b.isRewardedAdReady()) b.showRewardedAd();
  else showMessage('The ad is still loading. Try again in a few seconds.');
});

window.addEventListener('appmint:reward', function () { revealHint(); });

نکته‌ها: در مرورگر، وقتی تبلیغات با خرید حذف شده باشند و پیش از بارگذاری اولین تبلیغ، false برمی‌گرداند. پس از نمایش یک تبلیغ، بعدی خودبه‌خود بارگذاری می‌شود. در ساخت‌های کنترل‌شده توسط توسعه‌دهنده از AppMintAds.isReady('rewarded').

notifyUserAction پل#

window.WebToApk.notifyUserAction()

داخلی (توسط شمارندهٔ لمس تزریق‌شده فراخوانی می‌شود، نه کد سازنده): یک تعامل معنادار کاربر در صفحه رخ داد. فقط تا وقتی که هرگز ناوبری مبتنی بر URL مشاهده نشده باشد، در آهنگ «تبلیغ میان‌صفحه‌ای در هر N عمل» حساب می‌شود - اپلیکیشن‌های تک‌HTML که صفحه‌ها را با نمایش/پنهان کردن DOM عوض می‌کنند هرگز URL را تغییر نمی‌دهند، پس بدون این، شمارندهٔ ناوبری‌شان برای همیشه ۰ می‌ماند و تبلیغ‌های تنظیم‌شده هرگز نمایش داده نمی‌شدند (دستهٔ شکایت TicTrek، ۲۰۲۶-۰۷-۲۶). اپلیکیشن‌های URL/SPA تحت تأثیر نیستند: اولین ناوبری واقعی‌شان شمارش را برای همیشه به سیگنال‌های URL برمی‌گرداند.

نمونه

یک عمل معنادار کاربر را برای تنظیم «تبلیغ تمام‌صفحه در هر N عمل» می‌شمارد. اپلیکیشن این را خودش از شمارندهٔ لمس خودش فراخوانی می‌کند؛ صفحه‌ها معمولاً هرگز آن را فراخوانی نمی‌کنند.

مقدار بازگشتی: هیچ. نیازها: تبلیغات روشن، یک تبلیغ تمام‌صفحه با حالت راه‌انداز ← پس از ناوبری‌ها و کنترل خودکار تبلیغات.

نحوهٔ کار: صفحه‌ای که با پنهان و نمایان کردن عناصر DOM بین صفحه‌ها جابه‌جا می‌شود، هرگز نشانی‌اش (URL) را عوض نمی‌کند، پس اپلیکیشن نمی‌تواند «ناوبری» را ببیند. بنابراین اپلیکیشن یک شمارندهٔ لمس تزریق می‌کند (حداکثر یک شمارش در هر ۲ ثانیه) که این متد را فراخوانی می‌کند. به‌محض اینکه اپلیکیشن یک تغییر واقعی URL ببیند (بارگذاری صفحه، pushState یا یک #hash)، به‌جای آن تغییرهای URL را می‌شمارد و این متد شمارش را متوقف می‌کند.

فقط اگر تغییر صفحه‌هایتان از لمس نمی‌آیند (مثلاً حرکت با صفحه‌کلید یا گیم‌پد)، خودتان گزارششان کنید:

function goToScreen(name) {
  showScreen(name);                                   // your own DOM show/hide
  var b = window.WebToApk;
  if (b && typeof b.notifyUserAction === 'function') b.notifyUserAction();
}

document.addEventListener('keydown', function (e) {
  if (e.key === 'Enter') goToScreen('next');
});

اپلیکیشنی کارتی که کاربر برای رفتن به صفحهٔ بعد swipe می‌کند (swipe لمس یک دکمه نیست، پس شمارندهٔ لمس هرگز آن را نمی‌بیند):

var startX = null;

document.addEventListener('touchstart', function (e) { startX = e.touches[0].clientX; }, { passive: true });

document.addEventListener('touchend', function (e) {
  if (startX === null) return;
  var dx = e.changedTouches[0].clientX - startX;
  startX = null;
  if (Math.abs(dx) < 80) return;                       // not a swipe
  showScreen(dx < 0 ? 'next' : 'previous');            // your own DOM show/hide
  var b = window.WebToApk;
  if (b && typeof b.notifyUserAction === 'function') b.notifyUserAction();
});

یک بازی HTML5 که با گیم‌پد بازی می‌شود و به ازای هر مرحله‌ای که بازیکن با دکمهٔ A شروع می‌کند یک عمل می‌شمارد:

var aWasDown = false;

function pollPad() {
  var pad = navigator.getGamepads ? navigator.getGamepads()[0] : null;
  var aDown = !!(pad && pad.buttons[0] && pad.buttons[0].pressed);
  if (aDown && !aWasDown && isOnLevelSelect()) {       // your own game state
    startSelectedLevel();
    var b = window.WebToApk;
    if (b && typeof b.notifyUserAction === 'function') b.notifyUserAction();
  }
  aWasDown = aDown;
  requestAnimationFrame(pollPad);
}

window.addEventListener('gamepadconnected', function () { requestAnimationFrame(pollPad); }, { once: true });

نکته‌ها: وقتی تبلیغات خاموش باشند، با خرید حذف شده باشند، یا ساخت از کنترل تبلیغات ← کنترل‌شده توسط توسعه‌دهنده استفاده کند، این کاری نمی‌کند (در آن حالت خودتان AppMintAds.show() را فراخوانی می‌کنید). تبلیغ پاداشی که از این راه برسد همیشه با پرسش «تبلیغ ببینید؟ / نه، ممنون» پیشنهاد می‌شود و هرگز اجباری نیست. آن را در هر لمس فراخوانی نکنید؛ این کار تبلیغ را بیشتر از آنچه تنظیم کرده‌اید نمایش می‌دهد.

showInterstitialAd پل#

window.WebToApk.showInterstitialAd()

همین حالا یک تبلیغ میان‌صفحه‌ای نمایش دهید (مثلاً بین مرحله‌ها / در یک عمل عمدی). اگر همین حالا قابل نمایش نباشد ← رد می‌شود + 'appmint:ad-unavailable' با دلیل.

نمونه

همین حالا یک تبلیغ میان‌صفحه‌ای تمام‌صفحه نمایش می‌دهد، مثلاً بین دو مرحلهٔ بازی (کنترل خودکار تبلیغات).

مقدار بازگشتی: هیچ. وقتی تبلیغ بسته می‌شود، appmint:ad-closed با {adType:'interstitial', earned:false} اجرا می‌شود. وقتی نمایش داده نشود، appmint:ad-unavailable با {adType:'interstitial', reason} اجرا می‌شود. نیازها: تبلیغات روشن و تبلیغ تمام‌صفحه ← تبلیغ میان‌صفحه‌ای. اگر فقط صفحهٔ شما باید تصمیم بگیرد کی، حالت راه‌انداز ← بر حسب درخواست را انتخاب کنید.

var bridge = window.WebToApk;
var waitingForAd = false;

function levelFinished() {
  if (bridge && typeof bridge.isInterstitialAdReady === 'function' && bridge.isInterstitialAdReady()) {
    waitingForAd = true;
    bridge.showInterstitialAd();          // the next level starts when the ad closes
  } else {
    showNextLevel();                      // no ad ready: just continue
  }
}

window.addEventListener('appmint:ad-closed', function (e) {
  if (e.detail.adType === 'interstitial' && waitingForAd) { waitingForAd = false; showNextLevel(); }
});

window.addEventListener('appmint:ad-unavailable', function (e) {
  // reason: ad_free | disabled | consent | not_loaded | cooldown | show_failed
  if (e.detail.adType === 'interstitial' && waitingForAd) { waitingForAd = false; showNextLevel(); }
});

بازی و صدایش را پیش از تبلیغ متوقف کنید و با هر دو پاسخ از سر بگیرید:

var pausedForAd = false;

function adBetweenRounds() {
  var b = window.WebToApk;
  if (!b || typeof b.showInterstitialAd !== 'function') return;
  pausedForAd = true;
  pauseGame(); music.pause();
  b.showInterstitialAd();
}

function resumeAfterAd(e) {
  if (e.detail.adType !== 'interstitial' || !pausedForAd) return;
  pausedForAd = false;
  music.play(); resumeGame();
}
window.addEventListener('appmint:ad-closed', resumeAfterAd);
window.addEventListener('appmint:ad-unavailable', resumeAfterAd);

یک مقاله را پس از یک تبلیغ باز کنید، به‌صورت یک Promise که وقتی تبلیغ نمایش داده شد با true و وقتی رد شد با false تکمیل می‌شود:

function interstitialThen() {
  return new Promise(function (resolve) {
    var b = window.WebToApk;
    if (!b || typeof b.isInterstitialAdReady !== 'function' || !b.isInterstitialAdReady()) return resolve(false);
    function done(e) {
      if (e.detail.adType !== 'interstitial') return;
      window.removeEventListener('appmint:ad-closed', done);
      window.removeEventListener('appmint:ad-unavailable', done);
      resolve(e.type === 'appmint:ad-closed');
    }
    window.addEventListener('appmint:ad-closed', done);
    window.addEventListener('appmint:ad-unavailable', done);
    b.showInterstitialAd();
  });
}

interstitialThen().then(function () { openArticle(articleId); });

نکته‌ها: اپلیکیشن بین دو تبلیغ میان‌صفحه‌ای دست‌کم ۶۰ ثانیه فاصله نگه می‌دارد؛ فراخوانی در این فاصله با cooldown پاسخ می‌دهد. isInterstitialAdReady() خنک‌شدن را از قبل در نظر می‌گیرد، پس ابتدا بررسی آن از رویداد جلوگیری می‌کند. تبلیغ‌های میان‌صفحه‌ای را در وقفه‌های طبیعی نمایش دهید، نه در هر لمس. در ساخت‌های کنترل‌شده توسط توسعه‌دهنده از AppMintAds.show('interstitial').

showRewardedAd پل#

window.WebToApk.showRewardedAd()

همین حالا یک تبلیغ پاداشی نمایش دهید (به‌ابتکار کاربر - تنها راه سازگار با سیاست‌ها برای نمایش پاداشی). آن را با حالت راه‌انداز «بر حسب درخواست» در جادوگر جفت کنید تا تبلیغ پاداشی بدون هیچ تبلیغ خودکار باز شدن اپلیکیشن/ناوبری داشته باشید. پاداش از طریق deliverRewardToPage() به صفحه می‌رسد: window.addEventListener('appmint:reward', e => { /* e.detail = {type,amount} */ }) وقتی تبلیغ بسته می‌شود، 'appmint:ad-closed' با {adType:'rewarded', earned} اجرا می‌شود - اگر کاربر زود خارج شده باشد earned برابر false است، پس در آن حالت چیزی ندهید. اگر همین حالا قابل نمایش نباشد ← رد می‌شود + 'appmint:ad-unavailable' با دلیل اجرا می‌شود.

نمونه

همین حالا یک تبلیغ پاداشی نمایش می‌دهد، از لمس «تماشای تبلیغ» خود کاربر (کنترل خودکار تبلیغات).

مقدار بازگشتی: هیچ. نتیجه بعداً به‌صورت رویداد می‌رسد: appmint:reward {type, amount} وقتی تبلیغ تا آخر دیده شد، appmint:ad-closed {adType:'rewarded', earned} وقتی بسته می‌شود، یا appmint:ad-unavailable {adType:'rewarded', reason} وقتی چیزی نمایش داده نشد. نیازها: تبلیغات روشن، تبلیغ تمام‌صفحه ← تبلیغ پاداشی و حالت راه‌انداز ← بر حسب درخواست تا چیزی خودبه‌خود نمایش داده نشود.

پاداش را فقط در کنترل‌کنندهٔ پاداش بدهید، نه هنگام لمس:

var btn = document.getElementById('earn');
var bridge = window.WebToApk;

function refresh() {
  btn.disabled = !(bridge && typeof bridge.isRewardedAdReady === 'function' && bridge.isRewardedAdReady());
}
refresh();
setInterval(refresh, 2000);

btn.addEventListener('click', function () {        // a real user tap: the only place to call it
  if (!bridge || typeof bridge.showRewardedAd !== 'function') return;
  btn.disabled = true;
  bridge.showRewardedAd();
});

// GRANT HERE ONLY: the ad was watched to the end.
window.addEventListener('appmint:reward', function (e) {
  addCoins(e.detail.amount);                        // e.detail = {type, amount}
});

// The ad closed. earned === false means the user left early: grant nothing.
window.addEventListener('appmint:ad-closed', function (e) {
  if (e.detail.adType === 'rewarded' && !e.detail.earned) showMessage('No reward: the ad was closed early.');
  refresh();
});

// Nothing could be shown.
window.addEventListener('appmint:ad-unavailable', function (e) {
  // e.detail = {adType, reason}; reason: ad_free | disabled | consent | not_loaded | show_failed
  if (e.detail.reason === 'ad_free') addCoins(1);   // the user paid to remove ads: reward anyway
  else showMessage('No ad right now. Try again in a moment.');
  refresh();
});

همین سه لحظه hookهای صفحه را هم فراخوانی می‌کنند، اگر هر کدام را با یک تابع ترجیح می‌دهید (هر کدام همان شیئی را می‌گیرد که e.detail):

window.onAppMintReward = function (reward) { addCoins(reward.amount); };      // {type, amount}
window.onAppMintAdClosed = function (info) { console.log(info.adType, info.earned); };
window.onAppMintAdUnavailable = function (info) { console.log(info.adType, info.reason); };

فراخوانی و رویدادهایش را در یک Promise بپیچید تا هر دکمهٔ «تماشای تبلیغ» مثل یک فراخوانی ناهمگام معمولی خوانده شود:

function watchRewardedAd() {                      // call it inside the user's tap
  return new Promise(function (resolve) {
    var b = window.WebToApk;
    if (!b || typeof b.showRewardedAd !== 'function') return resolve({ earned: false, reason: 'no_app' });
    function done(e) {
      if (e.detail.adType !== 'rewarded') return;
      window.removeEventListener('appmint:ad-closed', done);
      window.removeEventListener('appmint:ad-unavailable', done);
      resolve(e.type === 'appmint:ad-closed' ? { earned: e.detail.earned } : { earned: false, reason: e.detail.reason });
    }
    window.addEventListener('appmint:ad-closed', done);
    window.addEventListener('appmint:ad-unavailable', done);
    b.showRewardedAd();
  });
}

document.getElementById('revive').addEventListener('click', function () {
  watchRewardedAd().then(function (r) {
    if (r.earned || r.reason === 'ad_free') revivePlayer();
    else if (r.reason) showMessage('No ad right now.');
  });
});

نکته‌ها: فقط از یک کنترل‌کنندهٔ کلیک فراخوانی کنید. هرگز از تایمر، بارگذاری صفحه یا تغییر مسیر فراخوانی نکنید و هرگز یک قابلیت اصلی را پشتش نگذارید. not_loaded یک بارگذاری جدید هم شروع می‌کند، پس لمس بعدی معمولاً کار می‌کند. در ساخت‌های کنترل تبلیغات ← کنترل‌شده توسط توسعه‌دهنده به‌جایش از AppMintAds.show('rewarded') استفاده کنید که با یک Promise پاسخ می‌دهد.