Create Free APK

JavaScript bridge API

Ads

Showing an interstitial or a rewarded ad on your own cue, and telling the shell when a navigation starts and settles so it does not interrupt one.

AppMintAds.appOpen helper#

window.AppMintAds.appOpen.setEnabled(on)

Example

Pauses or resumes the app-open ad, the full-screen ad shown at launch and when the user returns from another app.

Returns: nothing. Needs: Ad Control → Developer-controlled and an app-open ad unit ID.

Pause it while the user leaves the app on purpose for a short moment (a payment app, the camera, a share sheet), so coming back does not show an ad:

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);
  }
}

Check whether the build has an app-open unit at all:

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

Notes: It is on by default. At cold start the ad shows when the page is ready, or when it finishes loading within 15 seconds; a later load is kept for next time. An app-open ad older than 4 hours is never shown. You can also show one yourself with AppMintAds.show('app_open').

AppMintAds.banner helper#

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

Example

Places a banner or a 300×250 medium-rectangle ad anywhere in your page, on top of an element you choose.

Returns: attach returns a Promise of {ok:true, slot, width, height} (CSS px) once the ad has loaded, or {ok:false, slot?, code, message?}. detach returns nothing. Needs: Ad Control → Developer-controlled and a banner (or medium rectangle) ad unit ID.

The element only reserves the space. The ad is drawn over it and follows it when the page scrolls or resizes:

<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>

Medium rectangle (one at a time), and removing a banner again:

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;
}

Notes: target is an element or a CSS selector; size is 'banner' (default, adaptive width, at most 90 dp tall), 'medium_rectangle' or 'mrec'. At most two slots at once, and a slot whose ad failed to load still counts until you detach it. detach needs the element or the slot id from attach, not a selector. Removing the element from the DOM detaches it too. Codes: no_element, duplicate_slot, too_many_slots, detached, no_fill, network, invalid_unit, ad_free, disabled, consent, automatic_mode, internal.

AppMintAds.config helper#

window.AppMintAds.config()

Example

Tells the page which ad control mode the build uses and which ad formats it can serve.

Returns: an object, synchronously: {control: 'automatic' | 'developer', formats: {banner, mrec, interstitial, rewarded, rewarded_interstitial, app_open}} (each format true / false). On an internal error it returns {control:'automatic', formats:{}}. Needs: nothing; window.AppMintAds exists only inside the installed app.

Show only the ad UI this build can really serve:

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);

Notes: A format is true when ads are on and the build has an ad unit ID for it. In Automatic mode (control: 'automatic') every load / show / banner.attach call answers code: 'automatic_mode'; use WebToApk.showRewardedAd() / showInterstitialAd() there. Choose Ad Control → Developer-controlled in the build wizard to drive ads from the page.

AppMintAds.isReady helper#

window.AppMintAds.isReady(type)

Example

Tells you whether a full-screen ad of this type is loaded and can be shown right now.

Returns: true / false, synchronously. type: 'interstitial', 'rewarded', 'rewarded_interstitial' or 'app_open'. Needs: Ad Control → Developer-controlled and an ad unit ID for the type.

Keep a "Watch ad" button in step with the ad, using the appmint:ad status event:

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
}

Notes: banner and mrec always answer false (they are attached, not shown). An interstitial in its 60-second cooldown answers false; an app-open ad older than 4 hours answers false. In Automatic mode this is always false.

AppMintAds.load helper#

window.AppMintAds.load(type)

Example

Loads a full-screen ad so that a later show(type) can play it at once.

Returns: a Promise that resolves (never rejects) with {ok:true}, {ok:true, cached:true} when one is already waiting, or {ok:false, code, reason, message?, adCode?}. Needs: Ad Control → Developer-controlled and an ad unit ID for the type (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();

The whole life of every request also streams on the appmint:ad event:

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); };

Notes: Codes: no_fill, network, invalid_unit, internal (from AdMob), automatic_mode, unknown_type, ad_free, disabled, consent, and use_slot for banner / mrec (use AppMintAds.banner.attach). The app already preloads each full-screen type with a unit ID and loads the next one after every show, so load is mostly for knowing when the button may be enabled.

AppMintAds.show helper#

window.AppMintAds.show(type)

Example

Shows a loaded full-screen ad: interstitial, rewarded, rewarded_interstitial or app_open.

Returns: a Promise that resolves (never rejects) when the ad has closed: {ok:true, shown:true, earned, reward?} (reward = {type, amount} for the rewarded formats), or {ok:false, shown:false, code, reason, message?} when nothing was shown. Needs: Ad Control → Developer-controlled and an ad unit ID for the type.

Rewarded: call it inside the user's own tap. That tap is the user's opt-in, so the ad plays at once. Grant only when earned is true:

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.');
});

Interstitial: at a natural break. Continue whatever the answer is:

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

Notes: A rewarded or rewarded-interstitial show() that does NOT come from a user tap (a timer, page load, route change) first gets a "Watch an ad? / No thanks" screen, and "No thanks" answers declined. Never trigger rewarded formats that way. Other codes: automatic_mode, unknown_type, ad_free, disabled, consent, not_full_screen, showing, cooldown (60 s between interstitials), not_loaded (a new load starts for next time), show_failed, internal. In Automatic mode use WebToApk.showRewardedAd().

adsAppOpenEnable bridge#

window.WebToApk.adsAppOpenEnable(enabled: Boolean)

Lets the page pause/resume the app-open ad on return from another app (on by default when a unit is set).

Example

The native half of AppMintAds.appOpen.setEnabled(on): it pauses or resumes the app-open ad. Pages use AppMintAds.appOpen.setEnabled.

Returns: nothing. Needs: Ad Control → Developer-controlled and an app-open ad unit ID.

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); }

Notes: Raw signature adsAppOpenEnable(enabled). On by default when an app-open unit is set. The app-open ad shows at cold start (if it loads within 15 seconds) and when the user comes back from another app; an ad older than 4 hours is never shown.

adsConfig bridge#

window.WebToApk.adsConfig(): String

`{control, formats:{banner, mrec, interstitial, rewarded, rewarded_interstitial, app_open}}` - the ad formats this build can serve.

Example

Reads which ad formats this build can serve and which ad control mode it uses. Pages normally call AppMintAds.config(), which parses this for you.

Returns: a JSON string: {"control":"automatic"|"developer","formats":{"banner":bool,"mrec":bool,"interstitial":bool,"rewarded":bool,"rewarded_interstitial":bool,"app_open":bool}}. A format is true when ads are on and the build has an ad unit ID for it. Needs: nothing.

The public API first:

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;
  }
}

The raw call, if you do not use 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); }
}

Notes: In Automatic mode formats still tells you which units exist, but AppMintAds.load/show answer code: 'automatic_mode'; use WebToApk.showRewardedAd() / showInterstitialAd() there.

adsIsReady bridge#

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

True when a full-screen [type] is loaded and can be shown right now.

Example

Tells you whether a full-screen ad of one type is loaded and can show now (Developer-controlled ads). Pages normally call AppMintAds.isReady(type).

Returns: true / false, synchronously. type is 'interstitial', 'rewarded', 'rewarded_interstitial' or 'app_open'; 'banner' / 'mrec' always answer false. Needs: Ad Control → Developer-controlled and an ad unit ID for that type.

The public API first:

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

The raw call:

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

Notes: An interstitial inside its 60-second cooldown answers false. An app-open ad older than 4 hours answers false (Google says not to show it). In Automatic mode this is always false; use WebToApk.isRewardedAdReady() there.

adsLoad bridge#

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

Loads a full-screen [type]; the promise for [callbackId] resolves with the outcome.

Example

The native half of AppMintAds.load(type): it starts loading a full-screen ad and answers the shim's callback. Pages use AppMintAds.load(type), which returns a Promise; do not call this directly.

Returns: (through AppMintAds.load) a Promise of {ok:true}, {ok:true, cached:true} when one is already loaded, or {ok:false, code, reason, message?, adCode?}. Needs: Ad Control → Developer-controlled and an ad unit ID for the type.

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
}

Notes: Failure codes: no_fill, network, invalid_unit, internal (from AdMob, with adCode), and automatic_mode, unknown_type, ad_free, disabled, consent, and use_slot for banner / mrec (those load with AppMintAds.banner.attach). The app already preloads every full-screen type that has a unit ID, and reloads after each show. The raw signature is adsLoad(type, callbackId); its answer goes to an internal resolver, so a direct call gives you no result.

adsShow bridge#

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

Shows a loaded full-screen [type]; resolves when it closes, with earned/reward for rewarded formats. [userGesture] is the shim's `navigator.userActivation` reading - a rewarded format asked for without one gets AdMob's intro screen first (see DeveloperAds.offerRewarded).

Example

The native half of AppMintAds.show(type): it shows a loaded full-screen ad and answers when it closes. Pages use AppMintAds.show(type); do not call this directly.

Returns: (through AppMintAds.show) a Promise of {ok:true, shown:true, earned, reward?} after the ad closes (reward = {type, amount} for rewarded formats), or {ok:false, shown:false, code, reason, message?}. Needs: Ad Control → Developer-controlled and an ad unit ID for the type.

Call it from the user's tap. The shim passes navigator.userActivation.isActive as the third argument (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.');
  });
});

Notes: Raw signature adsShow(type, callbackId, userGesture). When userGesture is false for rewarded or rewarded_interstitial, the app first asks "Watch an ad? / No thanks" and a "no" answers declined. Other codes: automatic_mode, unknown_type, ad_free, disabled, consent, not_full_screen, showing, cooldown (interstitial, 60 s), not_loaded (a load starts for next time), show_failed, internal.

adsSlotAttach bridge#

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

Creates a banner/mrec overlay for the page's slot [slotId], sized to [widthCss]; resolves with the ad's size once loaded.

Example

The native half of AppMintAds.banner.attach(element, {size}): it creates a banner or medium-rectangle ad over a page element. Pages use AppMintAds.banner.attach; do not call this directly.

Returns: (through AppMintAds.banner.attach) a Promise of {ok:true, slot, width, height} in CSS pixels once the ad has loaded, or {ok:false, slot, code, message?}. Needs: Ad Control → Developer-controlled and a banner (or medium rectangle) ad unit ID.

<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>

Notes: Raw signature adsSlotAttach(slotId, type, widthCss, callbackId); type is 'banner' or 'mrec'. A WebView cannot hold a native view inside the page, so the ad is drawn over your element and follows it on scroll and resize (see adsSlotRect). At most two slots at once, and only one medium rectangle. Extra codes: duplicate_slot, too_many_slots, detached, internal, plus the load codes (no_fill, network, invalid_unit, ad_free, disabled, consent, automatic_mode).

adsSlotDetach bridge#

window.WebToApk.adsSlotDetach(slotId: String)

Removes a banner overlay.

Example

The native half of AppMintAds.banner.detach(slotOrElement): it removes a banner overlay and frees its slot. Pages use AppMintAds.banner.detach.

Returns: nothing. Needs: Ad Control → Developer-controlled.

Remove the banner before a screen where an ad does not belong (a video player, a checkout):

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' });
}

Notes: Raw signature adsSlotDetach(slotId). detach takes the element or the slot string that attach returned, not a CSS selector. An attach Promise still waiting for its ad answers {ok:false, code:'detached'}. Removing the element from the DOM also detaches the slot.

adsSlotRect bridge#

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

Internal: the slot element's current viewport rectangle (CSS px) - moves the overlay.

Example

Internal: moves a banner overlay to its element's current position. The AppMintAds.banner helper calls it for you on scroll, resize, visibility change and every 500 ms; pages use AppMintAds.banner.attach and never call this.

Returns: nothing. Needs: Ad Control → Developer-controlled, and a slot created by AppMintAds.banner.attach.

All a page does is give the slot element a place in the layout. The helper measures it and keeps the ad on top of it:

<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>

Notes: Raw signature adsSlotRect(slotId, x, y, w, h, visible), in CSS pixels relative to the viewport. The overlay is hidden while the element is off screen, has zero size, has visibility: hidden, or the page is in the background. If the element leaves the DOM, the helper detaches the slot by itself.

isInterstitialAdReady bridge#

window.WebToApk.isInterstitialAdReady(): Boolean

True when an interstitial is loaded AND past its cooldown (matches exactly what showInterstitialAd() will accept - no "ready" that then refuses to show).

Example

Tells you whether an interstitial ad is loaded AND past its 60-second cooldown, so showInterstitialAd() would show it now (Automatic ad control).

Returns: true / false, synchronously. Needs: Ads on and Full Screen Ad → Interstitial Ad.

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();
});

Notes: true here means the show will not be refused for not_loaded or cooldown. Consent or a "Remove Ads" purchase can still stop it (appmint:ad-unavailable). In Developer-controlled builds use AppMintAds.isReady('interstitial').

isRewardedAdReady bridge#

window.WebToApk.isRewardedAdReady(): Boolean

True when a rewarded ad is loaded and can be shown right now. Let the page enable/disable its "Watch ad" button off this (poll or call before showing).

Example

Tells you whether a rewarded ad is loaded and can be shown right now (Automatic ad control).

Returns: true / false, synchronously. Needs: Ads on and Full Screen Ad → Rewarded Ad.

Enable the "Watch an ad" button only when an ad is waiting:

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);

Notes: Returns false in a browser, when ads were removed by purchase, and before the first ad has loaded. After an ad is shown the next one loads by itself. In Developer-controlled builds use AppMintAds.isReady('rewarded').

notifyUserAction bridge#

window.WebToApk.notifyUserAction()

Internal (called by the injected tap counter, not creator code): one meaningful user interaction happened in the page. Counts toward the "interstitial every N actions" cadence ONLY while no URL-based navigation has ever been observed - single-HTML apps that switch screens via DOM show/hide never change the URL, so without this their navigation counter stayed at 0 forever and configured ads never showed (TicTrek complaint class, 2026-07-26). URL/SPA apps are unaffected: their first real navigation permanently switches counting back to URL signals.

Example

Counts one meaningful user action toward the "full-screen ad every N actions" setting. The app calls this itself from its own tap counter; pages normally never call it.

Returns: nothing. Needs: Ads on, a Full Screen Ad with Trigger Mode → After Navigations, and Automatic ad control.

How it works: a page that switches screens by hiding and showing DOM elements never changes its URL, so the app cannot see a "navigation". The app therefore injects a tap counter (at most one count per 2 seconds) that calls this method. As soon as the app sees one real URL change (a page load, pushState or a #hash), it counts URL changes instead and this method stops counting.

Only if your screen changes do not come from a tap (for example a keyboard or gamepad move), report them yourself:

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');
});

Notes: It does nothing when ads are off, removed by purchase, or when the build uses Ad Control → Developer-controlled (there you call AppMintAds.show() yourself). A rewarded ad reached this way is always offered with a "Watch an ad? / No thanks" question, never forced. Do not call it on every tap; that would show ads more often than you configured.

showInterstitialAd bridge#

window.WebToApk.showInterstitialAd()

Show an interstitial NOW (e.g. between levels / on a deliberate action). Not showable right now → skipped + 'appmint:ad-unavailable' with the reason.

Example

Shows a full-screen interstitial ad right now, for example between two game levels (Automatic ad control).

Returns: nothing. When the ad closes, appmint:ad-closed fires with {adType:'interstitial', earned:false}. When it cannot show, appmint:ad-unavailable fires with {adType:'interstitial', reason}. Needs: Ads on and Full Screen Ad → Interstitial Ad. Choose Trigger Mode → On Demand if only your page should decide when.

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(); }
});

Notes: The app keeps at least 60 seconds between two interstitials; a call inside that gap answers cooldown. isInterstitialAdReady() already includes the cooldown, so checking it first avoids the event. Show interstitials at natural breaks, never on every tap. In Developer-controlled builds use AppMintAds.show('interstitial').

showRewardedAd bridge#

window.WebToApk.showRewardedAd()

Show a rewarded ad NOW (user-initiated - the only policy-compliant way to show rewarded). Pair it with trigger mode "On Demand" in the wizard to get rewarded ads with NO automatic app-open/navigation ads at all. The reward is delivered back to the page via deliverRewardToPage(): window.addEventListener('appmint:reward', e => { /* e.detail = {type,amount} */ }) When the ad closes, 'appmint:ad-closed' fires with {adType:'rewarded', earned} - earned is false if the user backed out early, so grant nothing in that case. Not showable right now → skipped + 'appmint:ad-unavailable' fired with the reason.

Example

Shows a rewarded ad right now, from the user's own "Watch an ad" tap (Automatic ad control).

Returns: nothing. The outcome arrives later as events: appmint:reward {type, amount} when the ad was watched to the end, appmint:ad-closed {adType:'rewarded', earned} when it closes, or appmint:ad-unavailable {adType:'rewarded', reason} when nothing could show. Needs: Ads on, Full Screen Ad → Rewarded Ad, and Trigger Mode → On Demand so nothing shows by itself.

Grant the reward only in the reward handler, never on the tap:

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();
});

The same three moments also call page hooks, if you prefer one function each (each gets the same object as 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); };

Notes: Call it only from a click handler. Never call it from a timer, page load or route change, and never put a core feature behind it. not_loaded also starts a new load, so the next tap usually works. In Ad Control → Developer-controlled builds use AppMintAds.show('rewarded') instead, which answers with a Promise.

Generated from the app runtime and its example files on every docs build. Read it as Markdown · All families.

Checked against the shipped bridge on 2026-09-23.