# Request ads on audio-only content

The IMA HTML5 SDK supports audio ads with a similar setup as video ads but with
a few key differences. For any part of the IMA setup not covered in this guide,
see the [HTML5 Get started
guide](https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side).

## Use of an \<audio\> tag for content playback

The constructor for
[`AdDisplayContainer`](https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side/reference/class/google.ima.AdDisplayContainer#google.ima.AdDisplayContainer.constructor)
takes a second argument named `videoElement` which IMA tracks as the content
player. This argument accepts both a `<video>` or `<audio>` tag. For audio
content and ads, this guide recommends using an `<audio>` tag to construct an
`AdDisplayContainer`. If you have video content, you can use a `<video>` tag for
showing a mix of audio and video ads:

#### index.html

    <audio id="audio-player"></audio>
    <div class="ad-container"></div>

#### ads.js

    audioPlayer = document.getElementById('audio-player');
    adContainer = document.getElementById('ad-container');
    adDisplayContainer = new google.ima.AdDisplayContainer(adContainer,
    audioPlayer);

## Hide the AdDisplayContainer

The IMA HTML5 SDK still requires an `AdDisplayContainer` even if there is no
display portion to the ads or content. For this reason, we recommend hiding the
`AdDisplayContainer`. See an example of how you can hide the element:

#### style.css

    .ad-container {
      display: none;
    }

## Custom controls

Because the `AdDisplayContainer` is hidden, custom controls are needed to handle
playback during ad breaks. `AdsManager` has methods that can be used to
implement these custom controls:

- [`pause()`](https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side/reference/interface/google.ima.AdsManager#google.ima.AdsManager.pause)
- [`resume()`](https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side/reference/interface/google.ima.AdsManager#google.ima.AdsManager.resume)
- [`setVolume()`](https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side/reference/interface/google.ima.AdsManager#google.ima.AdsManager.setVolume)

## Handle skippable ads

Because there is no visible `AdDisplayContainer`, the IMA SDK cannot show a
**Skip ad** button. To handle skippable ads, implement the following IMA
methods:

- [`AdsManager.getAdSkippableState()`](https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side/reference/interface/google.ima.AdsManager#google.ima.AdsManager.getAdSkippableState)
- [`AdEvent.getAdData()`](https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side/reference/interface/google.ima.AdEvent#google.ima.AdEvent.getAdData)
- [`Ad.getSkipTimeOffset()`](https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side/reference/interface/google.ima.Ad#google.ima.Ad.getSkipTimeOffset)

The following sample code demonstrates how to do this.

#### ads.js

You can set up an `updateSkippable` function to determine whether and when an ad
can be skipped. This function should be called on each `AD_PROGRESS` IMA event.
See the
[Getting started guide](https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side#triggering-play-and-pause-events)
for directions on how to set up listeners for IMA events.

    function onAdsManagerLoaded(adsManagerLoadedEvent) {
      adsManager = adsManagerLoadedEvent.getAdsManager(
        audioPlayer);

      ...

      adsManager.addEventListener(
        google.ima.AdEvent.Type.AD_PROGRESS,
        onAdEvent);

      ...

    }

    function onAdEvent(adEvent) {
      const ad = adEvent.getAd();
      if (ad) {
        currentAd = ad; // currentAd is defined outside of this functions scope.
      }
      switch (adEvent.type) {

        ...

        case google.ima.AdEvent.Type.AD_PROGRESS:
          // See https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side/reference/interface/google.ima.AdProgressData
          const adProgressData = adEvent.getAdData();

          updateSkippable(
            adProgressData.currentTime,
            currentAd.getSkipTimeOffset()
          );
          break;
        ...

      }
    }

    /**
       * Called when there may be a change in the skippable state.
       * @param {number} currentTime The current time of the
       * currently playing ad.
       * @param {number} skipTimeOffset The number of seconds of playback
       * before the ad becomes skippable. -1 is returned for non skippable
       * ads or if this is unavailable.
       */
      updateSkippable(currentTime, skipTimeOffset) {
        const isAdSkippable = skipTimeOffset !== -1;
        const isSkipCurrentlyAllowed = adsManager.getAdSkippableState();
        const timeTillSkipInSeconds = Math.ceil(skipTimeOffset - currentTime);
        updateSkipUI(
            isAdSkippable, isSkipCurrentlyAllowed, timeTillSkipInSeconds);
      }

Unlike with video ads, IMA is not able to provide a skip button for audio ads.
Developers must add custom UI for skippable ads, which can be done with a
simple `<button>` tag. This `updateSkipUI` function updates the skip button
based on if the ad is skippable, if the ad is currently skippable, and
how much time is remaining until the ad becomes skippable. It makes use of the
`'.hidden'` class, which is not provided by IMA. The `.hidden` class adds
`display: none;` to the `<button>`.

    /**
     * Updates the skip button UI.
     * @param {boolean} isAdSkippable if the current ad is a skippable ad.
     * @param {boolean} isSkipCurrentlyAllowed if the ad can be skipped now.
     * @param {number} timeTillSkipInSeconds time until the ad can be skipped in
     * seconds.
     */
    updateSkipUI(isAdSkippable, isSkipCurrentlyAllowed, timeTillSkipInSeconds) {
      if (isAdSkippable) {
        skipButton.classList.remove('hidden');
        if (isSkipCurrentlyAllowed) {
          skipButton.textContent = 'Skip ad';
          skipButton.disabled = false;
        } else {
          skipButton.textContent = `Skip in ${timeTillSkipInSeconds} seconds`;
          skipButton.disabled = true;
        }
      } else {
        skipButton.classList.add('hidden');
      }
    }

Finally, set a listener for user clicks on your custom skip button. To skip ads,
call the
[`adsManager.skip()`](https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side/reference/interface/google.ima.AdsManager#google.ima.AdsManager.skip)
function.

    skipButton.addEventListener('click', () => {
      adsManager.skip();
    });

These are the main changes needed to set up the IMA SDK with audio ads. For
support with implementation issues, reach out through the
[Ad Manager Help Center](https://support.google.com/admanager/contact/contact_us_ima_sdk)
for support.