View as Markdown

Server-side (SSAI)

This guide covers calling the Ezoic VAST tag from a server-side ad insertion (SSAI) service, a stitcher, or any other server-side fetcher. Server-side integrations have two failure modes that do not exist on the device. Read the first two sections before anything else.

Rule 1: Forward the viewer's IP and user agent

The tag uses the IP and user agent it receives. Your stitcher's requests carry your data centre's values, which destroy geo targeting and most demand. Send the viewer's values on every request:

&ua=<viewer's user agent, URL-encoded>&ip=<viewer's IP>

Most SSAI platforms expose these as session values or macros. For example, AWS MediaTailor uses [session.client_ip] and [session.user_agent]. Check your vendor's macro table. For IPv6 sessions, send ipv6=.

Rule 2: Check that your macros expand

The tag drops any parameter whose whole value is an unexpanded macro, such as [IFA], {{BUNDLE}} or %%US_PRIVACY%%. The request still succeeds, but you lose that signal and the revenue attached to it. You get no error.

So do not judge the integration by whether it returns VAST. Capture a real session request and check that each parameter carries a concrete value. See Testing and troubleshooting.

Tag template

Replace the {{MACRO}} names with your vendor's macro syntax.

https://g.ezoic.net/ezoic/videoad/vast?bundle={{APP_BUNDLE}}&app_name={{APP_NAME}}&storeurl={{APP_STOREURL}}&app_domain=<YOUR_EZOIC_DOMAIN>&adunit=<YOUR_VIDEO_AD_UNIT>&ifa={{DEVICE_IFA}}&ifa_type={{IFA_TYPE}}&ua={{USER_AGENT}}&ip={{DEVICE_IP}}&lmt={{LMT}}&us_privacy={{US_PRIVACY}}&gdpr={{GDPR}}&consent={{GDPR_CONSENT}}&content_id={{CONTENT_ID}}&content_title={{CONTENT_TITLE}}&content_genre={{GENRE}}&content_cat={{IAB_CATEGORY}}&content_len={{CONTENT_DURATION}}&livestream={{IS_LIVE}}&pod={{POD_ID}}&slot={{POD_SLOT}}&minduration={{MIN_DURATION}}&maxduration={{MAX_DURATION}}&devicetype=3&plcmt=1&v=3&w=1920&h=1080&cb={{CACHEBUSTER}}

Set these once: app_domain (your Ezoic domain), adunit (your normal video ad unit name), devicetype=3, plcmt=1, ssai if you declare it, and v. Use v=3 unless your pipeline needs more.

Declare your SSAI level

Some buyers require this declaration before they buy SSAI inventory. Send ssai only when you know the value.

ssai Meaning
1 All client-side. Not server-side at all.
2 Assets stitched server-side, tracking pixels fired client-side.
3 All server-side, stitching and tracking.

A full server-side stitcher usually sends 3. A stitcher that stitches assets while the player fires tracking usually sends 2. If you are not stitched, omit the parameter.

Ad pods: sequential single-slot requests

The tag returns one ad per request, with no VMAP. To fill a break with several ads:

  1. Request each slot separately.
  2. Send the same pod for the whole break and an incrementing slot, starting at 1. Buyers use these to avoid showing the same creative twice in one break.
  3. Use a fresh cb for each call.
  4. Set minduration and maxduration per slot if the break has a fixed total length. For a 90-second break, for example, request slots with maxduration=30.

Timeout

The auction budget defaults to 3500 ms. If your stitcher has a tighter per-tag timeout, send tmax with your real budget in milliseconds so the auction finishes inside your window. The tag keeps a 50 ms network buffer, so a request that ends early can still get a fill if the auction is quick. Set tmax to what your stitcher really allows, and test that value end to end.

Response handling

All three response shapes return HTTP 200, after following any 302:

  • VAST with an <Ad> element: stitch it.
  • Empty VAST document: no fill. Skip the slot, or move down your waterfall.

A response can contain more than one <Ad>. If your stitcher takes only one, use the first. The others are same-request fallbacks, not a pod.

Identity notes

  • ifa and ifa_type come from the device session, passed through your stitcher's session macros. If they are missing, buyers discount the request, as they would on the device.
  • If you send universal IDs such as UID2 or RampID, pass them in eids. Keep to the size and shape limits in Parameters.
  • Send schain only when there are intermediaries between the content owner and Ezoic. Serialize it per the IAB spec exactly, because a malformed chain is dropped.

Go-live checklist

  • Viewer ip and ua are forwarded from session values. Check they are not your server's values.
  • Every macro expands with a real session. No literal [...] or {{...}} reaches the tag.
  • adunit, app_domain, devicetype=3 and plcmt=1 are set.
  • ssai is declared, or omitted when you are not stitched.
  • pod and slot are sent on multi-ad breaks, with a fresh cb per call.
  • tmax fits inside your stitcher's per-tag timeout.
  • v matches what your transcoding pipeline accepts.