Skip to content
Beet Media
Create account
Menu

Documentation

The publisher ad tag

Dependency-free JavaScript, no framework and no third-party requests. It derives its own endpoint from the src attribute it was loaded with.

Installation

One container per slot and one script per page. Order does not matter and the script can sit anywhere in the document.

Installation snippet
<div data-beet-placement="plc_xxx"></div>
<script async src="https://edge.beet.media/tag.js"></script>

Every element carrying the placement attribute becomes a slot. All the slots on one page are requested together, in the order they appear, so a page with six slots makes one call rather than six.

A token fills at most one element: the tag gives each token its first matching element and stops there. Repeating a token across several elements — to get more than one ad out of one placement — fills the first one and leaves the rest permanently empty. Create a separate placement, and give each its own element, for every slot on the page.

Pick up slots added after load
window.beet.refresh();

Checking with curl will show no slot. That is the crawler gate working, not a broken install: curl is treated as a bot, and bots are excluded so they cannot request slots they will never fill. Verify in a browser, or with a real browser user agent.

The endpoint is derived, never configured

No host is written anywhere inside the tag, and that is deliberate.

The tag reads the src of the script that loaded it and calls that same origin. If that fails — inside a tag manager, for instance — it looks for the last script whose path ends in the file name. If it cannot find that either, it disables itself and leaves the page untouched.

What it deliberately does not do is fall back to a hardcoded host. A wrong guess would serve from the wrong origin and break exactly the first-party measurement the derivation exists to protect.

What the ad request sends

The complete list. There is no parameter that is not on it.

Ad request parameters
ParameterTypeRequiredMeaning
pstringYesPlacement tokens separated by commas, in slot order.
prstringNoThe page's own content rating, when the page declares one. It can only make the page count as stronger, never weaker.
uurlYesThe page URL, without the fragment.
tstringNoThe page title.
dstringNoThe page's meta description.
hstringNoThe page's first three headings, joined.
rurlNoThe document referrer.
vwintegerNoViewport width.
vhintegerNoViewport height.
dprnumberNoDevice pixel ratio.
tzintegerNoThe browser's timezone offset, in minutes.
lstringNoThe browser language.
npintegerNoSet to 1 when the request must be non-personalised.
cmpintegerNoSet to 1 when a consent platform was present on the page.
gdprintegerNoSet to 1 when GDPR applies.
tcsstringNoThe consent string, if the consent platform supplied one.

The response

JSON, never cached, one object per slot and in the order they were requested.

One slot of the response
{
  "slots": [
    {
      "p": "plc_xxx",
      "w": 300,
      "h": 250,
      "img": "https://cdn.example/creative.png",
      "alt": "",
      "click": "https://edge.beet.media/c/<token>",
      "t": "<impression token>",
      "sk": "<per-impression signal subkey, base64url>",
      "ac": "br",
      "lang": "es",
      "why": { "country": "MX", "category": "Arts & Entertainment" },
      "report": "https://edge.beet.media/reports?t=<token>"
    }
  ]
}
  • The explanation field is what backs the "why am I seeing this ad" disclosure a reader can open from the creative itself.
  • The report field is a public, session-free link for reporting a specific ad. No account is needed to use it.
  • The creative sits in an iframe nested inside ours: the outer frame carries the AdChoices icon and the click layer, and the creative never shares a document with them.

The viewability beacon

This is what produces the billable impression, which is why it is documented here rather than hidden.

The beacon request
POST /b/i
Content-Type: application/x-www-form-urlencoded

t=<impression token>&d=<view_duration_ms>&s=<signed signal blob>

It is sent once per token, when the ad has spent at least one continuous second with half its pixels in view in a foreground tab. The server answers 204 and nothing else, always. A repeated token does not count again.