Broadsign Integration
An open-source HTML5 package for Broadsign Control that connects your DOOH screens to Adlocaite programmatic demand. Built for publishers who run Broadsign as their playout system.
Open Source
This integration is MIT-licensed and open source. Contributions are welcome. View the source on GitHub or read the Contributing Guide.
Overview
The Adlocaite Broadsign Integration is an HTML5 package (.x-html-package) that runs inside the Broadsign Control Player. When Broadsign schedules an ad slot for this package, it automatically requests a programmatic advertisement from the Adlocaite API, plays the creative (video or image), fires VAST tracking events, and confirms the playout.
The package is designed as a self-contained unit: no external build tools, no server-side components, no dependencies beyond what ships in the package. You configure it with your API key, build the package with a single command, and upload it to Broadsign Control.
Key features
- VAST 2.0/3.0/4.0 support -- Industry-standard ad serving protocol for video and image creatives
- VAST tracking pixels -- Fires impression, start, quartile, and completion events; the
completepixel is the playout signal to the backend - PREBUFFER pre-loading -- Content is loaded off-screen during Broadsign's pre-buffering phase for instant playback
- Strict Accept -- No playback without a
deal_id; offers that fail to close commercially are skipped, not silently served - WebSocket skip signal -- Reliable skip via Broadsign Remote Control API for seamless waterfall fallback
- Remote error logging -- Optional Axiom integration for production monitoring
- Graceful error handling -- API errors are handled without crashing the Broadsign Player, with fast fail and retry
- Debug mode -- Visual debug panel and detailed console logging for troubleshooting
- Browser-based test interface -- Test the full lifecycle with PREBUFFER simulation, without a Broadsign Player
- Zero dependencies -- Pure vanilla JavaScript, no external libraries or build tools
- Open source (MIT) -- Fully inspectable and modifiable
Current status
- Name
Version- Type
- string
- Description
2.0.0
- Name
License- Type
- string
- Description
MIT
- Name
Status- Type
- string
- Description
Stable (V2)
- Name
Requirements- Type
- string
- Description
Broadsign Control 15.4+ (Chromium 87+), Remote Control enabled
- Name
Repository- Type
- string
- Description
How it works
The integration follows a linear lifecycle within a single Broadsign ad slot:
Playback lifecycle
- Pre-Loading (PREBUFFER) -- Broadsign loads the HTML5 package off-screen. During this phase,
BroadSignObject.frame_idis already available. The package immediately requests an offer from the Adlocaite API, parses the VAST response, accepts the offer, and pre-loads the media asset. Accept and media download run in parallel. - Strict Accept -- The package only proceeds to playback if the accept call returned a
deal_id. Without a deal the offer was not commercially closed, so the package skips rather than serve inventory. - Skip Signal -- If no offer is available, the network fails, or the accept did not produce a
deal_id, the package sends askip_nextWebSocket command to Broadsign's Remote Control API (ws://localhost:2326). Broadsign then moves to the next item in the programmatic waterfall. The offer request uses a 2s timeout with one 1s retry to ensure skip fires within the PREBUFFER window. - BroadSignPlay() -- Broadsign calls
BroadSignPlay()when the ad slot becomes visible. Pre-loaded content plays instantly with no loading delay. - Playback & Tracking -- The media plays while VAST tracking pixels are fired at impression, start, quartiles (25%, 50%, 75%), and completion. The
completepixel is the playout signal to the backend -- there is no separate confirm endpoint call.
Architecture
The package consists of five core modules:
- Name
AdlocaiteApp- Type
- Orchestrator
- Description
Main application class in
index.html. Manages initialization, PREBUFFER pre-loading, and playback lifecycle. Coordinates all other modules. CentralizedsetPlaybackStatus()handles WebSocket skip commands, Axiom logging, and UI updates atomically.
- Name
BroadsignAdapter- Type
- broadsign-adapter.js
- Description
Handles Broadsign Control Player integration:
BroadSignPlay()lifecycle with dual handler (function + custom event), screen ID extraction fromBroadSignObject.frame_id, and WebSocketskip_nextcommand via Remote Control API.
- Name
AdlocaiteAPIClient- Type
- adlocaite-api.js
- Description
HTTP client for the Adlocaite API. Handles offer requests (by screen ID or external ID) and offer acceptance/rejection. Offer requests use aggressive timeouts (2s + 1s retry) to fit within the PREBUFFER window. Playout reporting happens via VAST tracking pixels fired by
AdlocaitePlayer, not via a separate API call.
- Name
AdlocaiteLogger- Type
- logger.js
- Description
Centralized logging with optional Axiom integration for production error monitoring. Buffers events and flushes periodically or immediately on errors. Graceful degradation without Axiom token (console-only).
- Name
VASTParser- Type
- vast-parser.js
- Description
Parses VAST XML responses. Extracts media files, tracking URLs, deal IDs from custom extensions (supports multiple naming variants), and creative metadata. Supports VAST 2.0, 3.0, and 4.0.
- Name
AdlocaitePlayer- Type
- player.js
- Description
Media playback engine. Pre-loads video and image assets during PREBUFFER phase (
canplayevent for streaming playback). Handles HTML5 video with muted autoplay (Chromium 87+ requirement), image display with timed duration, and VAST tracking pixel firing.
Integration comparison
Adlocaite offers multiple integration paths for publishers. Choose the one that fits your infrastructure:
Integration | Setup Effort | Maintenance | Customizability | Best For |
|---|---|---|---|---|
| Core API (Direct) | High | Self-managed | Full | Custom CMS / full control |
| Grassfish CMS | Low | Managed by Grassfish | Limited | Grassfish CMS users |
| Broadsign | Medium | Self-managed (open source) | High (fork & modify) | Broadsign Control users |
| OpenRTB 2.6 | Medium | Managed by Adlocaite | Limited (protocol constraints) | SSP / legacy RTB systems |
Getting started
Prerequisites
Before you begin, make sure you have:
- Adlocaite Publisher API key -- Obtain one through the Publisher Onboarding process
- Screens registered in Adlocaite -- Each screen needs an
external_idmatching the Broadsignframe_id(see Screen Registration) - Git installed on your machine
- Broadsign Control 15.4+ (Chromium 87+) for production deployment
- Remote Control enabled in Broadsign Control Player settings (required for WebSocket skip signaling)
Step 1: Clone the repository
Clone
git clone https://github.com/Adlocaite/adlocaite-broadsign.git
cd adlocaite-broadsign
Step 2: Configure your API key
cp package/js/config.example.js package/js/config.js
Open package/js/config.js and set your API key and environment:
const ADLOCAITE_CONFIG = {
// Your publisher API key (required)
apiKey: 'pub_your_actual_api_key_here',
// Use production URL for live screens
apiBaseUrl: 'https://api.adlocaite.com/functions/v1/api',
// Minimum bid price in cents (100 = 1.00 EUR, 0.5 = half a cent)
minBidCents: 100,
// Disable debug mode for production
debugMode: false,
// Keep other defaults unless you have specific requirements
// ...
};
See the full Configuration Reference below for all available options.
Step 3: Build the package
Build
./build.sh
This creates adlocaite-broadsign.x-html-package in the project root. The build script validates your config, injects the version number, and packages everything into a zip file with the .x-html-package extension.
Step 4: Deploy to Broadsign Control
- Open Broadsign Control Administrator
- Navigate to Library > Ad Copies
- Click Upload and select the
.x-html-packagefile - Assign the ad copy to your campaign
Step 5: Configure a fallback campaign
Fallback campaign required
You must configure a separate fallback campaign in Broadsign Control. When Adlocaite has no ad to serve, the integration signals Broadsign to skip, but Broadsign needs fallback content to display instead. Without this, empty slots will show a black screen. See Known Limitations for details.
Deployment checklist
- API key configured in
config.js(not the placeholderpub_xxxx) - API base URL set to production (
https://api.adlocaite.com/functions/v1/api) - Debug mode disabled for production deployment
- Package built with
./build.sh(check for warnings) - Screens registered in Adlocaite with matching
external_id - Fallback campaign configured in Broadsign Control
- Tested on staging before rolling out to production
- Remote Control enabled in Broadsign Control Player settings (required for skip signaling)
Configuration reference
Configuration lives in package/js/config.js. This file is loaded as a global JavaScript object and must not be committed to version control (it contains your API key).
The config file exports a global ADLOCAITE_CONFIG object:
const ADLOCAITE_CONFIG = {
apiKey: 'pub_your_api_key_here',
apiBaseUrl: 'https://api.adlocaite.com/functions/v1/api',
minBidCents: 100,
vastMode: true,
debugMode: false,
axiomToken: '',
axiomDataset: 'broadsign',
packageVersion: '2.0.0',
};
if (typeof window !== 'undefined') {
window.ADLOCAITE_CONFIG = ADLOCAITE_CONFIG;
}
Never commit config.js
The file package/js/config.js contains your API key and is listed in .gitignore. Only config.example.js should be committed. Git hooks in the repository will prevent accidental commits of sensitive data.
Required parameters
- Name
apiKey- Type
- string
- Description
Publisher API key for authenticating with the Adlocaite API. Obtain this from your onboarding team or the Adlocaite Dashboard. Must start with
pub_.
- Name
apiBaseUrl- Type
- string
- Description
Base URL for the Adlocaite API. Determines whether you connect to staging or production.
- Production:
https://api.adlocaite.com/functions/v1/api - Staging:
https://staging.api.adlocaite.com/functions/v1/api
- Production:
Offer configuration
- Name
minBidCents- Type
- number
- Description
Minimum bid price in cents. Only offers with bids at or above this value will be accepted. Accepts decimal values for subcent precision (e.g.,
0.5for half a cent). For example,100means a minimum bid of 1.00 EUR. Default:100
- Name
vastMode- Type
- boolean
- Description
When
true, API requests includevast=trueto receive VAST XML responses. VAST provides standardized tracking and better compatibility with industry tools. Disable only if you need raw JSON offer responses. Default:true
Debug configuration
- Name
debugMode- Type
- boolean
- Description
Enable detailed logging and the visual debug panel. When
true, all modules log timestamped messages to the browser console, and a debug overlay is shown on screen. Disable for production. Default:false
Remote logging (Axiom)
- Name
axiomToken- Type
- string
- Description
Axiom ingest-only API token for remote error logging. Leave empty to disable remote logging (console-only). Get from Axiom dashboard under Settings > API Tokens (ingest-only permission). Default:
''
- Name
axiomDataset- Type
- string
- Description
Axiom dataset name where error events are sent. Default:
'broadsign'
- Name
packageVersion- Type
- string
- Description
Version string included in log events. Auto-injected by the build script from
package.json. Default:'2.0.0'
Environment setup
Staging -- Use for testing and development. Staging uses separate API keys and campaign data from production.
{
apiKey: 'pub_your_staging_key',
apiBaseUrl: 'https://staging.api.adlocaite.com/functions/v1/api',
debugMode: true,
minBidCents: 1, // Low threshold for testing
}
Production -- Use for live screens serving real ad campaigns.
{
apiKey: 'pub_your_production_key',
apiBaseUrl: 'https://api.adlocaite.com/functions/v1/api',
debugMode: false, // Always disable in production
minBidCents: 100, // Set your actual minimum
}
Test on staging first
Always test your configuration on the staging environment before deploying to production screens. Staging and production use separate API keys -- a staging key will not work on production and vice versa.
Screen registration
Each Broadsign screen must be registered in the Adlocaite platform with a matching identifier. The integration uses the Broadsign frame_id as the screen identifier.
How screen matching works
- Broadsign provides
BroadSignObject.frame_idto the HTML5 package at runtime - The integration sends this
frame_idto the Adlocaite API as anexternal_id - The API looks up the screen by its
external_idand returns matching offers
Fallback identification methods (in order): URL parameter ?screen_id=, localStorage value adlocaite_screen_id.
Finding your frame_id
Check your Broadsign Player debug logs to find the frame_id value. The frame_id is assigned by Broadsign when you configure a frame (display area) in Broadsign Control.
Alternatively, in the test interface, the frame_id field shows what value would be used.
Registering in Adlocaite
In the Adlocaite Dashboard, set the screen's external_id to match the Broadsign frame_id. For detailed instructions, see External Screen IDs.
Verifying the mapping
Enable debugMode: true and check the console logs for:
[Broadsign Adapter] Screen ID (frame_id) from BroadSignObject: 842292831
Then verify the API responds with offers (not 404) for this screen ID.
Testing
The built-in test interface (/test/) simulates the Broadsign Control Player in your browser.
Starting the test server
npm run test:serve
# Open http://127.0.0.1:8000/test/
Test interface features
- Configuration panel -- Set
frame_id, API key, environment, resolution, and options - BroadSignObject simulation -- Mocks the
BroadSignObjectthat Broadsign injects - Manual lifecycle control -- "Load Package" initializes the integration, "Trigger Play" calls
BroadSignPlay() - Real-time log output -- All console output from the package is displayed
- Status monitoring -- Observes WebSocket skip commands and the package's playback status events
- Persistent config -- Settings are saved to localStorage and can be passed via URL parameters
Quick test via URL parameters
http://127.0.0.1:8000/test/?api_key=pub_xxx&frame_id=842292831&env=staging&debug=true
Test scenarios
- Happy path -- Configure a valid
frame_idand API key, load package, trigger play. Expected: ad plays successfully,completetracking pixel fires at end. - No offers -- Use a
frame_idthat has no active campaigns. Expected: WebSocketskip_nextsent, logs show "no offers available". - Invalid screen -- Use a non-existent
frame_id. Expected: 404 handled gracefully, skip signal sent. - Invalid API key -- Use
pub_invalid. Expected: 401 error in logs, skip signal sent. - Accept failure (Strict Accept) -- Force an expired offer (let one age past 12 minutes before triggering play) or otherwise cause
/offers/response/{offerId}to return 4xx. Expected: skip signal sent with reasonaccept failed, Axiom event includes the backenderror_code. The ad does not play.
Strengths & limitations
Strengths
- Name
Zero-dependency package- Description
The integration is pure vanilla JavaScript with no external dependencies, build tools, or bundlers. This makes it lightweight, easy to audit, and compatible with any Broadsign Control version that supports HTML5 (Chromium 87+).
- Name
VAST standard compliance- Description
Full support for VAST 2.0, 3.0, and 4.0. This means the integration works with industry-standard ad serving infrastructure and fires all expected tracking events (impression, start, quartiles, complete).
- Name
Graceful error handling- Description
API errors (404, 5xx) are handled without throwing exceptions that could crash the Broadsign Player. The integration returns structured error objects and signals Broadsign to skip to fallback content instead.
- Name
PREBUFFER pre-loading- Description
Content is loaded during Broadsign's off-screen pre-buffering phase. Accept offer and media download run in parallel. When the ad slot becomes visible, playback starts instantly.
- Name
Reliable skip signaling- Description
WebSocket
skip_nextcommand via Broadsign Remote Control API provides immediate, reliable skipping. Fast fail (2s timeout + 1s retry) ensures skip fires within the PREBUFFER window.
- Name
Strict Accept (no inventory leaks)- Description
The package only proceeds to playback if the offer accept call returned a
deal_id. If accept fails -- e.g.OFFER_NOT_FOUNDfor an expired or already-consumed offer,PRICE_VALIDATION_FAILED, or a network error -- the package skips instead of serving the ad. Without a deal the offer was not commercially closed, so playing would mean giving inventory away. The backenderror_codeis forwarded to Axiom so failures are diagnosable rather than silent.
- Name
Built-in test interface- Description
A browser-based test UI simulates the Broadsign Player environment with PREBUFFER simulation,
BroadSignObjectinjection,BroadSignPlay()triggering, and real-time log output. No Broadsign hardware required for development.
- Name
Open source (MIT)- Description
Fully open source under the MIT license. You can inspect, modify, and redistribute the code. Contributions are welcome via the GitHub repository.
Known limitations
Remote Control required -- The WebSocket skip mechanism requires Broadsign's Remote Control API to be enabled on the player. Without it, there is no reliable skip mechanism and the player may show black screens when no ad is available.
Fallback campaign required -- Publishers must configure a fallback campaign in Broadsign Control. When the integration signals skip, Broadsign needs fallback content to display instead.
No automated test suite -- The integration currently relies on manual testing via the browser-based test interface. Automated end-to-end tests are planned but not yet implemented.
Muted video playback -- Due to Chromium 87+ autoplay policies, all video playback is muted (muted=true). This is a browser-level restriction -- unmuted autoplay is blocked by the Chromium engine used in Broadsign Control.
Comparison with direct API
If you can build a custom integration using the Core API directly, here is what you gain and lose compared to using the Broadsign package:
Aspect | Broadsign Package | Direct Core API |
|---|---|---|
| Setup time | Minutes (clone, configure, build) | Days to weeks (custom development) |
| Playout system | Broadsign Control only | Any system |
| Offer workflow | Automated (request + accept + play) | Full control (request, review, accept/reject) |
| VAST tracking | Built-in | Must implement yourself |
| Pre-loading | PREBUFFER pre-loading (automatic) | Custom implementation possible |
| Customizability | Config + source modification | Unlimited |
| Fallback handling | Requires Broadsign fallback campaign | Fully custom |
Troubleshooting
No screen ID available
The package cannot determine which screen to request offers for.
- In Broadsign Player: Verify that
frame_idis configured in your Broadsign setup - In the test interface: Enter a
frame_idin the configuration panel - Check Broadsign Player debug logs for
BroadSignObjectvalues
404 -- No offers available
The API cannot find matching offers for this screen.
- Verify the screen is registered in Adlocaite with the correct
external_id - Check that there are active campaigns targeting this screen
- Ensure the screen's resolution matches available ad creatives
401 -- Invalid API key
Authentication failed.
- Verify your API key in
config.jsstarts withpub_ - Check that the key is for the correct environment (staging vs. production)
- Ensure there are no trailing spaces or newlines in the key
CORS errors
Asset loading fails with cross-origin errors.
- Ad asset servers must include
Access-Control-Allow-Origin: *header - This is configured on the Adlocaite side -- contact support if you encounter this
Black screen / no ad playing
The ad slot is visible but nothing appears.
- Ensure a fallback campaign is configured in Broadsign Control
- Enable
debugMode: truein config and check console output - Verify the API is reachable from the player network
Build fails
The build.sh script reports errors.
- Ensure
package/js/config.jsexists (copy fromconfig.example.js) - Check that
zipis installed (brew install zipon macOS,apt install zipon Ubuntu) - Verify the API key line is not still set to the placeholder
pub_xxxx