Publisher Integration Guide

A one-tag drop-in: runs a Prebid auction against limelightDigital, stitches the winning bid into your GAM ad call, plays the result through video.js + IMA.

Overview

One <script> tag with data-* attributes handles: lazy-loading video.js + IMA + Prebid (≈ 250 KB), running the auction, stitching hb_pb / hb_bidder / hb_uuid / hb_size / hb_format / hb_adid into GAM's cust_params, and rendering the cached creative via IMA.

Engine hosted at versioned, immutable jsDelivr URLs. Pin to a tag (e.g. @v2.5.1) — the bytes cannot silently change.

How it works

Engine parallel-loads video.js, IMA, Prebid; reads data-*; registers a video ad unit.
Prebid Limelight: POST {host}/ortbhb
Limelight responds with a bid (or no-bid). Winning VAST is cached at Prebid Cache; engine gets a UUID.
Engine stitches the full hb_* set into the GAM tag's cust_params, applies floor bias to hb_pb, refreshes correlator.
IMA GAM: fetches VAST; line item targeting hb_pb wins.
GAM returns a VAST wrapper with %%PATTERN:hb_uuid%% resolved.
IMA Prebid Cache: resolves the wrapper; plays the bidder creative; content resumes after.
Fallback

Prebid load failure, bidder timeout, or no-bid → engine still calls GAM with hb_pb=0.00&hb_bidder=none. Your house line item fills the slot.

Prerequisites

  • Google Ad Manager account with video inventory; a GAM Master Ad Tag URL ending in correlator=.
  • Limelight Digital publisher ID + ad unit ID.
  • Domain allowlisted by Limelight (1–3 business days). Without this, every auction returns no-bid.
  • HTTPS publisher pages; content video URL (.mp4 / .m3u8) on your CDN.
#1 cause of zero fill

The publisher domain not being on Limelight's allowlist. Verify before launch.

Quick start

  1. Generate the tag

    Open the Tag Generator, fill in version, GAM tag, Limelight pub/ad-unit IDs, content URL → copy the <script>.

  2. Set up GAM

    Create the key-values, the VAST wrapper creative, and one line item per $0.10 bucket (one-time setup — see GAM setup).

  3. Embed

    Paste the snippet where the player should render. The engine auto-creates a mount <div>.

  4. Verify

    Open with ?debug=true — see testing checklist.

  5. Monitor

    GAM Reports → filter by hb_bidder=limelightDigital for impressions / eCPM / fill.

Embed code reference

The v2 tag shape uses data-bidders — a JSON array of every SSP that should bid in this auction. The Prebid bundle at data-prebid-url must include adapters for every bidder listed.

<script src="https://cdn.jsdelivr.net/gh/shashwatsilverpush/bidding-player@v2.5.1/engine/player.js"
        id="adtech-player-core"
        data-bidders='[
          {"bidder":"limelightDigital","params":{"host":"ads-jbi003.rtba.bidsxchange.com","publisherId":"649658371","adUnitId":972556929,"adUnitType":"video"}},
          {"bidder":"appnexus","params":{"placementId":12345678}}
        ]'
        data-tag="https://pubads.g.doubleclick.net/gampad/ads?iu=/…&sz=640x480&output=vast&correlator="
        data-video="https://your-cdn.example.com/content.mp4"
        data-prebid-url="https://cdn.jsdelivr.net/gh/shashwatsilverpush/bidding-player@v2.5.1/prebid/prebid-limelight-appnexus.js"
        data-timeout="1200"  data-bias="0.10"
        data-autoplay="true"  data-muted="true"  data-fluid="true"
        async></script>

Attribute reference

AttributeReqDefaultNotes
srcYesVersioned jsDelivr URL. Pin to a tag — never @main.
idYesadtech-player-coreMust be exactly this value.
asyncYesRequired HTML attr; engine boots after DOMReady.
data-biddersYes*v2 multi-bidder. JSON array of Prebid bid objects ({bidder, params}). Each entry's params shape is per-SSP — see Prebid bidder docs. *Optional if you use the legacy three-attr shortcut instead.
data-pub-id / -adunit-id / -hostLegacyv1 legacy single-bidder shortcut. Engine builds a 1-element limelightDigital array from these. Use when you want only Limelight and can't / won't write the JSON. Ignored when data-bidders is set.
data-tagYesGAM master ad tag URL; must end with correlator=.
data-prebid-urlYesPrebid.js build URL. Must include an adapter for every bidder in data-bidders — Prebid silently drops unknown bidders. Pick a bundle from prebid/ in this repo, or build a new one (see prebid/README.md).
data-videoNoContent video (.mp4 / .m3u8). Required for instream; omitted for outstream.
data-placementNoinstreaminstream plays the ad against your content video. outstream needs no content video — slot stays collapsed until ≥50% in view, autoplays muted, then collapses. See Placement & sticky below.
data-stickyNofalseInstream only. true floats the player to the bottom-right corner when scrolled out of view (keeps playing, × to dismiss) and reflows the live ad to fit.
data-timeoutNo1200Prebid bidder timeout (ms). Industry default 1500–2000.
data-biasNo0.10USD added to winning CPM before bucketing. Explicit 0.00 disables the bias.
data-floor-minNoReject bids below this CPM (fall through to house line item). Omitted = no floor.
data-floor-maxNoCap the winning CPM before bias + bucketing. Omitted = no cap.
data-autoplay / data-mutedNotrue / trueBrowser policy: autoplay requires muted. Outstream + sticky both rely on muted autoplay.
data-fluidNotruetrue = responsive 16:9; false = fixed 640×480.
data-loopNofalseLoop content after end.
data-preloadNometadatametadata / auto / none.
data-vpaidNoinsecureinsecure / enabled / disabled.
data-div-idNocomparos-video-placementMount div ID. Auto-created if missing.
data-cacheNoprebid.adnxs.com/pbc/v1/cachePrebid Cache server.

Placement & sticky

Instream (default) plays the ad as pre-roll against your data-video content. Outstream (data-placement="outstream") needs no content video — drop it into a text article and the slot stays collapsed until it scrolls ≥50% into view, autoplays muted, then collapses when the ad finishes.

For instream, add data-sticky="true" to keep the player visible while the reader scrolls: it floats to the bottom-right corner (still playing, × to dismiss) and snaps back inline on scroll-up, with the original layout space preserved. This raises viewability and completed-view rates — off by default, opt in per placement.

Adding a new SSP / Prebid bundle

The prebid/ directory holds pre-built Prebid.js bundles. Each data-prebid-url points at one of these. To add a new bundle (e.g. when onboarding a publisher that uses a different SSP), trigger the "Build Prebid bundle" workflow in the Actions tab — supply the comma-separated module list and a filename, the workflow runs gulp build and commits the result. Full instructions in prebid/README.md.

Keep src, data-prebid-url, and data-bidders in sync

Always point src and data-prebid-url at the same version tag. The Tag Generator enforces this. Make sure every bidder named in data-bidders has its adapter in the bundle at data-prebid-url.

GAM setup

One-time setup: key-values, a VAST wrapper creative, and price-bucket line items.

1. Custom key-values

GAM → Inventory → Key-values → New key-value:

KeyTypeValues
hb_pbPredefined0.00, 0.10, …, 20.00 (per $0.10 step)
hb_bidderPredefinedlimelightDigital, none
hb_uuidFree-form(dynamic UUIDs)
hb_sizePredefined640x360, 1280x720, 1920x1080
hb_formatPredefinedvideo
hb_adidFree-form(dynamic)
hb_sourcePredefinedclient, s2s

2. VAST wrapper creative

GAM → Delivery → Creatives → New → Video → VAST 3.0 ad tag. Paste:

https://prebid.adnxs.com/pbc/v1/cache?uuid=%%PATTERN:hb_uuid%%

Duration: 0:00 (wrapper resolves real duration). Substitute your own cache URL if not using the AppNexus public cache.

3. Price-bucket line items

One line item per $0.10 bucket (200 total for $0–$20). Use Prebid's Line Item Generator to bulk-create via CSV.

FieldValue
NamePrebid HB $2.50
TypePrice Priority
CPMExact bucket (e.g. $2.50)
Targeting → key-valueshb_pb is one of 2.50
CreativeThe VAST wrapper from step 2
Exact string match

Prebid emits "2.50" (two decimals). A line item targeting "2.5" will never serve.

4. House fallback + order

Add a low-priority line item targeting hb_pb=0.00 with your house creative or AdSense passback. Wrap all line items in one Order (e.g. "Prebid Header Bidding") for one-click pause/activate.

Limelight onboarding

  1. Apply for a Limelight account via your CSM.
  2. Receive credentials: publisherIddata-pub-id; adUnitIddata-adunit-id; hostdata-host.
  3. Submit publisher domain(s) for allowlist approval (1–3 business days).
  4. Verify bidding using the testing checklist.
Pre-allowlist

You can test integration mechanics before allowlisting completes — the bidder returns no-bid and GAM's fallback fills.

Testing & verification

Append ?debug=true to your URL.

Console (filter for STEP)

  • STEP 1 Auction Initialized · Target: limelightDigital · Timeout: 1200ms
  • STEP 1.5 Requesting from Limelight. Player size: WxH
  • WINNER <bidder> · Raw CPM: $X.XX, or NO MARKET DEMAND
  • STEP 6 Dispatching VAST Request

Network

RequestStatus
cdn.jsdelivr.net/.../player.js + .../prebid.js200
imasdk.googleapis.com/.../ima3.js200
POST {host}/ortbhb — inspect Payload200
prebid.adnxs.com/pbc/v1/cache (winning bid only)200
GET pubads.g.doubleclick.net/gampad/ads — decode cust_params, must contain hb_pb, hb_bidder, hb_uuid200

Visual

  • Pre-roll plays before content; Video.js controls (play / pause / mute / volume / progress / fullscreen) respond.

Troubleshooting

No POST /ortbhb in Network
  • pbjs.installedModules must include limelightDigitalBidAdapter. If missing, fix data-prebid-url.
  • Look for "Canceling auction as per consentManagement config" in console (see Consent).
200 response but empty seatbid
  • Domain not allowlisted by Limelight — the most common cause.
  • Player rendered < 300×200 — bidders may reject small inventory.
Bid wins but no ad plays / GAM falls through
  • cust_params must contain hb_uuid. Missing → engine < v1.2.0, upgrade.
  • Line item targeting must match Prebid's string format exactly: "2.50" not "2.5".
  • VAST wrapper must use %%PATTERN:hb_uuid%%.
Request timeout after 1200ms

Increase data-timeout to 15002000 ms, or ask Limelight for a regional endpoint.

Autoplay doesn't start

Confirm data-autoplay="true" AND data-muted="true". HTTPS required. iOS Safari has additional restrictions with no workaround.

Mixed-content warnings

HTTPS page + http:// content URL / GAM tag / creative. Force everything to HTTPS.

FAQ

Multiple players on the same page?

Not currently. Workaround: iframe per player.

Other Prebid bidders / multiple SSPs?

Yes — v2 supports multi-bidder via data-bidders. Ask your account manager which SSPs you need; they will generate a Prebid bundle containing those adapters.

If Prebid fails to load?

Engine catches it and calls GAM with hb_pb=0.00&hb_bidder=none. House line item fills.

Auction analytics?

Impression-level: GAM Reports filtered by hb_bidder. Auction-level (bid latency / rate): request a Prebid build with an analytics adapter.

Latency impact?

async script — zero impact on Time to Interactive. Adds the bidder timeout (default 1200 ms) before pre-roll start.

Auction refresh / mid-rolls?

Not currently supported. Once per page load.

@v2.5.1 vs @main?

Tags are immutable (1-year CDN cache). @main = latest commit (~12 h cache). Pin tags for prod.