# Ads on portals

Where ads come from on each host, the three rules a game follows, and the fact that filudi.com has none yet.

filudi.com has no ad network today. Both ad kinds answer `unavailable` with reason `host` there, and the
console shows nothing about revenue. On CrazyGames, Poki and Playgama the same calls show the portal's ads.
Write the game so that it is complete without them.

## Where ads come from

| Host       | Rewarded                                                                          | Interstitial                          | Pacing                                                                                       |
| ---------- | --------------------------------------------------------------------------------- | ------------------------------------- | -------------------------------------------------------------------------------------------- |
| filudi.com | `unavailable: host`                                                               | `unavailable: host`                   | The SDK keeps a 120 s interval so the day an ad network exists, nothing changes in your game |
| CrazyGames | `requestAd('rewarded')`                                                           | `requestAd('midgame')`                | The portal's                                                                                 |
| Poki       | `rewardedBreak`: `completed` on `true`, `skipped` on `false`                      | `commercialBreak`: always `completed` | The portal's                                                                                 |
| Playgama   | `showRewarded`: `rewarded` then `closed` is `completed`, `closed` alone `skipped` | `showInterstitial`                    | The portal's                                                                                 |
| mock       | What `mock.ads` says: `fill`, `no-fill`, `adblock`, `error`                       | Same                                  | 120 s                                                                                        |

On filudi.com an ad request goes to the hub, which answers with a result. No ad script runs inside your
bundle on any host: the SDK loads the portal's script on the portal's own page.

## The three rules

1. Bracket play with `gameplay.start()` and `stop()`, never around an ad. The SDK stops play before an ad
   and starts it again after.
2. Mute on `sdk.ads.on('start')`, unmute on `sdk.ads.on('end')`. Not when you request the ad: a refused ad
   never starts and the game would stay silent.
3. Grant the reward on `status === 'completed'` only. Hide the button when `sdk.ads.available().rewarded`
   is false, and read that each time you draw the button.

<CodePanel title="The three rules in code">
  <Fragment slot="javascript">
    ```js
    sdk.ads.on('start', () => audio.mute());
    sdk.ads.on('end', () => audio.unmute());

    function showGameOver() {
      lifeButton.hidden = usedLife || !sdk.ads.available().rewarded;
    }

    lifeButton.addEventListener('click', async () => {
      lifeButton.hidden = true;
      if ((await sdk.ads.rewarded()).status === 'completed') secondLife();
    });
    ```

  </Fragment>
  <Fragment slot="typescript">
    ```ts
    sdk.ads.on('start', () => audio.mute());
    sdk.ads.on('end', () => audio.unmute());

    function showGameOver(): void {
      lifeButton.hidden = usedLife || !sdk.ads.available().rewarded;
    }

    lifeButton.addEventListener('click', async () => {
      lifeButton.hidden = true;
      if ((await sdk.ads.rewarded()).status === 'completed') secondLife();
    });
    ```

  </Fragment>
</CodePanel>

## Where to put an interstitial

At a natural break, after `gameplay.stop()`: every few game overs, between levels, never in the middle of
play and never before the first frame. The SDK refuses one inside the host's interval with `too-soon`; a
game that asks too often sees that status and nothing else. Keep your own counter (every third game over)
so the game feels the same on every host.

## Policy and consent

`policy.personalizedAds` from `init()` is false on a kids site or without consent; the portal or the hub
applies it, your game does not have to. Without ad consent on filudi.com the answer is `unavailable: policy`.
`sdk.on('consent', ...)` tells you when the player changes it, and `sdk.ads.available()` follows.

## Not offered yet

No ad network on filudi.com, no revenue share, no payment. When that changes, the SDK calls stay the same;
this page and the console will say what is new.
