Rewarded Ads
Rewarded ads let a publisher grant a user some benefit — unlocking an article, extra content,
an in-game item — in exchange for watching a full-screen ad to completion. Unlike regular ad
slots, a rewarded ad is not defined in slots and is not requested automatically by the ad
pipeline. It is explicitly requested at runtime via moli.rewardedAd(), typically from a button
click.
Overview
rewardedAd() runs a waterfall: within a single call, moli attempts each configured
channel in priority order, falling through to the next channel immediately if the current
one has no fill. The call resolves once a channel grants the reward, the user cancels, or every
channel is exhausted.
Two channels are supported:
gam— Google Ad Manager Rewarded Ads for Webwelect— Welect Ad Chooser
Every business outcome — including a complete no-fill — resolves the promise. It only rejects on unexpected technical exceptions, e.g. a crash in an underlying channel integration.
Usage
document.getElementById('unlock-article').addEventListener('click', () => {
window.moli.que.push(function (moliAdTag) {
moliAdTag.rewardedAd().then(result => {
switch (result.state) {
case 'granted':
// result.payload: { amount: number; type: string }
unlockArticle(result.payload);
break;
case 'canceled':
// the user closed the ad before finishing it
break;
case 'empty':
// no channel could fill the request, or the feature isn't configured
break;
case 'error':
// result.reason: 'already-in-progress' | 'ad-tag-error'
break;
}
});
});
});
Result states
state | Meaning |
|---|---|
granted | The user completed the ad. channel and payload describe which channel filled and what was granted. |
canceled | The user closed the ad before a reward was granted. channel names the channel that was showing. |
empty | No channel filled the request, or rewardedAd is not configured / disabled. |
error | The call could not be performed. See reasons below. |
error.reason:
already-in-progress— anotherrewardedAd()call is still in flight. Only one rewarded ad can run at a time; calling it again while one is active resolves immediately with this error instead of queueing.ad-tag-error— the ad tag is in theerrorstate, so no rewarded ad can be requested.
Timing: calls queue until finished
rewardedAd() is gated on the same pipeline state as refreshAdSlot(). Calls made in
configurable, configured, requestAds, or spa-requestAds are queued and resolve once
the pipeline reaches finished / spa-finished. This guarantees consent (CMP) has been
resolved before any rewarded ad script is loaded — a rewarded flow never fires ahead of the main
ad pipeline's init/configure stages. Calling rewardedAd() while in the error state
resolves immediately with { state: 'error', reason: 'ad-tag-error' }.
In practice this means it's safe to wire up the button click handler immediately on page load —
the first click, even before requestAds() has completed, is queued rather than dropped or
rejected.
Configuration
rewardedAd is configured under globalAuctionContext.rewardedAd:
const moliConfig: Moli.MoliConfig = {
slots: [ /* ... */ ],
globalAuctionContext: {
rewardedAd: {
enabled: true,
priority: ['gam', 'welect'],
timeoutMs: 5000,
gam: {
adUnitPath: '/1234/publisher/rewarded'
},
welect: {
bundleUrl: 'https://static.welect.de/p/bundles/example.js',
payload: { amount: 1, type: 'article' }
}
}
}
};
Options
enabled(boolean) — turns the feature on. If disabled,priorityis empty, or a prioritized channel is missing its config block,rewardedAd()resolves with{ state: 'empty' }.priority(RewardedAdChannel[]) — the channels to attempt, in order.['gam', 'welect']tries GAM first, then Welect on no-fill;['welect', 'gam']reverses that.timeoutMs(number) — per-channel attempt budget, not a total budget for the whole waterfall. Forgam, this is how long to wait for therewardedSlotReadyevent before the slot is destroyed and the attempt counted as no-fill. Forwelect, this covers the SDK bundle download plus thecheckAvailabilitycall.gam(optional) — required ifpriorityincludes'gam'.adUnitPath— the ad unit path for the rewarded slot. May contain ad unit path variables.
welect(optional) — required ifpriorityincludes'welect'.bundleUrl— the partner-specific Welect SDK bundle URL, e.g.https://static.welect.de/p/bundles/<a-bundle-id>.js.payload— the static reward payload ({ amount, type }) granted on a successful Welect session. Welect has no dynamic payload, so this value is used for everygrantedresult on this channel.checkToken(boolean, defaulttrue) — see Welect token preflight below.
Like other globalAuctionContext settings, rewardedAd supports the
module config override pattern via Overridable<RewardedAdConfig>.
Waterfall example
globalAuctionContext: {
rewardedAd: {
enabled: true,
priority: ['welect', 'gam'],
timeoutMs: 4000,
welect: {
bundleUrl: 'https://static.welect.de/p/bundles/example.js',
payload: { amount: 1, type: 'article' },
checkToken: true
},
gam: {
adUnitPath: '/1234/publisher/rewarded'
}
}
}
With this config, a rewardedAd() call:
- Checks for a valid Welect token — if present, grants immediately with the Welect payload.
- Otherwise attempts Welect. On no-fill, falls through to GAM.
- Attempts GAM. On no-fill, resolves with
{ state: 'empty' }.
Only one call can be in flight at a time; a second rewardedAd() call made while the first is
still resolving immediately gets { state: 'error', reason: 'already-in-progress' }.
API Reference
See the MoliTag.rewardedAd()
API reference for the full method signature, and
RewardedAdConfig for
the configuration type.