@trillboards/ctv-measurement
v0.1.0
Published
CTV co-viewing measurement and audience enrichment SDK
Maintainers
Readme
@trillboards/ctv-measurement
CTV co-viewing measurement and audience enrichment SDK. Zero runtime dependencies.
Features
- BLE co-viewing measurement via Android WebView bridge
- Device fingerprinting (canvas, WebGL, audio)
- IP detection (WebRTC + HTTP fallback)
- Census demographic enrichment
- CTV viewability tracking (MRC DOOH-compliant, 95% duration threshold)
- QR attribution URL generation
- BLE proximity confidence scoring
- Connection quality signals
- Session tracking with crypto-grade session IDs
- GDPR/CCPA consent gating
Install
npm install @trillboards/ctv-measurementQuick Start
import { CtvMeasurement } from '@trillboards/ctv-measurement';
// Initialize
const sdk = await CtvMeasurement.create({
apiKey: 'your-api-key',
screenId: 'screen-123',
debug: false,
});
// Track ad events from IMA SDK
sdk.trackAdEvent('impression', { adId: 'ad1', placementId: 'p1', scheduledDurationMs: 30000 });
sdk.trackAdEvent('start', { adId: 'ad1', placementId: 'p1' });
sdk.trackAdEvent('complete', { adId: 'ad1', placementId: 'p1', actualDurationMs: 30000 });
// Measure — runs all modules in parallel
const payload = await sdk.measure();
console.log(payload);
// => { schema_version: '0.1', sessionId: '...', bleDeviceCount: 3, viewable: true, ... }
// Check viewability
const verdict = sdk.getViewability();
console.log(verdict.viewable, verdict.reason);
// => true 'ctv_full_completion'
// Generate a QR tracking URL — appends tb_sid/tb_aid/tb_pid params to your destination URL.
// The next sdk.measure() call will include the scanId in qrScanId for impression correlation.
const qrUrl = sdk.getQrTrackingUrl('https://shop.example.com/landing', 'ad1', 'placement1');
// => https://shop.example.com/landing?tb_sid=...&tb_aid=ad1&tb_pid=placement1
// Clean up
sdk.destroy();GDPR/CCPA Consent
// Deny consent — measure() returns zeroed payload with no signals
sdk.setConsentStatus(false);
// Re-grant consent
sdk.setConsentStatus(true);Android WebView Integration
The companion trillboards-measurement-sdk Android library handles both modes
automatically. From a publisher app:
// In Application.onCreate() or Activity.onCreate()
TrillboardsMeasurement.initialize(
context,
MeasurementConfig.Builder("your-api-key")
.scanIntervalMs(30_000)
.build()
)
TrillboardsMeasurement.setConsentStatus(true) // After GDPR/CCPA consent
// Before WebView.loadUrl()
TrillboardsMeasurement.attachToWebView(webView)
TrillboardsMeasurement.startScheduledScans()The Android library exposes window.TrillboardsMeasurement.getSnapshot() (pull
mode) and dispatches window.dispatchEvent(new CustomEvent('trillboards:measurement', {detail}))
on each scan (push mode). The JS SDK listens to both automatically.
Events
sdk.on('scan_complete', (snapshot) => {
console.log(`BLE scan: ${snapshot.deviceCount} devices`);
});
sdk.on('viewability_update', (verdict) => {
console.log(`Viewable: ${verdict.viewable} (${verdict.reason})`);
});
sdk.on('enrichment_received', (enrichment) => {
console.log(`Income segment: ${enrichment.iabIncomeSegment?.name}`);
});
sdk.on('error', ({ module, message }) => {
console.error(`Module ${module} failed: ${message}`);
});Script Tag (IIFE)
<script src="https://cdn.trillboards.com/sdk/trillboards-ctv-measurement.global.js"></script>
<script>
TrillboardsCtvMeasurement.create({ apiKey: 'your-key' })
.then(sdk => sdk.measure())
.then(payload => console.log(payload));
</script>API Reference
CtvMeasurement.create(config)
Factory method. Returns Promise<CtvMeasurement>.
| Option | Type | Required | Default |
| ---------- | ------- | -------- | -------------------------------- |
| apiKey | string | Yes | |
| apiBase | string | No | https://api.trillboards.com |
| screenId | string | No | |
| debug | boolean | No | false |
sdk.measure()
Runs all measurement modules in parallel. Returns Promise<ImpressionMetadata>.
sdk.trackAdEvent(event, data?)
Track an IMA SDK ad lifecycle event. Events: impression, start, firstQuartile, midpoint, thirdQuartile, complete.
sdk.getViewability()
Returns current ViewabilityVerdict without tracking a new event.
sdk.getQrTrackingUrl(destinationUrl, adId, placementId)
Returns a QR tracking URL by appending tb_sid, tb_aid, tb_pid query parameters
to the publisher's destinationUrl. Mobile users scan the QR → land on the destination
page → the publisher's page extracts tb_sid and POSTs to /v2/sdk/qr/scan to record
the scan and unlock attribution.
The generated tb_sid is also stored on the SDK instance and included as qrScanId
in the next measure() payload for impression correlation.
sdk.setConsentStatus(granted)
Set GDPR/CCPA consent. When false, measure() returns zeroed payload.
sdk.on(event, handler) / sdk.off(event, handler)
Subscribe/unsubscribe to SDK events.
sdk.destroy()
Clean up listeners and internal state.
License
MIT
