---
title: "Ad tag FAQ"
description: "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."
type: "reference"
audience: [network-manager, publisher, admin]
keywords: [FAQ, iframe, ad wrapper, custom container, element id, Google Ad Manager, GAM, third-party creative, click macro, CLS, layout shift, slot size, fit container, several tags, multiple ads, render ad yourself, auto-refresh, serving domain, CDN domain]
ui_path: "Account → Publishers → site → zone → placement → Ad tags & API"
---

Fetch the complete documentation index at: https://epom.com/ad-server/docs/llms.txt. Use this file to discover all available pages before exploring further. Append .md to any documentation page URL to get its markdown version.

# Ad tag FAQ

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](https://epom.com/ad-server/docs/guides/inventory/ad-tags-and-api.md).

## 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>` an `id`.** 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](https://epom.com/ad-server/docs/guides/inventory/ad-tags-api-and-vast.md#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-key` decides 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 with `data-channel` (or a `data-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](https://epom.com/ad-server/docs/guides/inventory/ad-tags-api-and-vast.md#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 an `id` of its own stays empty — see
> [Can the tag render into my own element id](#can-the-tag-render-into-my-own-element-id-a-custom-container).
> 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](https://epom.com/ad-server/docs/guides/inventory/ad-tags-and-api.md#corner-cases-and-gotchas).

## Related

- [Ad tags, invocation codes and the API](https://epom.com/ad-server/docs/guides/inventory/ad-tags-and-api.md)
- [API tab, VAST tags and the JavaScript API](https://epom.com/ad-server/docs/guides/inventory/ad-tags-api-and-vast.md)
- [Copy and preview an ad tag](https://epom.com/ad-server/docs/guides/inventory/ad-tags-preview.md)
- [Tags and preview troubleshooting](https://epom.com/ad-server/docs/troubleshooting/tags-and-preview.md)
- [Invocation codes reference](https://epom.com/ad-server/docs/reference/invocation-codes.md)