---
title: "Track impressions of a partner's ad code (sticker, banner, pop script)"
description: "Count impressions of a third-party ad code in Epom — wrap the code in an HTML Code banner, get an impression pixel URL for a partner, add extra third-party impression trackers to your banner, detect that the partner's ad actually rendered, and use cache-busters."
type: "howto"
audience: [network-manager]
keywords: [third-party code, partner code, wrap ad code, sticker, impression pixel]
ui_path: "Account → Advertisers → campaign → HTML Code banner; Account → Publishers → Click-through placement → Show tracking URLs"
---

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.

# Track impressions of a partner's ad code (sticker, banner, pop script)

A partner gives you their ad code — a sticker, a catfish, a banner script — and you want Epom to
count its impressions (and, ideally, only the ones that really rendered). This page lists the
four ways to do it, from the simplest to the most precise, and the traps in each.

## Who this is for

Network managers and publishers. You need edit access to an advertiser (to create the banner)
and to the site where the code runs.

## Prerequisites

- The partner's ad code, or their agreement to fire a pixel URL you give them.
- An advertiser and campaign to hold the banner, and the site the code runs on.
- Role permissions for the option you pick: the **Code** banner content type for Option 1 and 4;
  **Click Through Placements** and an image banner type (**Local File** or **External File**) for
  Option 2; **Banner Third-Party Tracking Code** or **Placement Third-Party Tracking Code** for
  Option 3.
- Access to the page's HTML, to replace the partner's code with the Epom tag (Options 1 and 4).

## Steps

Pick the option that matches what the partner gives you.

### Option 1 — wrap the partner’s code in an HTML Code banner

This is the standard way: Epom serves the partner's code, so Epom counts every time it serves it.

1. **Account → Advertisers → advertiser → campaign → New banner**, type **HTML Code**. Pick the
   placement type of the slot (a sticker or catfish that positions itself on the page belongs on
   a **Non-standard Placement**).
2. Paste the partner's code into **Code**. Keep their click macros; if they accept a click URL,
   put `$$CLICK_REDIRECT_URL$$` in front of their landing page so Epom counts clicks too
   ([Fix click tracking on third-party ad tags](https://epom.com/ad-server/docs/troubleshooting/click-tracking-third-party-tags.md)).
3. Create a placement for the slot and link the banner.
4. On the placement, **Ad Tags & API → Settings → Ad wrapper**: a code that positions itself on
   the page (sticker, catfish, pop) needs **Without Wrapper** — it is written straight into the
   page, so it can reach the page layout. In a frame it can only draw inside the frame.
5. Put the placement's **Universal JS** tag on the page instead of the partner's code.

**When the impression is counted:** Epom adds a small impression script to the markup it
delivers, and the impression is counted when that script runs in the browser — that is, when the
partner's code has been **delivered to the page**, not when the partner's own ad has finished
loading. If the partner's code then shows nothing (no fill on their side, blocked by an ad
blocker), Epom still has an impression. Option 4 closes that gap.

> **Corner case — the banner's *Third-Party tracking codes* card does nothing on an HTML Code
> banner.** Banner-level tracking codes are added to image, template and OpenRTB banners only.
> On an HTML Code banner put the extra pixel inside the code itself; the **placement**'s
> tracking codes still apply.

### Option 2 — give the partner an Epom impression pixel URL

When the partner serves the ad themselves and can fire a pixel for you:

1. Create a **Click-through Placement** on the site.
2. Link any **image** banner (Local File or External File) to it — the banner is only there to
   carry the IDs; tracking URLs are generated for image and video banners only.
3. Open the placement's **Ad Tags & API → Show tracking URLs**. Each linked banner has an
   **Impression URL** (`…/impression.gif?…`), a **Click URL** and two click-through URLs.
4. Give the partner the Impression URL to fire as a 1×1 image when their ad renders, and the
   click-through URL as their click destination.

The impression URL carries a hash of the banner, placement and campaign, so it cannot be
re-pointed at another banner. Full field list:
[Click-through placements](https://epom.com/ad-server/docs/guides/inventory/placement-mobile-email-other.md#click-through-placements).

### Option 3 — add an extra third-party impression tracker to your banner

The other direction: your banner should also fire the partner's or a verification vendor's
pixel. Use the **Third-Party tracking codes** card on the banner (or on the placement, to cover
every banner it serves) — paste the vendor's snippet, for example:

```html
<img src="https://verify.example/imp?camp=42&cb=$$RANDOM$$" width="1" height="1" alt="">
```

The card takes an **HTML snippet**, not a bare URL, and one snippet per country plus a Global
fallback ([Third-party tracking codes](https://epom.com/ad-server/docs/guides/conversions/third-party-tracking-codes.md)). It is applied to image,
template and OpenRTB banners; video banners use the **VAST event tracking pixels** of the
VAST tracking card instead.

> **Corner case — firing for one domain only.** A tracking code can be limited by **country**,
> not by site domain or custom parameter. To fire it on one host only, make two copies of the
> banner — one targeted at that domain, one excluding it — and put the tracker on the first.

### Option 4 — detect that the partner’s ad actually rendered

To count only the impressions where the partner's ad really appeared, let the page watch for it
and fire a pixel when it shows up. Wrap the partner's code (Option 1) and add a small observer
after it in the same HTML Code banner. The example fires an Option-2 impression URL when an
element matching the partner's container appears, and gives up after 3 seconds:

```html
<div id="partner-slot"><!-- partner's code here --></div>
<script>
(function () {
  var slot = document.getElementById('partner-slot');
  var fired = false;
  function fire() {
    if (fired) { return; }
    fired = true;
    new Image().src = 'https://<ad-serving-domain>/impression.gif?...&cb=' + Date.now();
    observer.disconnect();
  }
  var observer = new MutationObserver(function () {
    if (slot.querySelector('iframe, img, .partner-ad')) { fire(); }
  });
  observer.observe(slot, { childList: true, subtree: true });
  setTimeout(function () { observer.disconnect(); }, 3000);
})();
</script>
```

Adjust the selector to what the partner's ad inserts. A sticker that attaches itself to
`document.body` instead of its own container needs `observe(document.body, …)` and a more
specific selector. If you also want a count of the times it did **not** render, fire a second
URL — for example a [conversion action pixel](https://epom.com/ad-server/docs/guides/conversions/conversion-actions.md)
(`…/action.gif?key=<action key>`) — from the timeout.

> **Note — `ad-loaded` is not a render signal for the partner's ad.** The Universal JS tag
> fires an `ad-loaded` event on the slot when **Epom** has inserted its markup
> ([The JavaScript API](https://epom.com/ad-server/docs/guides/inventory/ad-tags-api-and-vast.md#the-javascript-api)). For a wrapped
> third-party code that moment is "the partner's code was delivered", the same moment the
> impression is counted.

## Cache-busters and the `rnd` parameter

- Epom's own tag and tracking URLs do not need a cache-buster from you: the Universal JS tag
  adds a timestamp (`t=`) to every request and every impression URL is unique.
- A `rnd=` (or `cb=`, `ord=`) parameter you add to an Epom URL is **ignored** by the server —
  harmless, not required.
- For **third-party** pixels inside your codes, use `$$RANDOM$$` (a random integer) or
  `$$TIMESTAMP$$` (milliseconds) where the vendor wants its cache-buster, so the browser and
  CDNs never serve the pixel from cache.

## Corner cases and gotchas

> **Corner case — numbers will not match the partner's.** With Option 1 Epom counts delivery of
> the code, the partner counts their own ad render or their own view; Option 4 narrows the gap
> but timeouts and blockers still differ. See
> [Analytics discrepancies](https://epom.com/ad-server/docs/troubleshooting/analytics-discrepancies.md).

> **Corner case — a sticker in a frame.** With the default **Friendly Frame** wrapper a code
> using `position: fixed` sticks to the frame, not to the page — it looks broken or invisible.
> Switch the placement's Ad wrapper to **Without Wrapper**.

## Per-role notes

- **Publishers** without advertiser access cannot create the HTML Code banner — ask the network
  manager, or use Option 2 on your own placement.
- The **Third-Party tracking codes** card needs the banner (or placement) third-party tracking
  permission.

## Related

- [Third-party tracking codes](https://epom.com/ad-server/docs/guides/conversions/third-party-tracking-codes.md)
- [Fix click tracking on third-party ad tags](https://epom.com/ad-server/docs/troubleshooting/click-tracking-third-party-tags.md)
- [HTML code and Template banners](https://epom.com/ad-server/docs/guides/advertising/banner-html-and-template.md)
- [Application, email and click-through placements](https://epom.com/ad-server/docs/guides/inventory/placement-mobile-email-other.md)
- [Ad tags, invocation codes and the API](https://epom.com/ad-server/docs/guides/inventory/ad-tags-and-api.md)