Skip to main content
sdk

Web SDK Ad Customization

active
Audience: developerUpdated 2026-07-28

On the SDK-rendering path (Render Display Ads with the Web SDK) the Web SDK fetches, renders, and tracks every Display Ads slot you place. This page is the reference for changing how those ads look, without giving up the fetching and tracking the SDK does for you.

It does not apply to Sponsored Ads, which the SDK does not render — you own that markup entirely.

There are three levers, in increasing order of control:

GoalUse
Recolor, resize, round, or reposition the existing markupCSS classes — your own stylesheet
Toggle behavior the SDK already supports (closable, sticky, slider, grid columns…)Display options — configured on the Binoban platform
Change the markup itself: reorder, omit, wrap, or render through your own codeCustom creative templates

None of them changes behavior. Which creative shows, impression and click tracking, and slider mechanics stay owned by the SDK in all three cases.


CSS classes

The SDK renders every ad into your <div data-bob-id="…"> slot using predictable, BEM-style class names. They are a stable contract — target them from your own CSS.

The SDK also injects a small base stylesheet into a <style id="bob-ads-display-styles"> element in <head>. Your own rules override it with ordinary specificity: load your stylesheet after it, or use a slightly more specific selector.

Slot lifecycle

The SDK toggles state classes on your slot element as it renders:

ClassMeaning
bob-ads--loadedA creative has been rendered into this slot.
bob-ads--failedNo ad was available. The slot is also set aria-hidden="true" and hidden with display:none.

Container and creative

ClassElement
bob-ads-containerThe wrapper the SDK renders inside your slot.
bob-ads-container--{type}Type modifier — bob-ads-container--banners or bob-ads-container--native.
bob-ads-container--{type}-{template}Type and template modifier (e.g. bob-ads-container--native-native_slider).
bob-ads-container--scaleupPresent when the scaleUp display option is on (the creative stretches to fill).
bob-ads-container__closeThe built-in close button, shown when the slot is closable.
bob-ads-creativeThe clickable creative anchor (<a>). Wraps every creative, built-in or custom.
bob-ads-creative__imageThe <img> inside a banner creative.
bob-ads-bannerA banner creative anchor.

Native creative

ClassElement
bob-ads-nativeA native creative anchor.
bob-ads-native--{template}Template modifier (e.g. bob-ads-native--native_text).
bob-ads-native__imageThe native image wrapper (the <img> is inside).
bob-ads-native__titleThe native title.
bob-ads-native__ctaThe native call-to-action (wraps a <button>).
ClassElement
bob-ads-sliderThe slider root.
bob-ads-slider__containerThe track holding the slides.
bob-ads-slider__slideA single slide.
bob-ads-slider__buttonA previous/next arrow button.
bob-ads-slider__button--prev / bob-ads-slider__button--nextArrow direction modifiers.
bob-ads-slider__button__svgThe arrow icon.
bob-ads-slider__dotsThe pagination-dots container.
bob-ads-slider__dotA single pagination dot.
bob-ads-slider__dot--selectedThe active dot.

Sticky placement

ClassElement
bob-ads-sticky-positionA slot pinned to the viewport (fixed position).
bob-ads-sticky-position__{position}Placement modifier — top, right, left, bottom, top_right, top_left, bottom_right, bottom_left.

Example

/* Round every creative and give native cards a subtle border */
.bob-ads-creative {
border-radius: 12px;
overflow: hidden;
}
.bob-ads-native {
border: 1px solid #eee;
}
/* Recolor the slider's active dot */
.bob-ads-slider__dot--selected:after {
box-shadow: inset 0 0 0 0.2rem #263d69;
}

Display options

Each ad slot can carry a set of display options. These are configured on the Binoban platform, per inventory and ad slot, and delivered with the ad response — you do not set them from the SDK. They are documented here so you know what behavior to expect and what the SDK will render.

General

OptionTypeEffect
closablebooleanShows a close button. Closing hides the slot and emits a close event.
samePagebooleanOpens the ad's destination in the same tab (_self) instead of a new tab (_blank).
borderRadiusstringCSS radius applied to the creative (e.g. "8px"), with overflow clipped.
rotatebooleanRotates which creative shows across page views when a slot has several.
fillWithRepeatbooleanRepeats creatives to fill the slot when there are more cells than creatives.
scaleUpbooleanStretches the creative to fill its container (adds bob-ads-container--scaleup).

Card

OptionTypeEffect
card.cardBgstringBackground color of the native card.
card.ctaBgstringBackground color of the native CTA button.

Slider

OptionTypeEffect
slider.hideArrowsbooleanHides the previous/next arrows.
slider.hideDotsbooleanHides the pagination dots.
slider.disableAutoStartbooleanDisables autoplay.
slider.isLtrbooleanSets slide direction to left-to-right. The default is right-to-left.
slider.sizenumberSlide width as a percentage of the track (e.g. 50 for two per view).
slider.spacingnumberGap between slides, in pixels.

Grid

OptionTypeEffect
grid.maxColumnsnumberMaximum columns for the native grid layout. Defaults to 3.

Sticky

OptionTypeEffect
sticky.positionenumWhere the slot pins: TOP, RIGHT, LEFT, BOTTOM, TOP_RIGHT, TOP_LEFT, BOTTOM_RIGHT, BOTTOM_LEFT.
sticky.transformXstringHorizontal offset (CSS translate X, e.g. "10px").
sticky.transformYstringVertical offset (CSS translate Y).
sticky.boxBgstringBackground color of the sticky box.
sticky.boxShadowstringBox-shadow of the sticky box.

Custom creative templates

When CSS on the fixed structure is not enough — you need to reorder elements, add a badge, omit something, wrap the creative in your own card, or render it through your own code — supply a custom creative template. The SDK still fetches the ads, manages the layout (slider, sticky, grid), and reports every event.

This is creative-level customization: you template one ad item, and the SDK places your markup into each cell of the layout the campaign selected.

Two ways to author a template

1. Declarative <template> (no JavaScript)

Place a <template data-bob-template> inside the ad slot. The SDK clones it for each creative, fills in the ad data, and wires up the events.

<div data-bob-id="hero-slot">
<template data-bob-template>
<article class="promo">
<span class="promo__badge">Sponsored</span>
<img data-bob-src="image" alt="" />
<h3 data-bob-text="title"></h3>
<p class="promo__cta" data-bob-text="cta" data-bob-if="cta"></p>
<button data-bob-action="close" aria-label="Close">×</button>
</article>
</template>
</div>

Reuse one template across many slots by giving it an id and pointing slots at it:

<template id="promo-card">
<article class="promo">
<img data-bob-src="image" alt="" />
<h3 data-bob-text="title"></h3>
</article>
</template>

<div data-bob-id="rail-1" data-bob-template="promo-card"></div>
<div data-bob-id="rail-2" data-bob-template="promo-card"></div>

2. JavaScript render callback

Register renderers through the adTemplates option when you load the SDK. This is the recommended programmatic path: your renderers are registered before the SDK loads its first ads, so there is no flicker.

Binoban.load({
credentials: {
apiKey: "PROJECT_API_KEY",
sourceIdentifier: "PROJECT_SOURCE_IDENTIFIER",
},
host: {
rtbPath: "YOUR_BINOBAN_SERVER_RTB_URL",
sdkPath: "YOUR_BINOBAN_SERVER_SDK_URL",
apiPath: "YOUR_BINOBAN_SERVER_API_URL",
},
adTemplates: {
// Named renderers, referenced by data-bob-template="promo-card"
renderers: {
"promo-card": (ad, api) => {
const el = document.createElement("article");
el.className = "promo";
el.innerHTML = `<img src="${ad.image}" alt=""><h3>${ad.title}</h3>`;
return el; // return an HTMLElement or an HTML string
},
},
// Or a blanket fallback per creative type:
defaults: {
native: (ad, api) => {
/* build and return your node */
},
banner: (ad, api) => {
/* … */
},
},
},
});
Why adTemplates and not ads?

The ads option is already used for RTB host and click configuration, so custom templates live under adTemplates.

Binding attributes

Inside a <template>, these data-bob- attributes tell the SDK where to put the ad data. The SDK writes text and attribute values only — it never injects markup from ad data — so your template is safe from content-driven injection.

AttributeWhat it does
data-bob-text="field"Sets the element's text to ad.field.
data-bob-src="field"Sets an image's src to ad.field.
data-bob-attr:NAME="field"Sets attribute NAME to ad.field (e.g. data-bob-attr:alt="title").
data-bob-if="field"Removes the element when ad.field is empty.
data-bob-action="close"Marks your close button. Honored only when the slot is closable.

There is no click marker — the whole creative is the link. The SDK wraps your markup in an <a class="bob-ads-creative"> and handles navigation and click tracking itself.

Ad data fields

Templates and renderers bind to this curated, read-only field set. Internal fields such as bid and campaign identifiers are deliberately not exposed.

Ad typeFields
Nativeimage, title, cta, landingUrl, logo, icon
Bannerimage, targetUrl, width, height

A JavaScript renderer also receives an api:

interface CreativeRenderApi {
// Wire an element as the close trigger (no-op unless the slot is closable).
bindClose(el: Element): void;
// The resolved display options for this slot (read-only).
ui?: AdsInventoryUi;
}

Which template applies

For each creative, the first match wins:

  1. an inline <template data-bob-template> inside the slot element;
  2. data-bob-template="name" on the slot — matching a document <template id="name">, or a registered renderers["name"]. A matching document template wins over a same-named renderer.
  3. a per-type default renderer (adTemplates.defaults.banner / .native);
  4. otherwise, the SDK's built-in rendering.

What the SDK still owns

A template changes structure, never behavior:

  • Click — the creative is an SDK <a> reusing the standard click handling: a 500 ms flush delay before navigation, _self or _blank from the samePage display option, and rel="nofollow noopener".
  • Impression — fired once, when the creative first enters the viewport.
  • Close — wired to your data-bob-action="close" element, and only when the slot is closable. It hides the slot and emits the close event.

Fallback and safety

Any failure — missing template content, a renderer that throws, or a binder error — falls back to the built-in renderer for that creative. A slot is never left empty because of a bad template. Turn on debug mode to see why a template was skipped.

Ad data is advertiser-controlled, so the binder also hardens attribute bindings:

  • data-bob-attr:NAME never sets an event-handler attribute. Any NAME starting with on (e.g. onclick) is stripped outright.
  • On URL-bearing attributes (href, src, xlink:href, formaction, action, poster, background, cite — including via data-bob-src), a javascript:, vbscript:, or data:text/html value is neutralized to an empty string instead of being written. Ordinary URLs pass through unchanged.

Non-URL, non-handler attributes are unaffected.

Closable slots need their own close element

If a slot is closable and resolves to a custom template, your creative replaces the SDK's built-in close button. Include a data-bob-action="close" element in your template, or the slot has no close control.

Limitations

Slider layouts render a single, collection-level close button. If a JavaScript renderer succeeds for some slides but fails for others — falling back to the built-in creative for those — the shared close button is suppressed. Declarative templates are deterministic per slide, so this affects only renderer functions with per-item failures.