Fetch several native teasers in one batch and render them as entries in your content feed with dlApi.fetchNativeTeasers
Native Teasers: Batched In-Feed Ads
dlApi.fetchNativeTeasers fetches native ads for several consecutive feed positions in a single batch and returns them in your content-feed contract shape, so you can inject them into a feed alongside editorial entries.
This method does not render anything into the page. It hands you the data and leaves rendering, feed injection, and event tracking to the page:
teasers— an array with one feed entry per filled position, ready to merge into your feed. Each entry carries abidPosfield so you can pair it back to itsbidsitem for tracking.bids— the raw ad data per position. You reach an entry'sadmhere (viabidPos) and pass it todlApi.registerBidResponsefor impression and viewability tracking.
Use it when the page owns the rendering (for example a homepage feed built server-side or in a framework) and you only need the ad payload in a shape that matches your existing feed entries.
Live Demo
See it working: Content Commerce Teasers Demo
The demo fetches live teasers from the ad server and renders them as feed entries. View the source to see the full fetchNativeTeasers → registerBidResponse flow.
Integration
Step 1: Fetch the teasers
dlApi.cmd.push(function(dlApi) {
dlApi.fetchNativeTeasers({
slot: 'flat-natleft3',
limit: 3,
opts: { DX_keyword: 'value' }
}).then(function(result) {
var teasers = result.teasers; // [entry, entry, ...]
var bids = result.bids; // [{ pos, div, adm }]
// ... Steps 2 and 3
});
});slot is required — the promise rejects when it is missing. Teaser campaigns are targeted through the slot and the per-position opts; the SDK does not add any page-wide keyword or key-value of its own.
Step 2: Inject the entries into your feed
teasers contains one entry per filled position, already mapped to the feed contract. Merge them into your feed and render them the same way you render editorial entries. Render each teaser into a container you can locate again in Step 3 — for example an element id derived from the entry's uuid:
myFeed.entries = myFeed.entries.concat(teasers);
renderFeed(myFeed);Empty positions are excluded from teasers (see Empty Positions).
Step 3: Track impressions, viewability, and clicks
Track from the same teasers list you rendered — not from bids. For each entry, find its bid by bidPos and register the bid's adm on the container you rendered the entry into. This fires the impression and, when the creative is eligible, sets up viewability (Active View) tracking:
teasers.forEach(function(entry) {
var bid = bids.find(function(b) { return b.pos === entry.bidPos; });
var container = document.getElementById('feed-entry-' + entry.uuid); // the element you rendered this entry into
dlApi.registerBidResponse(bid.adm, container);
});Viewability is only set up when a container element is provided and the creative is marked viewable (adserver_meta.viewability === true). Without a container the impression still fires, but Active View is skipped.
Clicks are not covered by registerBidResponse — you count them through the tile's own link. Set the tile's anchor href to link.href: whenever the ad carries a click-count endpoint, the SDK has already assembled it into the ready-made click-counting URL (meta.adclick + destination), so the browser navigates through the ad server's click-count endpoint, which counts the click and 302-redirects to the real destination. When there is no click-count endpoint, link.href is simply the plain destination.
teasers.forEach(function(entry) {
tileLink.setAttribute('href', entry.link.href); // the anchor of the tile you rendered this entry into
});Options
| Option | Type | Default | Description |
|---|---|---|---|
slot | string | – (required) | Slot name used for every position. |
limit | number | 1 | Number of teaser positions to fetch (pos 1..limit). |
opts | object | – | Targeting options merged into each position's opts. The SDK adds pos per position. |
Return Value
The promise resolves with { teasers, bids } — the entries you render, and the ad data you track.
teasers
teasersOne entry per filled position, in order, each matching your feed entry contract and populated from the teaser creative:
| Field | Description |
|---|---|
bidPos | The 1..limit position this entry was resolved for. Use bidPos to pair the entry with its bids item (bids.find(function(b) { return b.pos === entry.bidPos; })) to reach the raw adm for registerBidResponse (impression and viewability). |
uuid | Entry identifier — carries the ad id. |
type.code | Story kind for the renderer; defaults to article. |
title.text | Teaser headline. |
title.prefix / title.label | Commercial disclosure markers (for example materiał promocyjny / sponsoring), always set so the tile renders as sponsored content. |
image.url | Teaser image URL. |
image.size | Creative dimensions; 0 when the creative carries none. |
link.href | The tile's single link — set it as the anchor href (see Step 3). Whenever the ad carries a click-count endpoint, this is the ready-made click-counting URL (meta.adclick + destination) so the click is counted by the redirect; otherwise it's the plain destination URL. |
summary.text | Lead text with HTML stripped; present only when the teaser has a lead. |
sources | Partner logo; present only when the teaser carries one. |
flags | Marks the entry as content_commerce. |
published / modified | Publication timestamps. |
variants | Intentionally absent — the winning teaser variant is already resolved into title / summary, so there is nothing left for the page to choose. |
bids
bidsOne item per requested position, in order — empty positions included, so the array is always limit long:
[
{ pos: 1, div: 'nativeTeaser_1_ab12cd34', adm: { /* ad data */ } },
{ pos: 2, div: 'nativeTeaser_2_ef56gh78', adm: null } // empty position
]| Field | Description |
|---|---|
pos | Teaser position, 1..limit — the same value the ad was requested with as pos targeting. |
div | Internal id of the technical container the SDK used for that position. |
adm | Raw ad data (fields, meta, gctx, lctx) for registerBidResponse, or null when there was no ad for that position. |
Empty Positions
When a position returns no ad (or fails), its bid is { pos, div, adm: null } and it is excluded from teasers. If fewer ads come back than requested, teasers is simply shorter than limit.
Because teasers is filtered, its array index no longer matches the requested position. Each entry's bidPos carries its original 1..limit position, so you can still map a surviving teaser back to the right feed slot or bids item.
The consumer decides how to fill the gap — for example by falling back to an editorial entry for that position. The SDK only signals the gap via adm: null.
SDK Methods Used
dlApi.fetchNativeTeasers()— fetch the batch, get{ teasers, bids }dlApi.registerBidResponse()— count impression and set up viewability per rendered teaser
