What the console sets up
Club admins set up the inventory in the console. These are console screens, not partner API:- Property. A website, identified by its origin, for example
https://www.example.com. Only web properties serve ads. An iOS or Android property can be recorded but never fills. - Ad unit. A slot on a property, with a code and a fixed size in pixels. The code is what your page asks for. Codes are lowercase and match
^[a-z0-9][a-z0-9_.-]{0,63}$, for examplehome_top_banner. - Campaign. A flight with a start date, an optional end date, a priority, the ad units it runs on, and optional country and member label targeting. Only an
activecampaign serves;draft,pausedandarchivedones do not. - Creative. An image and a click destination, both
https, with a size. A creative only fills a unit of exactly the same width and height.
Key and origins
Ad requests use anek_live_… tracking key, the same kind of publishable key POST /v1/track uses. A partner admin issues it with the website’s origins on its allowlist; see Trigger an event for the call. A key used for tracking can also serve ads.
Two origin checks apply to every serve:
- The request’s
Originheader must be on the key’s allowlist, exactly. A missing or unlisted origin answers403 FORBIDDEN. - The origin must also be the origin of the property the ad unit belongs to. A unit on another property, or an origin that matches no property, answers as a no-fill.
Origin on a fetch() call but not when loading an <img> or an <iframe>, so an ad tag that points an image or a frame at the serve URL is always refused. Request ads with fetch(), which the SDK does.
Serve an ad
GET /v1/ads/serve picks an ad for one ad unit. It takes the tracking key as key, the ad unit code as unit, and, for a signed-in fan, an identity_token (see Member targeting). The parameters and the response schema are in the API reference under Endpoints.
200 OK with an ad object: the creative’s asset_url, size and ids, plus click_url, impression_url and token, which the next two sections use. With nothing to show, it is 200 OK with:
404. An unknown unit code, an archived unit and a unit with no eligible campaign all look the same, so leave the slot empty and move on.
How an ad is picked:
- The campaign is
active, its flight has started and has not ended, and the creative is active and the same size as the unit. - The campaign’s country rule, if it has one, matches the viewer’s country. The country comes from the request’s IP address, coarsely, and the address is not stored. When no country can be resolved, campaigns limited by country do not fill.
- The campaign’s label rule, if it has one, matches the viewer’s labels. See Member targeting.
- Among the eligible creatives, the highest campaign priority wins. Creatives tied at that priority take turns.
click_url points at 4D’s click redirector, not at the advertiser. token is signed and ties the impression and the click to this serve. Every response from the ad endpoints carries Cache-Control: no-store; do not cache them.
An identity token never causes an error. A missing, malformed, expired or other-club token serves the slot as if the viewer were anonymous.
Count the impression
When the creative’s image has loaded, post the serve token toPOST /v1/ads/impression. A served ad whose image never loaded is not an impression.
Content-Type, so navigator.sendBeacon, which sends text/plain, works. The token can also go in the query string as ?t=. The body is capped at 4096 bytes.
202 Accepted:
202 with { "status": "duplicate" } and is not counted twice, so retrying a beacon is safe.
This call takes no key and checks no origin: the signed token is the only credential. A token is good for 30 minutes after the serve.
Clicks
Use the servedclick_url as the link around the image. GET /v1/ads/click?t=… records the click and answers 302 to the advertiser’s destination, which 4D looks up when the click arrives. The destination is never in the page, the token or the query string.
A repeated click on the same ad still redirects and is counted once. The redirect carries Referrer-Policy: no-referrer, so the advertiser does not learn which page the click came from. A click token is good for 24 hours after the serve.
When the click cannot be recorded, there is no redirect: the call answers 422 AD_TOKEN_INVALID for a bad or expired token, 404 NOT_FOUND when the creative or its ad unit no longer exists, or 429 RATE_LIMITED.
Rate limits
A serve over its limit is checked after the key and the origin, so traffic from origins you have not listed cannot use up your allowance. Each ad unit on a page is its own serve request, so a page with three slots makes three.
Member targeting
A campaign can include or exclude member labels. A viewer must hold at least one included label, when the campaign lists any, and no excluded label. Exclusions win. To target by label, the serve call has to say who the viewer is, and the page cannot be trusted to say it. Your server mints an identity token for the signed-in fan with its organization API key,POST /v1/ads/identity-tokens, and the page passes it as identity_token on serve. The call, its body and the one-hour expiry are in Signed-in fans on ad requests. Mint one when the fan signs in and a new one before expires_at. The ads SDK takes it through identify.
Send no labels: 4D reads the viewer’s current labels from the membership the token names. An anonymous viewer, or a token that names no active member, is only eligible for campaigns with no label rule. Campaigns without label rules serve to everyone, signed in or not. The unsigned member_external_id and user_id serve parameters of earlier integrations no longer identify anyone, so a request that sends them is served as anonymous.
Targeting uses the member whatever their consent. Recording is different: the impression and the click are stored against the member only when the fan holds your club’s Personalised content consent at the moment the ad is served. Without it, or without a valid token, they are counted anonymously, as for any viewer.
Nothing the page can read names the member. The identity token is opaque, and the serve response, its token and the click URL carry no readable member id and no labels.
Next
The ads SDK wraps all of this in four calls:init, identify, defineSlot and display. A creative can click through to a sponsor’s draw on your site; your backend reports the fan’s entry as described in Sponsor draw entries.