@trillboards/ads-sdk 2.1.1 → 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/README.md +9 -1
- package/dist/cli.js +2 -2
- package/dist/index.d.mts +45 -5
- package/dist/index.d.ts +45 -5
- package/dist/index.js +124 -11
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +124 -11
- package/dist/index.mjs.map +1 -1
- package/dist/react-native.d.mts +2 -0
- package/dist/react-native.d.ts +2 -0
- package/dist/react-native.js +1 -0
- package/dist/react-native.js.map +1 -1
- package/dist/react-native.mjs +1 -0
- package/dist/react-native.mjs.map +1 -1
- package/dist/react.d.mts +6 -0
- package/dist/react.d.ts +6 -0
- package/dist/react.js +124 -8
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +124 -8
- package/dist/react.mjs.map +1 -1
- package/dist/server.js +2 -2
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +2 -2
- package/dist/server.mjs.map +1 -1
- package/dist/trillboards-lite.global.js +1 -1
- package/dist/trillboards-lite.global.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `@trillboards/ads-sdk` will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [2.2.0] - 2026-02-24
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
- Heartbeat payloads now include runtime telemetry (`telemetry`, `sdk`, `device`, `network`) for partner-side device profiling.
|
|
9
|
+
- SDK now consumes heartbeat `ad_delivery_profile` responses and prefers direct fallback playback when profile mode is `vast_fallback`.
|
|
10
|
+
- SDK now executes queued heartbeat commands (`refresh_ads`, `restart`) delivered by the partner API polling channel.
|
|
11
|
+
|
|
12
|
+
### Fixes
|
|
13
|
+
- Programmatic retry/backoff now resets correctly on ad completion and no-fill-like errors to prevent runaway retry escalation.
|
|
14
|
+
|
|
5
15
|
## [2.1.1] - 2026-02-15
|
|
6
16
|
|
|
7
17
|
### Fixes
|
package/README.md
CHANGED
|
@@ -93,6 +93,14 @@ The `TrillboardsConfig` interface accepts the following options:
|
|
|
93
93
|
| `refreshInterval` | `number` | `120000` | Ad refresh interval (ms) |
|
|
94
94
|
| `cacheSize` | `number` | `10` | Max cached ads |
|
|
95
95
|
|
|
96
|
+
## Heartbeat Telemetry and Delivery Profile
|
|
97
|
+
|
|
98
|
+
Every heartbeat now includes runtime telemetry (`sdk`, `device`, `network`, `ad`) so the partner API can segment legacy devices and return an `ad_delivery_profile`.
|
|
99
|
+
|
|
100
|
+
- `mode: "ima_sdk"` keeps normal IMA playback.
|
|
101
|
+
- `mode: "vast_fallback"` indicates the SDK should prefer direct fallback playback when direct ads are available.
|
|
102
|
+
- Heartbeat command polling now executes queued `refresh_ads` commands immediately.
|
|
103
|
+
|
|
96
104
|
## Debug Mode
|
|
97
105
|
|
|
98
106
|
Enable debug logging to see all API requests, state transitions, and cache operations:
|
|
@@ -215,7 +223,7 @@ console.log('Tracked:', result.tracked);
|
|
|
215
223
|
|
|
216
224
|
## Links
|
|
217
225
|
|
|
218
|
-
- [Developer documentation](https://trillboards.com/developers/partner-sdk)
|
|
226
|
+
- [Developer documentation](https://trillboards.com/support/developers/partner-sdk)
|
|
219
227
|
- [API reference](https://api.trillboards.com/docs/partner)
|
|
220
228
|
|
|
221
229
|
## License
|
package/dist/cli.js
CHANGED
|
@@ -28,7 +28,7 @@ var fs__namespace = /*#__PURE__*/_interopNamespace(fs);
|
|
|
28
28
|
var path__namespace = /*#__PURE__*/_interopNamespace(path);
|
|
29
29
|
|
|
30
30
|
// src/core/config.ts
|
|
31
|
-
var SDK_VERSION = "2.
|
|
31
|
+
var SDK_VERSION = "2.2.0";
|
|
32
32
|
|
|
33
33
|
// src/cli.ts
|
|
34
34
|
var BANNER = `
|
|
@@ -127,7 +127,7 @@ async function runInit() {
|
|
|
127
127
|
console.log(" Next steps:");
|
|
128
128
|
console.log(" 1. Register more devices: POST /v1/partner/device");
|
|
129
129
|
console.log(" 2. Connect Stripe for payouts: POST /v1/partner/stripe/connect");
|
|
130
|
-
console.log(" 3. Read the docs: https://trillboards.com/developers");
|
|
130
|
+
console.log(" 3. Read the docs: https://trillboards.com/support/developers");
|
|
131
131
|
console.log("");
|
|
132
132
|
completed = true;
|
|
133
133
|
} catch (err) {
|
package/dist/index.d.mts
CHANGED
|
@@ -59,6 +59,7 @@ interface TrillboardsState {
|
|
|
59
59
|
programmaticPlaying: boolean;
|
|
60
60
|
prefetchedReady: boolean;
|
|
61
61
|
waterfallMode: WaterfallMode;
|
|
62
|
+
adDeliveryProfileMode: AdDeliveryMode | null;
|
|
62
63
|
screenId: string | null;
|
|
63
64
|
deviceId: string | null;
|
|
64
65
|
}
|
|
@@ -113,6 +114,37 @@ interface CircuitBreakerState {
|
|
|
113
114
|
consecutiveFailures: number;
|
|
114
115
|
openUntil: number;
|
|
115
116
|
}
|
|
117
|
+
type AdDeliveryMode = 'ima_sdk' | 'vast_fallback';
|
|
118
|
+
interface AdDeliveryProfile {
|
|
119
|
+
mode: AdDeliveryMode;
|
|
120
|
+
reason?: string;
|
|
121
|
+
auto_recovery_enabled?: boolean;
|
|
122
|
+
ima_integration?: 'android_native' | 'html5_webview' | 'disabled' | 'unknown';
|
|
123
|
+
android_api_level?: number | null;
|
|
124
|
+
webview_chromium_major?: number | null;
|
|
125
|
+
notes?: string[];
|
|
126
|
+
}
|
|
127
|
+
interface HeartbeatCommand {
|
|
128
|
+
id: string;
|
|
129
|
+
command: string;
|
|
130
|
+
payload?: Record<string, unknown>;
|
|
131
|
+
queued_at?: string;
|
|
132
|
+
}
|
|
133
|
+
interface HeartbeatResponseData {
|
|
134
|
+
status?: 'online' | 'offline' | string;
|
|
135
|
+
last_seen_at?: string;
|
|
136
|
+
ad_delivery_profile?: AdDeliveryProfile;
|
|
137
|
+
commands?: HeartbeatCommand[];
|
|
138
|
+
}
|
|
139
|
+
interface HeartbeatPayload {
|
|
140
|
+
telemetry?: Record<string, unknown>;
|
|
141
|
+
metadata?: Record<string, unknown>;
|
|
142
|
+
sdk?: Record<string, unknown>;
|
|
143
|
+
device?: Record<string, unknown>;
|
|
144
|
+
network?: Record<string, unknown>;
|
|
145
|
+
ad?: Record<string, unknown>;
|
|
146
|
+
[key: string]: unknown;
|
|
147
|
+
}
|
|
116
148
|
interface FetchAdsResult {
|
|
117
149
|
ads: AdItem[];
|
|
118
150
|
settings: Record<string, unknown>;
|
|
@@ -260,6 +292,10 @@ declare class TrillboardsAds {
|
|
|
260
292
|
private refreshAds;
|
|
261
293
|
private startRefreshTimer;
|
|
262
294
|
private startHeartbeatTimer;
|
|
295
|
+
private sendHeartbeatTick;
|
|
296
|
+
private buildHeartbeatPayload;
|
|
297
|
+
private applyAdDeliveryProfile;
|
|
298
|
+
private runHeartbeatCommands;
|
|
263
299
|
private playNextAd;
|
|
264
300
|
private playProgrammatic;
|
|
265
301
|
private playDirect;
|
|
@@ -317,7 +353,7 @@ declare class EventEmitter {
|
|
|
317
353
|
}
|
|
318
354
|
|
|
319
355
|
/** Single source of truth for the SDK version string. */
|
|
320
|
-
declare const SDK_VERSION = "2.
|
|
356
|
+
declare const SDK_VERSION = "2.2.0";
|
|
321
357
|
/**
|
|
322
358
|
* Compile-time constants that mirror the original IIFE CONFIG
|
|
323
359
|
* object. Every value here acts as a sensible production default
|
|
@@ -336,7 +372,7 @@ declare const DEFAULT_CONFIG: {
|
|
|
336
372
|
readonly PROGRAMMATIC_MIN_INTERVAL_MS: 5000;
|
|
337
373
|
readonly PROGRAMMATIC_RETRY_MS: 5000;
|
|
338
374
|
readonly PROGRAMMATIC_BACKOFF_MAX_MS: number;
|
|
339
|
-
readonly VERSION: "2.
|
|
375
|
+
readonly VERSION: "2.2.0";
|
|
340
376
|
};
|
|
341
377
|
/**
|
|
342
378
|
* Merge a caller-supplied TrillboardsConfig with the defaults,
|
|
@@ -392,6 +428,7 @@ interface InternalState {
|
|
|
392
428
|
programmaticRetryActive: boolean;
|
|
393
429
|
programmaticRetryCount: number;
|
|
394
430
|
programmaticLastError: string | null;
|
|
431
|
+
adDeliveryProfile: AdDeliveryProfile | null;
|
|
395
432
|
initialized: boolean;
|
|
396
433
|
screenOrientation: string | null;
|
|
397
434
|
screenDimensions: ScreenDimensions | null;
|
|
@@ -537,6 +574,10 @@ declare class WaterfallEngine {
|
|
|
537
574
|
recordFailure(sourceName: string): void;
|
|
538
575
|
}
|
|
539
576
|
|
|
577
|
+
interface HeartbeatResult {
|
|
578
|
+
ok: boolean;
|
|
579
|
+
data: HeartbeatResponseData | null;
|
|
580
|
+
}
|
|
540
581
|
/**
|
|
541
582
|
* Low-level HTTP client for the Trillboards Partner API.
|
|
542
583
|
*
|
|
@@ -580,10 +621,9 @@ declare class ApiClient {
|
|
|
580
621
|
completed: boolean;
|
|
581
622
|
}): Promise<boolean>;
|
|
582
623
|
/**
|
|
583
|
-
* Ping
|
|
584
|
-
* Returns `true` on 2xx, `false` on any error.
|
|
624
|
+
* Ping heartbeat endpoint and return delivery profile + queued commands.
|
|
585
625
|
*/
|
|
586
|
-
sendHeartbeat(deviceId: string, screenId: string | null): Promise<
|
|
626
|
+
sendHeartbeat(deviceId: string, screenId: string | null, payload?: HeartbeatPayload): Promise<HeartbeatResult>;
|
|
587
627
|
/**
|
|
588
628
|
* Report a programmatic lifecycle event (VAST fill, timeout,
|
|
589
629
|
* error, etc.) to the analytics backend.
|
package/dist/index.d.ts
CHANGED
|
@@ -59,6 +59,7 @@ interface TrillboardsState {
|
|
|
59
59
|
programmaticPlaying: boolean;
|
|
60
60
|
prefetchedReady: boolean;
|
|
61
61
|
waterfallMode: WaterfallMode;
|
|
62
|
+
adDeliveryProfileMode: AdDeliveryMode | null;
|
|
62
63
|
screenId: string | null;
|
|
63
64
|
deviceId: string | null;
|
|
64
65
|
}
|
|
@@ -113,6 +114,37 @@ interface CircuitBreakerState {
|
|
|
113
114
|
consecutiveFailures: number;
|
|
114
115
|
openUntil: number;
|
|
115
116
|
}
|
|
117
|
+
type AdDeliveryMode = 'ima_sdk' | 'vast_fallback';
|
|
118
|
+
interface AdDeliveryProfile {
|
|
119
|
+
mode: AdDeliveryMode;
|
|
120
|
+
reason?: string;
|
|
121
|
+
auto_recovery_enabled?: boolean;
|
|
122
|
+
ima_integration?: 'android_native' | 'html5_webview' | 'disabled' | 'unknown';
|
|
123
|
+
android_api_level?: number | null;
|
|
124
|
+
webview_chromium_major?: number | null;
|
|
125
|
+
notes?: string[];
|
|
126
|
+
}
|
|
127
|
+
interface HeartbeatCommand {
|
|
128
|
+
id: string;
|
|
129
|
+
command: string;
|
|
130
|
+
payload?: Record<string, unknown>;
|
|
131
|
+
queued_at?: string;
|
|
132
|
+
}
|
|
133
|
+
interface HeartbeatResponseData {
|
|
134
|
+
status?: 'online' | 'offline' | string;
|
|
135
|
+
last_seen_at?: string;
|
|
136
|
+
ad_delivery_profile?: AdDeliveryProfile;
|
|
137
|
+
commands?: HeartbeatCommand[];
|
|
138
|
+
}
|
|
139
|
+
interface HeartbeatPayload {
|
|
140
|
+
telemetry?: Record<string, unknown>;
|
|
141
|
+
metadata?: Record<string, unknown>;
|
|
142
|
+
sdk?: Record<string, unknown>;
|
|
143
|
+
device?: Record<string, unknown>;
|
|
144
|
+
network?: Record<string, unknown>;
|
|
145
|
+
ad?: Record<string, unknown>;
|
|
146
|
+
[key: string]: unknown;
|
|
147
|
+
}
|
|
116
148
|
interface FetchAdsResult {
|
|
117
149
|
ads: AdItem[];
|
|
118
150
|
settings: Record<string, unknown>;
|
|
@@ -260,6 +292,10 @@ declare class TrillboardsAds {
|
|
|
260
292
|
private refreshAds;
|
|
261
293
|
private startRefreshTimer;
|
|
262
294
|
private startHeartbeatTimer;
|
|
295
|
+
private sendHeartbeatTick;
|
|
296
|
+
private buildHeartbeatPayload;
|
|
297
|
+
private applyAdDeliveryProfile;
|
|
298
|
+
private runHeartbeatCommands;
|
|
263
299
|
private playNextAd;
|
|
264
300
|
private playProgrammatic;
|
|
265
301
|
private playDirect;
|
|
@@ -317,7 +353,7 @@ declare class EventEmitter {
|
|
|
317
353
|
}
|
|
318
354
|
|
|
319
355
|
/** Single source of truth for the SDK version string. */
|
|
320
|
-
declare const SDK_VERSION = "2.
|
|
356
|
+
declare const SDK_VERSION = "2.2.0";
|
|
321
357
|
/**
|
|
322
358
|
* Compile-time constants that mirror the original IIFE CONFIG
|
|
323
359
|
* object. Every value here acts as a sensible production default
|
|
@@ -336,7 +372,7 @@ declare const DEFAULT_CONFIG: {
|
|
|
336
372
|
readonly PROGRAMMATIC_MIN_INTERVAL_MS: 5000;
|
|
337
373
|
readonly PROGRAMMATIC_RETRY_MS: 5000;
|
|
338
374
|
readonly PROGRAMMATIC_BACKOFF_MAX_MS: number;
|
|
339
|
-
readonly VERSION: "2.
|
|
375
|
+
readonly VERSION: "2.2.0";
|
|
340
376
|
};
|
|
341
377
|
/**
|
|
342
378
|
* Merge a caller-supplied TrillboardsConfig with the defaults,
|
|
@@ -392,6 +428,7 @@ interface InternalState {
|
|
|
392
428
|
programmaticRetryActive: boolean;
|
|
393
429
|
programmaticRetryCount: number;
|
|
394
430
|
programmaticLastError: string | null;
|
|
431
|
+
adDeliveryProfile: AdDeliveryProfile | null;
|
|
395
432
|
initialized: boolean;
|
|
396
433
|
screenOrientation: string | null;
|
|
397
434
|
screenDimensions: ScreenDimensions | null;
|
|
@@ -537,6 +574,10 @@ declare class WaterfallEngine {
|
|
|
537
574
|
recordFailure(sourceName: string): void;
|
|
538
575
|
}
|
|
539
576
|
|
|
577
|
+
interface HeartbeatResult {
|
|
578
|
+
ok: boolean;
|
|
579
|
+
data: HeartbeatResponseData | null;
|
|
580
|
+
}
|
|
540
581
|
/**
|
|
541
582
|
* Low-level HTTP client for the Trillboards Partner API.
|
|
542
583
|
*
|
|
@@ -580,10 +621,9 @@ declare class ApiClient {
|
|
|
580
621
|
completed: boolean;
|
|
581
622
|
}): Promise<boolean>;
|
|
582
623
|
/**
|
|
583
|
-
* Ping
|
|
584
|
-
* Returns `true` on 2xx, `false` on any error.
|
|
624
|
+
* Ping heartbeat endpoint and return delivery profile + queued commands.
|
|
585
625
|
*/
|
|
586
|
-
sendHeartbeat(deviceId: string, screenId: string | null): Promise<
|
|
626
|
+
sendHeartbeat(deviceId: string, screenId: string | null, payload?: HeartbeatPayload): Promise<HeartbeatResult>;
|
|
587
627
|
/**
|
|
588
628
|
* Report a programmatic lifecycle event (VAST fill, timeout,
|
|
589
629
|
* error, etc.) to the analytics backend.
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
// src/core/config.ts
|
|
4
|
-
var SDK_VERSION = "2.
|
|
4
|
+
var SDK_VERSION = "2.2.0";
|
|
5
5
|
var DEFAULT_CONFIG = {
|
|
6
6
|
API_BASE: "https://api.trillboards.com/v1/partner",
|
|
7
7
|
CDN_BASE: "https://cdn.trillboards.com",
|
|
@@ -60,6 +60,7 @@ var DEFAULT_PUBLIC_STATE = {
|
|
|
60
60
|
programmaticPlaying: false,
|
|
61
61
|
prefetchedReady: false,
|
|
62
62
|
waterfallMode: "programmatic_only",
|
|
63
|
+
adDeliveryProfileMode: null,
|
|
63
64
|
screenId: null,
|
|
64
65
|
deviceId: null
|
|
65
66
|
};
|
|
@@ -87,6 +88,7 @@ function createInitialState() {
|
|
|
87
88
|
programmaticRetryActive: false,
|
|
88
89
|
programmaticRetryCount: 0,
|
|
89
90
|
programmaticLastError: null,
|
|
91
|
+
adDeliveryProfile: null,
|
|
90
92
|
initialized: false,
|
|
91
93
|
screenOrientation: null,
|
|
92
94
|
screenDimensions: null,
|
|
@@ -104,6 +106,7 @@ function getPublicState(internal) {
|
|
|
104
106
|
programmaticPlaying: internal.programmaticPlaying,
|
|
105
107
|
prefetchedReady: internal.prefetchedReady ?? false,
|
|
106
108
|
waterfallMode: internal.waterfallMode,
|
|
109
|
+
adDeliveryProfileMode: internal.adDeliveryProfile?.mode ?? null,
|
|
107
110
|
screenId: internal.screenId,
|
|
108
111
|
deviceId: internal.deviceId
|
|
109
112
|
};
|
|
@@ -364,10 +367,9 @@ var ApiClient = class {
|
|
|
364
367
|
}
|
|
365
368
|
}
|
|
366
369
|
/**
|
|
367
|
-
* Ping
|
|
368
|
-
* Returns `true` on 2xx, `false` on any error.
|
|
370
|
+
* Ping heartbeat endpoint and return delivery profile + queued commands.
|
|
369
371
|
*/
|
|
370
|
-
async sendHeartbeat(deviceId, screenId) {
|
|
372
|
+
async sendHeartbeat(deviceId, screenId, payload = {}) {
|
|
371
373
|
logger.debug("Sending heartbeat", { deviceId });
|
|
372
374
|
try {
|
|
373
375
|
const response = await fetch(`${this.apiBase}/device/${deviceId}/heartbeat`, {
|
|
@@ -377,13 +379,24 @@ var ApiClient = class {
|
|
|
377
379
|
device_id: deviceId,
|
|
378
380
|
screen_id: screenId,
|
|
379
381
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
380
|
-
status: "active"
|
|
382
|
+
status: "active",
|
|
383
|
+
...payload
|
|
381
384
|
}),
|
|
382
385
|
signal: AbortSignal.timeout(5e3)
|
|
383
386
|
});
|
|
384
|
-
|
|
387
|
+
if (!response.ok) {
|
|
388
|
+
return { ok: false, data: null };
|
|
389
|
+
}
|
|
390
|
+
let data = null;
|
|
391
|
+
try {
|
|
392
|
+
const json = await response.json();
|
|
393
|
+
data = json?.data ?? null;
|
|
394
|
+
} catch {
|
|
395
|
+
data = null;
|
|
396
|
+
}
|
|
397
|
+
return { ok: true, data };
|
|
385
398
|
} catch {
|
|
386
|
-
return false;
|
|
399
|
+
return { ok: false, data: null };
|
|
387
400
|
}
|
|
388
401
|
}
|
|
389
402
|
/**
|
|
@@ -1676,11 +1689,104 @@ var _TrillboardsAds = class _TrillboardsAds {
|
|
|
1676
1689
|
}
|
|
1677
1690
|
startHeartbeatTimer() {
|
|
1678
1691
|
if (this.state.heartbeatTimer) clearInterval(this.state.heartbeatTimer);
|
|
1692
|
+
const tick = () => {
|
|
1693
|
+
this.sendHeartbeatTick().catch(() => {
|
|
1694
|
+
});
|
|
1695
|
+
};
|
|
1696
|
+
tick();
|
|
1679
1697
|
this.state.heartbeatTimer = setInterval(() => {
|
|
1680
|
-
|
|
1698
|
+
tick();
|
|
1681
1699
|
}, this.config.heartbeatInterval);
|
|
1682
1700
|
}
|
|
1701
|
+
async sendHeartbeatTick() {
|
|
1702
|
+
const result = await this.api.sendHeartbeat(
|
|
1703
|
+
this.config.deviceId,
|
|
1704
|
+
this.state.screenId,
|
|
1705
|
+
this.buildHeartbeatPayload()
|
|
1706
|
+
);
|
|
1707
|
+
if (!result.ok || !result.data) return;
|
|
1708
|
+
if (result.data.ad_delivery_profile?.mode) {
|
|
1709
|
+
this.applyAdDeliveryProfile(result.data.ad_delivery_profile);
|
|
1710
|
+
}
|
|
1711
|
+
if (Array.isArray(result.data.commands) && result.data.commands.length > 0) {
|
|
1712
|
+
this.runHeartbeatCommands(result.data.commands);
|
|
1713
|
+
}
|
|
1714
|
+
}
|
|
1715
|
+
buildHeartbeatPayload() {
|
|
1716
|
+
const userAgent = typeof navigator !== "undefined" ? navigator.userAgent : "";
|
|
1717
|
+
const platform = typeof navigator !== "undefined" ? navigator.platform : null;
|
|
1718
|
+
const connection = typeof navigator !== "undefined" ? navigator.connection : null;
|
|
1719
|
+
const chromiumMatch = userAgent.match(/(?:Chrome|Chromium)\/(\d+)/i);
|
|
1720
|
+
const chromiumMajor = chromiumMatch ? Number(chromiumMatch[1]) : void 0;
|
|
1721
|
+
const imaSupported = typeof window !== "undefined" ? Boolean(window?.google?.ima) : null;
|
|
1722
|
+
const telemetry = {
|
|
1723
|
+
powerState: typeof document !== "undefined" && document.hidden ? "standby" : "on",
|
|
1724
|
+
agentStatus: typeof document !== "undefined" && document.hidden ? "background" : "foreground",
|
|
1725
|
+
os: platform || void 0,
|
|
1726
|
+
agentVersion: SDK_VERSION,
|
|
1727
|
+
ima_integration: "html5_webview",
|
|
1728
|
+
ima_supported: imaSupported,
|
|
1729
|
+
webview_chromium_major: Number.isFinite(chromiumMajor) ? chromiumMajor : void 0
|
|
1730
|
+
};
|
|
1731
|
+
const payload = {
|
|
1732
|
+
telemetry,
|
|
1733
|
+
sdk: {
|
|
1734
|
+
version: SDK_VERSION,
|
|
1735
|
+
ima_supported: imaSupported,
|
|
1736
|
+
ima_integration: "html5_webview",
|
|
1737
|
+
webview_chromium_major: Number.isFinite(chromiumMajor) ? chromiumMajor : void 0
|
|
1738
|
+
},
|
|
1739
|
+
device: {
|
|
1740
|
+
os: platform || void 0,
|
|
1741
|
+
model: userAgent || void 0
|
|
1742
|
+
}
|
|
1743
|
+
};
|
|
1744
|
+
if (connection) {
|
|
1745
|
+
payload.network = {
|
|
1746
|
+
connectionType: connection.type || void 0,
|
|
1747
|
+
effectiveType: connection.effectiveType || void 0,
|
|
1748
|
+
downlinkMbps: typeof connection.downlink === "number" ? connection.downlink : void 0,
|
|
1749
|
+
bandwidthMbps: typeof connection.downlink === "number" ? connection.downlink : void 0,
|
|
1750
|
+
rtt: typeof connection.rtt === "number" ? connection.rtt : void 0,
|
|
1751
|
+
latencyRtt: typeof connection.rtt === "number" ? connection.rtt : void 0,
|
|
1752
|
+
saveData: typeof connection.saveData === "boolean" ? connection.saveData : void 0
|
|
1753
|
+
};
|
|
1754
|
+
}
|
|
1755
|
+
return payload;
|
|
1756
|
+
}
|
|
1757
|
+
applyAdDeliveryProfile(profile) {
|
|
1758
|
+
if (!profile?.mode) return;
|
|
1759
|
+
const previousMode = this.state.adDeliveryProfile?.mode ?? null;
|
|
1760
|
+
this.state.adDeliveryProfile = profile;
|
|
1761
|
+
if (profile.mode === "vast_fallback" && this.state.programmaticPlaying) {
|
|
1762
|
+
this.programmaticPlayer.stop({ silent: true });
|
|
1763
|
+
this.state.programmaticPlaying = false;
|
|
1764
|
+
}
|
|
1765
|
+
if (previousMode !== profile.mode) {
|
|
1766
|
+
this.emitStateChanged();
|
|
1767
|
+
}
|
|
1768
|
+
}
|
|
1769
|
+
runHeartbeatCommands(commands) {
|
|
1770
|
+
for (const command of commands) {
|
|
1771
|
+
const name = String(command?.command || "").toLowerCase();
|
|
1772
|
+
if (name === "refresh_ads") {
|
|
1773
|
+
this.refresh().catch(() => {
|
|
1774
|
+
});
|
|
1775
|
+
} else if (name === "restart") {
|
|
1776
|
+
if (typeof window !== "undefined" && typeof window.location?.reload === "function") {
|
|
1777
|
+
window.location.reload();
|
|
1778
|
+
return;
|
|
1779
|
+
}
|
|
1780
|
+
this.refresh().catch(() => {
|
|
1781
|
+
});
|
|
1782
|
+
}
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1683
1785
|
playNextAd() {
|
|
1786
|
+
if (this.state.adDeliveryProfile?.mode === "vast_fallback" && this.state.ads.length > 0) {
|
|
1787
|
+
this.playDirect();
|
|
1788
|
+
return;
|
|
1789
|
+
}
|
|
1684
1790
|
const mode = this.state.waterfallMode;
|
|
1685
1791
|
if (mode === "programmatic_only" || mode === "programmatic_then_direct") {
|
|
1686
1792
|
this.playProgrammatic();
|
|
@@ -1695,13 +1801,20 @@ var _TrillboardsAds = class _TrillboardsAds {
|
|
|
1695
1801
|
this.programmaticPlayer.play(
|
|
1696
1802
|
() => {
|
|
1697
1803
|
this.state.programmaticPlaying = false;
|
|
1804
|
+
this.resetProgrammaticBackoff();
|
|
1698
1805
|
this.emitStateChanged();
|
|
1699
1806
|
this.scheduleProgrammaticRetry();
|
|
1700
1807
|
},
|
|
1701
1808
|
(error) => {
|
|
1702
1809
|
this.state.programmaticPlaying = false;
|
|
1703
1810
|
this.state.programmaticLastError = error;
|
|
1704
|
-
|
|
1811
|
+
const normalizedError = String(error || "").toLowerCase();
|
|
1812
|
+
const isNoFillLike = normalizedError.includes("no fill") || normalizedError.includes("no ads vast response") || normalizedError.includes("waterfall_exhausted") || normalizedError === "throttled" || normalizedError === "busy";
|
|
1813
|
+
if (isNoFillLike) {
|
|
1814
|
+
this.state.programmaticRetryCount = 0;
|
|
1815
|
+
} else {
|
|
1816
|
+
this.state.programmaticRetryCount++;
|
|
1817
|
+
}
|
|
1705
1818
|
this.emitStateChanged();
|
|
1706
1819
|
if (this.state.waterfallMode === "programmatic_then_direct" && this.state.ads.length > 0) {
|
|
1707
1820
|
this.playDirect();
|
|
@@ -1823,12 +1936,12 @@ var TrillboardsError = class extends Error {
|
|
|
1823
1936
|
var TrillboardsAuthenticationError = class extends TrillboardsError {
|
|
1824
1937
|
constructor(message) {
|
|
1825
1938
|
super(
|
|
1826
|
-
message ?? "Invalid API key. Check your key at https://trillboards.com/developers",
|
|
1939
|
+
message ?? "Invalid API key. Check your key at https://trillboards.com/support/developers",
|
|
1827
1940
|
{
|
|
1828
1941
|
type: "authentication_error",
|
|
1829
1942
|
code: "invalid_api_key",
|
|
1830
1943
|
statusCode: 401,
|
|
1831
|
-
help: "https://trillboards.com/developers"
|
|
1944
|
+
help: "https://trillboards.com/support/developers"
|
|
1832
1945
|
}
|
|
1833
1946
|
);
|
|
1834
1947
|
this.name = "TrillboardsAuthenticationError";
|