Debug, native ads, and custom rendering patterns
SDK Recipes: Advanced Integration
Advanced integration patterns for debugging, native ads, and custom rendering.
Recipe 8: "I need native/in-feed ads"
Problem: You want ads that blend with your content feed.
Native Ad Implementation
1. Mark element as native slot
<!-- Article feed -->
<div class="feed">
<article class="article-card">
<h2>Real article 1</h2>
<p>Real content...</p>
</article>
<!-- Native ad placeholder -->
<article class="article-card nativeinfeed" data-collapse="1">
<h2>Placeholder title</h2>
<p>This content will be replaced by native ad</p>
</article>
<article class="article-card">
<h2>Real article 2</h2>
<p>Real content...</p>
</article>
</div>Key classes:
nativeinfeed- Marks element as native ad containerdata-collapse="1"- Hides element if no ad available
2. Automatic slot detection
With autoslot: 1, the SDK automatically finds .nativeinfeed elements:
dlApi = {
target: "SITE/AREA",
autoslot: 1, // Auto-detects native slots
async: 1
};3. Restore content if no ad
When a native slot gets no ad, restore the editorial content:
dlApi.cmd.push(function(dlApi) {
dlApi.on("afterDestroySlot", function(event, slot) {
// Check if this was a native slot
var el = document.getElementById(slot.div);
if (el && el.classList.contains('nativeinfeed')) {
// Restore editorial content
el.innerHTML = `
<h2>Real article title</h2>
<p>Real editorial content here...</p>
<a href="/article-url">Read more</a>
`;
// Show the element again
el.style.display = '';
}
});
});Manual Native Slot Definition
For more control, define native slots manually:
dlApi = {
target: "SITE/AREA",
autoslot: 0, // Manual control
async: 1,
cmd: []
};
dlApi.cmd.push(function(dlApi) {
// Define multiple native slots
dlApi.defineSlot("infeed1", "native-slot-1", {
pos: 1,
native: true
});
dlApi.defineSlot("infeed2", "native-slot-2", {
pos: 2,
native: true
});
dlApi.fetch();
});Track Native Ad Events
dlApi.cmd.push(function(dlApi) {
dlApi.on("afterDisplay", function(event, ad) {
if (ad.native) {
console.log("Native ad displayed:", ad);
// Track to analytics
}
});
dlApi.on("empty", function(event, slot) {
console.log("No native ad for:", slot.name);
// Restore editorial content
});
});SDK Objects Used
- Native ad classes:
nativeinfeed dlApi.defineSlot()- Manual slot definitiondlApi.on("afterDestroySlot")- Slot removal eventslotwithnativeproperty
Recipe 9: "I need custom ad rendering"
Problem: You need special ad formats or custom templates.
Custom Template Registration
1. Register your custom renderer
dlApi.cmd.push(function(dlApi) {
dlApi.registerTemplate({
// Template identifier (from campaign setup)
tplCode: "1746213/CustomFormat",
// Your rendering function
renderAd: function(ad) {
console.log("Rendering custom ad:", ad);
// Create custom HTML structure
var container = document.createElement("div");
container.className = "my-custom-ad";
// Access ad data
container.innerHTML = `
<div class="custom-ad-header">
<span class="sponsor">Sponsored</span>
</div>
<div class="custom-ad-body">
<img src="${ad.fields.image}" alt="${ad.fields.headline}">
<h3>${ad.fields.headline}</h3>
<p>${ad.fields.description}</p>
<a href="${ad.meta.adclick}${ad.fields.url}"
class="custom-cta"
target="_blank">
${ad.fields.cta || 'Learn More'}
</a>
</div>
`;
// Insert into slot
var slotElement = document.getElementById(ad.div);
slotElement.appendChild(container);
// IMPORTANT: Track impression
if (ad.meta.impression) {
var pixel = new Image();
pixel.src = ad.meta.impression;
}
// Track click properly
var link = container.querySelector('a');
link.addEventListener('click', function(e) {
// ad.meta.adclick already prepended to href
console.log("Custom ad clicked");
});
}
});
});2. Ad object structure
The ad parameter contains:
{
// Ad metadata
meta: {
adclick: "https://click-tracking-url/", // Click tracker prefix
impression: "https://impression-url/", // Impression pixel
adid: "12345", // Ad ID
cmpid: "67890" // Campaign ID
},
// Creative data (depends on template)
fields: {
headline: "Product Title",
description: "Product description...",
image: "https://cdn.example.com/image.jpg",
url: "https://destination-url.com",
cta: "Shop Now",
price: "$99.99"
// ... other custom fields
},
// Slot reference
div: "ad-slot-id", // Container element ID
slot: slot, // Slot instance
// Template info
tpl: "1746213/CustomFormat"
}Multiple Custom Templates
dlApi.cmd.push(function(dlApi) {
// Product carousel template
dlApi.registerTemplate({
tplCode: "1746213/ProductCarousel",
renderAd: function(ad) {
// Render carousel with multiple products
var carousel = createCarousel(ad.fields.products);
document.getElementById(ad.div).appendChild(carousel);
trackImpression(ad.meta.impression);
}
});
// Video template
dlApi.registerTemplate({
tplCode: "1746213/VideoAd",
renderAd: function(ad) {
// Render video player
var player = createVideoPlayer(ad.fields.videoUrl);
document.getElementById(ad.div).appendChild(player);
trackImpression(ad.meta.impression);
}
});
// Interactive template
dlApi.registerTemplate({
tplCode: "1746213/Interactive",
renderAd: function(ad) {
// Render interactive experience
var interactive = createInteractive(ad.fields);
document.getElementById(ad.div).appendChild(interactive);
trackImpression(ad.meta.impression);
}
});
});Important: Tracking Requirements
Always preserve click and impression tracking:
renderAd: function(ad) {
// ✓ CORRECT - Impression tracking
if (ad.meta.impression) {
var pixel = new Image();
pixel.src = ad.meta.impression;
}
// ✓ CORRECT - Click tracking (prefix preserved)
var link = document.createElement('a');
link.href = ad.meta.adclick + ad.fields.url;
// ✗ WRONG - Missing impression
// (No tracking pixel)
// ✗ WRONG - Broken click tracking
link.href = ad.fields.url; // Missing adclick prefix!
}Template with Error Handling
dlApi.cmd.push(function(dlApi) {
dlApi.registerTemplate({
tplCode: "1746213/SafeTemplate",
renderAd: function(ad) {
try {
// Validate required fields
if (!ad.fields.image || !ad.fields.headline) {
console.error("Missing required fields:", ad);
return;
}
// Render ad
var container = createAdElement(ad);
document.getElementById(ad.div).appendChild(container);
// Track impression
if (ad.meta.impression) {
new Image().src = ad.meta.impression;
}
} catch (error) {
console.error("Template render error:", error, ad);
// Fallback to standard rendering
ad.renderStandard();
}
}
});
});Access Ad Instance Methods
The ad object is an ad instance:
renderAd: function(ad) {
// Access ad methods
console.log("Ad ID:", ad.adid);
console.log("Campaign ID:", ad.cmpid);
// Watch visibility
var view = ad.watchVisibility();
view.on('viewed', function() {
console.log("Custom ad was viewed");
});
// Access counter for tracking
ad.counter.finish(); // Mark ad as loaded
}SDK Objects Used
dlApi.registerTemplate()- Register custom rendereradobject - Ad data with fields and metadataad.meta- Tracking URLs and metadataad.fields- Creative field dataadinstance - Ad object with methods
Next Steps
- Having issues? See Troubleshooting Guide
- Need more examples? See SDK Recipes
- Deep dive? See DL API SDK Reference
