View as Markdown

Apple TV (tvOS)

This guide covers serving Ezoic video ads from tvOS apps with Google's IMA SDK for tvOS. The tag is player-agnostic, so any VAST-capable player works the same way.

Tag template

https://g.ezoic.net/ezoic/videoad/vast?bundle=<APP_STORE_ID>&app_domain=<YOUR_EZOIC_DOMAIN>&app_name=<APP_NAME>&storeurl=<APP_STORE_URL>&adunit=<YOUR_VIDEO_AD_UNIT>&ifa=<IDFA>&ifa_type=idfa&lmt=<0|1>&devicetype=3&plcmt=1&v=4&w=1920&h=1080&startdelay=0&content_id=<ID>&content_title=<TITLE>&content_genre=<GENRE>&content_cat=<IAB_CAT>&content_len=<SECONDS>&livestream=<0|1>&us_privacy=<USP>&cb=<RANDOM>
  • bundle is your numeric App Store ID, the number in your store URL. It is not the Xcode bundle identifier.
  • ifa_type is idfa.

App Tracking Transparency

The IDFA is gated behind App Tracking Transparency (ATT). On tvOS, request authorization with ATTrackingManager. The prompt appears on the TV screen.

ATT state What to send
Authorized ifa=<real IDFA> and lmt=0
Denied, restricted or not determined ifa=<zeroed IDFA as returned> and lmt=1

Never fabricate or persist an IDFA. Expect a meaningful share of tvOS sessions to send lmt=1. For those sessions, the content metadata and app identity carry more of the request, so fill them in fully.

IMA SDK integration (Swift)

let adsLoader = IMAAdsLoader(settings: nil)
let display = IMAAdDisplayContainer(adContainer: adContainerView, viewController: self)
let request = IMAAdsRequest(
    adTagUrl: buildEzoicTagUrl(for: video),
    adDisplayContainer: display,
    contentPlayhead: contentPlayhead,
    userContext: nil)
adsLoader.requestAds(request)

URL-encode every dynamic value when you build the tag URL.

Open Measurement

IMA for tvOS bundles the OM SDK, and verification runs automatically for ads that carry it. The tag declares OMID support for non-Roku CTV requests, so you do not need api. If you run your own OM session outside IMA, also send omidpn and omidpv.

Behaviour notes

  • An empty VAST document is a no-fill. IMA raises its "VAST response empty" error. Fall through to content.
  • Request one ad per break, with startdelay. Send pod and slot for multi-ad breaks.

Go-live checklist

  • bundle is your numeric App Store ID, the store listing is live, and app-ads.txt is on your developer domain
  • The ATT flow is in place, and ifa and lmt reflect the real authorization state
  • devicetype=3, real w and h, and startdelay are sent
  • adunit is set to your normal video ad unit name
  • Content metadata is populated
  • The app is registered under Mobile & CTV Apps