Ad tag FAQ
Answers to the common questions about placing an ad tag on a page — why the ad is in an iframe, rendering into your own container, Epom tags inside Google Ad Manager, slot sizing and layout shift, fit container, several tags per page, several ads per request, rendering the ad yourself, auto-refresh and switching serving domains.
Short answers to the questions publishers ask most once a tag is on a page: how the ad is wrapped, where it renders, how it behaves inside Google Ad Manager, how to size the slot, and what the tag can and cannot do. Setting up the tag itself is on Ad tags, invocation codes and the API.
Who this is for
Publishers placing tags on their pages and the network managers who support them.
Why is the ad inside an iframe? What does the Ad wrapper setting do?
The placement’s Ad wrapper (Settings tab) decides how the Universal JS / Mount JS tag puts the ad on the page:
| Ad wrapper | What happens | Use it for |
|---|---|---|
| Friendly Frame (default) | The ad is written into a same-origin iframe | Most display ads — the ad’s scripts and styles cannot break your page |
| Sandboxed Frame | The same iframe with a sandbox attribute that still allows scripts, forms, pop-ups and top navigation | Untrusted creatives you still want to click through |
| No-redirect Frame | The sandbox without top navigation: the ad can only take the visitor to another page after a click | Stopping auto-redirect creatives |
| Without Wrapper | The ad is written straight into the page | Stickers, catfish, pops and other codes that position themselves on the page, and partner codes that need the page’s DOM |
Can the tag render into my own element id (a custom container)?
Not by naming an id — the Universal JS tag has no attribute for a target element. The ad renders
inside the tag’s own <ins> element, so you choose the spot by placing the <ins> there:
put it inside your container (<div id="sidebar-ad"><ins class="…" data-key="…"></ins></div>)
and style the container.
Corner case — do not give the
<ins>anid. The loader fills only slots that have no id yet: it assigns its own id to each<ins>it takes, and treats one that already has an id as filled. An<ins id="my-slot" …>therefore stays empty. Put your id on a wrapper element.
When the container is created by your own script — a single-page app, a feed, a modal — use the
Mount JS tag instead: it takes the container element as an argument and inserts the slot
into it. Or insert the <ins> yourself and call init() (see
The JavaScript API).
Epom tag inside Google Ad Manager: which placement, who counts what, and the click macro
To sell Epom demand through a Google Ad Manager (GAM) line item, paste the placement’s Universal JS tag into a GAM third-party creative of the slot’s size.
- One Epom placement per GAM slot you want to report on. The tag’s
data-keydecides the placement, and with it the zone, site and every Epom report line. Several GAM ad units can share one placement; then tell them apart withdata-channel(or adata-cp-value) set per creative. - Who counts what. GAM counts an impression for its creative — the Epom tag — when it renders, whether or not Epom then has an ad. Epom counts requests, its own impressions and its no-ads. So GAM’s number for the line item is close to Epom’s Requests, not to Epom’s Impressions; the gap is Epom’s no-fill.
- Clicks in GAM’s report. Put GAM’s click macro in the tag’s third-party click prefix:
data-click="%%CLICK_URL_UNESC%%". Epom records the click first, then sends the visitor through that prefix with the landing page URL-encoded at its end, so GAM records the click and forwards to the advertiser. - It renders inside GAM’s iframe. GAM serves third-party creatives in its own frame, usually on a different domain, so formats that have to reach the page — catfish, sticky, overlays on the publisher’s player — cannot get out of it. Use display-type demand through GAM, and put page-level formats on the page directly.
How do I size the slot and avoid layout shift (CLS)?
The tag inserts an inner container sized to the ad: on a Site Placement the placement’s size, on
Mobile Site and Non-standard placements the served banner’s size. Until the response arrives the
<ins> has no height, so content below it jumps when the ad lands. To avoid that, reserve the
space on your own wrapper element around the <ins> — for a 300×100 mobile top banner,
<div style="min-height:100px">…</div>. The loader overwrites the <ins> element’s own inline
style when it takes the slot, so CSS on the <ins> needs !important to win.
When no ad is served the slot collapses to height 0.
My ads are 0 px high in a Non-standard or Mobile Site placement / how do I fit the container?
Turn on Fit container (Settings tab; Mobile Site and Non-standard placements only). The
<ins>, its inner container and the ad’s iframe then all take width:100%; height:100% of the
element you put the tag in — so give that element a size. Without Fit container the ad gets the
banner’s own pixel size.
Can I put several tags on one page (call the ad code more than once)?
Yes. Include the script once and put one <ins> per placement — each with its own data-key.
Every slot sends its own request and gets its own ad; a second copy of the script is harmless.
The <ins> must keep exactly the class from the tag: a slot with an extra CSS class is
skipped. Slots added after load are filled by init() (see The JavaScript API).
The tag does not change for programmatic demand — the same code serves direct campaigns and
DSP bids.
Can one request return several ads?
The Universal JS, Mount JS and Direct URL tags return one ad per request — use one slot per
ad. Several ads in one response exist only on the API (format=xml-bids with maxBids), the
native API (count) and video pods (maxAds).
Can I render the ad myself instead of using the script?
Yes — call the placement’s API request URL (the API tab) server-side or from your app with
format=json, and insert the returned markup. Two things to keep: the impression is counted
when the returned markup runs (it carries its own impression script) — if you take only the
image and click URL out of a JSON answer, fire the returned impression URL yourself when you
show it; and send clientIp, clientUa and requestUrl from a server, or geo and device
targeting see your server instead of the visitor.
How does auto-refresh work?
Refresh after (sec) on the placement’s Basic info card (needs Auto refresh)
reloads the slot every that many seconds while the tab is visible — it does not check whether the
slot is on screen. Each refresh is a new request and, when the new ad renders, a new impression.
0 turns it off.
Can I switch my tags to another serving or CDN domain by editing the URL?
No. Each serving domain has its own generated script, class name and request encryption key, so a tag copied for one domain and edited by hand to another will not work. Pick the new domain in Ad Tags & API → Settings → Domain and copy the tag again — and replace it on the page. Tags already on pages keep the domain they were copied with.
Corner cases and gotchas
Corner case: an
<ins>with anidof its own stays empty — see Can the tag render into my own element id. The gotchas of the Settings tab (which settings change tags already on pages, when the Domain selector appears) are on Ad tags, invocation codes and the API.