@falcongames/falcon-playable-ads-sdk 1.3.0 → 1.3.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/README.md +316 -316
- package/dist/FalconPlayableSDK.d.ts +3 -0
- package/dist/FalconPlayableSDK.d.ts.map +1 -1
- package/dist/FalconPlayableSDK.js +14 -0
- package/dist/FalconPlayableSDK.js.map +1 -1
- package/dist/adNetworkNotifier.d.ts +0 -0
- package/dist/adNetworkNotifier.d.ts.map +0 -0
- package/dist/adNetworkNotifier.js +0 -0
- package/dist/adNetworkNotifier.js.map +0 -0
- package/dist/adNetworkUtils.d.ts +0 -0
- package/dist/adNetworkUtils.d.ts.map +0 -0
- package/dist/adNetworkUtils.js +0 -0
- package/dist/adNetworkUtils.js.map +0 -0
- package/dist/config/SDKConfig.d.ts +0 -0
- package/dist/config/SDKConfig.d.ts.map +0 -0
- package/dist/config/SDKConfig.js +0 -0
- package/dist/config/SDKConfig.js.map +0 -0
- package/dist/dynamic/DynamicPlayable.d.ts +0 -0
- package/dist/dynamic/DynamicPlayable.d.ts.map +0 -0
- package/dist/dynamic/DynamicPlayable.js +0 -0
- package/dist/dynamic/DynamicPlayable.js.map +0 -0
- package/dist/http_transport/event_core/CSHttpCoreEventMessage.d.ts +0 -0
- package/dist/http_transport/event_core/CSHttpCoreEventMessage.d.ts.map +0 -0
- package/dist/http_transport/event_core/CSHttpCoreEventMessage.js +0 -0
- package/dist/http_transport/event_core/CSHttpCoreEventMessage.js.map +0 -0
- package/dist/http_transport/http_core/CSHttpMessage.d.ts +0 -0
- package/dist/http_transport/http_core/CSHttpMessage.d.ts.map +0 -0
- package/dist/http_transport/http_core/CSHttpMessage.js +0 -0
- package/dist/http_transport/http_core/CSHttpMessage.js.map +0 -0
- package/dist/http_transport/http_core/FHttpMessage.d.ts +0 -0
- package/dist/http_transport/http_core/FHttpMessage.d.ts.map +0 -0
- package/dist/http_transport/http_core/FHttpMessage.js +0 -0
- package/dist/http_transport/http_core/FHttpMessage.js.map +0 -0
- package/dist/http_transport/http_core/FHttpMessageScanner.d.ts +0 -0
- package/dist/http_transport/http_core/FHttpMessageScanner.d.ts.map +0 -0
- package/dist/http_transport/http_core/FHttpMessageScanner.js +0 -0
- package/dist/http_transport/http_core/FHttpMessageScanner.js.map +0 -0
- package/dist/http_transport/http_core/SCHttpMessage.d.ts +0 -0
- package/dist/http_transport/http_core/SCHttpMessage.d.ts.map +0 -0
- package/dist/http_transport/http_core/SCHttpMessage.js +0 -0
- package/dist/http_transport/http_core/SCHttpMessage.js.map +0 -0
- package/dist/http_transport/playable_events/FPlayableEventManager.d.ts +0 -0
- package/dist/http_transport/playable_events/FPlayableEventManager.d.ts.map +0 -0
- package/dist/http_transport/playable_events/FPlayableEventManager.js +0 -0
- package/dist/http_transport/playable_events/FPlayableEventManager.js.map +0 -0
- package/dist/http_transport/playable_events/GlobalInteractionTracker.d.ts +0 -0
- package/dist/http_transport/playable_events/GlobalInteractionTracker.d.ts.map +0 -0
- package/dist/http_transport/playable_events/GlobalInteractionTracker.js +0 -0
- package/dist/http_transport/playable_events/GlobalInteractionTracker.js.map +0 -0
- package/dist/http_transport/playable_events/PlayableEventDefinitionCollection.d.ts +0 -0
- package/dist/http_transport/playable_events/PlayableEventDefinitionCollection.d.ts.map +0 -0
- package/dist/http_transport/playable_events/PlayableEventDefinitionCollection.js +0 -0
- package/dist/http_transport/playable_events/PlayableEventDefinitionCollection.js.map +0 -0
- package/dist/http_transport/playable_events/defaultNodes.d.ts +0 -0
- package/dist/http_transport/playable_events/defaultNodes.d.ts.map +0 -0
- package/dist/http_transport/playable_events/defaultNodes.js +0 -0
- package/dist/http_transport/playable_events/defaultNodes.js.map +0 -0
- package/dist/http_transport/playable_events/types.d.ts +0 -0
- package/dist/http_transport/playable_events/types.d.ts.map +0 -0
- package/dist/http_transport/playable_events/types.js +0 -0
- package/dist/http_transport/playable_events/types.js.map +0 -0
- package/dist/http_transport/types/EventTypes.d.ts +0 -0
- package/dist/http_transport/types/EventTypes.d.ts.map +0 -0
- package/dist/http_transport/types/EventTypes.js +0 -0
- package/dist/http_transport/types/EventTypes.js.map +0 -0
- package/dist/http_transport/utils/detectNetwork.d.ts +0 -0
- package/dist/http_transport/utils/detectNetwork.d.ts.map +0 -0
- package/dist/http_transport/utils/detectNetwork.js +0 -0
- package/dist/http_transport/utils/detectNetwork.js.map +0 -0
- package/dist/http_transport/utils/detectPlatform.d.ts +0 -0
- package/dist/http_transport/utils/detectPlatform.d.ts.map +0 -0
- package/dist/http_transport/utils/detectPlatform.js +0 -0
- package/dist/http_transport/utils/detectPlatform.js.map +0 -0
- package/dist/http_transport/utils/generateId.d.ts +0 -0
- package/dist/http_transport/utils/generateId.d.ts.map +0 -0
- package/dist/http_transport/utils/generateId.js +0 -0
- package/dist/http_transport/utils/generateId.js.map +0 -0
- package/dist/http_transport/utils/generateReferralCode.d.ts +0 -0
- package/dist/http_transport/utils/generateReferralCode.d.ts.map +0 -0
- package/dist/http_transport/utils/generateReferralCode.js +0 -0
- package/dist/http_transport/utils/generateReferralCode.js.map +0 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/mraid.d.ts +7 -0
- package/dist/mraid.d.ts.map +1 -0
- package/dist/mraid.js +146 -0
- package/dist/mraid.js.map +1 -0
- package/dist/storeRouter.d.ts +0 -0
- package/dist/storeRouter.d.ts.map +1 -1
- package/dist/storeRouter.js +9 -8
- package/dist/storeRouter.js.map +1 -1
- package/dist/types/index.d.ts +0 -0
- package/dist/types/index.d.ts.map +0 -0
- package/dist/types/index.js +0 -0
- package/dist/types/index.js.map +0 -0
- package/dist/utils/Logger.d.ts +0 -0
- package/dist/utils/Logger.d.ts.map +0 -0
- package/dist/utils/Logger.js +0 -0
- package/dist/utils/Logger.js.map +0 -0
- package/dist/utils/dispatchWindowCustomEvent.d.ts +0 -0
- package/dist/utils/dispatchWindowCustomEvent.d.ts.map +0 -0
- package/dist/utils/dispatchWindowCustomEvent.js +0 -0
- package/dist/utils/dispatchWindowCustomEvent.js.map +0 -0
- package/package.json +40 -40
package/README.md
CHANGED
|
@@ -1,316 +1,316 @@
|
|
|
1
|
-
# Falcon Playable Ads SDK
|
|
2
|
-
|
|
3
|
-
A TypeScript SDK for tracking events in playable advertisements.
|
|
4
|
-
|
|
5
|
-
## Installation
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm install @falcongames/falcon-playable-ads-sdk
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## Quick Start
|
|
12
|
-
|
|
13
|
-
```typescript
|
|
14
|
-
import FalconPlayableSDK from "@falcongames/falcon-playable-ads-sdk";
|
|
15
|
-
|
|
16
|
-
// `initialize()` is async: await it so a dynamic playable's config is fetched before the game
|
|
17
|
-
// starts. For non-dynamic creatives it resolves immediately. (Calling without await still works.)
|
|
18
|
-
await FalconPlayableSDK.initialize();
|
|
19
|
-
|
|
20
|
-
// Lifecycle events
|
|
21
|
-
FalconPlayableSDK.onLoaded(); // Ad finished loading
|
|
22
|
-
FalconPlayableSDK.onFrame(); // First frame renderedinside ad
|
|
23
|
-
FalconPlayableSDK.onEndGame(); // Game/ad ended
|
|
24
|
-
FalconPlayableSDK.onCTA(); // User clicked CTA button
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
If your ESNext setup imports the SDK as a namespace, you can also call the
|
|
28
|
-
top-level exports directly:
|
|
29
|
-
|
|
30
|
-
```typescript
|
|
31
|
-
import * as FalconPlayableSDK from "@falcongames/falcon-playable-ads-sdk";
|
|
32
|
-
|
|
33
|
-
FalconPlayableSDK.initialize();
|
|
34
|
-
FalconPlayableSDK.onCTA();
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
## Default Event Flow
|
|
38
|
-
|
|
39
|
-
The SDK has a built-in event hierarchy:
|
|
40
|
-
|
|
41
|
-
```
|
|
42
|
-
LOADED → FRAME → INTERACTION → [custom events...]
|
|
43
|
-
↓
|
|
44
|
-
END_GAME → CTA
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
`END_GAME` and `CTA` are **terminal nodes** — they always fire after all custom events, regardless of how deep the hierarchy is.
|
|
48
|
-
|
|
49
|
-
## Custom Events
|
|
50
|
-
|
|
51
|
-
### 1. Register a custom event node
|
|
52
|
-
|
|
53
|
-
Use `registerPlayableEventNode` to define and register a custom event. It is automatically added to the collection — no extra step needed.
|
|
54
|
-
|
|
55
|
-
```typescript
|
|
56
|
-
import {
|
|
57
|
-
FalconPlayableSDK,
|
|
58
|
-
registerPlayableEventNode,
|
|
59
|
-
DefaultPlayableEventNodes,
|
|
60
|
-
} from "@falcongames/falcon-playable-ads-sdk";
|
|
61
|
-
|
|
62
|
-
// Default parent is INTERACTION
|
|
63
|
-
const LEVEL_START = registerPlayableEventNode("level_start");
|
|
64
|
-
|
|
65
|
-
// Or specify a custom parent
|
|
66
|
-
const LEVEL_COMPLETE = registerPlayableEventNode("level_complete", LEVEL_START);
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
### 2. Fire a custom event
|
|
70
|
-
|
|
71
|
-
```typescript
|
|
72
|
-
FalconPlayableSDK.logEvent(LEVEL_START);
|
|
73
|
-
FalconPlayableSDK.logEvent(LEVEL_COMPLETE);
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
### 3. Define events via SDK (registers + tracks definition)
|
|
77
|
-
|
|
78
|
-
```typescript
|
|
79
|
-
const levelStart = FalconPlayableSDK.defineEventNode({
|
|
80
|
-
key: "level_start",
|
|
81
|
-
parent: DefaultPlayableEventNodes.INTERACTION,
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
// Define multiple at once
|
|
85
|
-
FalconPlayableSDK.defineEventNodes([
|
|
86
|
-
{ key: "level_start" },
|
|
87
|
-
{ key: "level_complete", parent: levelStart },
|
|
88
|
-
]);
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
### 4. Inspect the event hierarchy
|
|
92
|
-
|
|
93
|
-
```typescript
|
|
94
|
-
const hierarchy = FalconPlayableSDK.getEventHierarchy();
|
|
95
|
-
|
|
96
|
-
// hierarchy.roots — the main event tree (LOADED → ... → custom events)
|
|
97
|
-
// hierarchy.terminalNode — END_GAME → CTA (detached)
|
|
98
|
-
|
|
99
|
-
console.log(JSON.stringify(hierarchy, null, 2));
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
Example output:
|
|
103
|
-
|
|
104
|
-
```json
|
|
105
|
-
{
|
|
106
|
-
"roots": [
|
|
107
|
-
{
|
|
108
|
-
"eventId": "loaded",
|
|
109
|
-
"parentEventId": null,
|
|
110
|
-
"isDefault": true,
|
|
111
|
-
"children": [
|
|
112
|
-
{
|
|
113
|
-
"eventId": "frame",
|
|
114
|
-
"parentEventId": "loaded",
|
|
115
|
-
"isDefault": true,
|
|
116
|
-
"children": [
|
|
117
|
-
{
|
|
118
|
-
"eventId": "interaction",
|
|
119
|
-
"parentEventId": "frame",
|
|
120
|
-
"isDefault": true,
|
|
121
|
-
"children": [
|
|
122
|
-
{
|
|
123
|
-
"eventId": "level_start",
|
|
124
|
-
"parentEventId": "interaction",
|
|
125
|
-
"isDefault": false,
|
|
126
|
-
"children": []
|
|
127
|
-
}
|
|
128
|
-
]
|
|
129
|
-
}
|
|
130
|
-
]
|
|
131
|
-
}
|
|
132
|
-
]
|
|
133
|
-
}
|
|
134
|
-
],
|
|
135
|
-
"terminalNode": {
|
|
136
|
-
"eventId": "end_game",
|
|
137
|
-
"parentEventId": null,
|
|
138
|
-
"isDefault": true,
|
|
139
|
-
"children": [
|
|
140
|
-
{
|
|
141
|
-
"eventId": "cta",
|
|
142
|
-
"parentEventId": "end_game",
|
|
143
|
-
"isDefault": true,
|
|
144
|
-
"children": []
|
|
145
|
-
}
|
|
146
|
-
]
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
### Circular parent detection
|
|
152
|
-
|
|
153
|
-
The SDK throws an error if a circular dependency is detected when registering a node:
|
|
154
|
-
|
|
155
|
-
```typescript
|
|
156
|
-
const A = registerPlayableEventNode("a");
|
|
157
|
-
const B = registerPlayableEventNode("b", A);
|
|
158
|
-
// Error: Circular event definition detected: "a" is an ancestor of itself.
|
|
159
|
-
registerPlayableEventNode("a", B);
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
## API Reference
|
|
163
|
-
|
|
164
|
-
### Lifecycle Methods
|
|
165
|
-
|
|
166
|
-
| Method | Description |
|
|
167
|
-
| -------------------- | --------------------------------------------------------------- |
|
|
168
|
-
| `initialize(config)` | Initialize SDK — must be called first |
|
|
169
|
-
| `onLoaded()` | Ad finished loading |
|
|
170
|
-
| `onFrame()` | First frame rendered |
|
|
171
|
-
| `onInternalClick()` | User clicked inside ad (fires `pa:internal_click` window event) |
|
|
172
|
-
| `onEndGame()` | Game/ad ended |
|
|
173
|
-
| `onCTA()` | User clicked CTA — routes to store automatically |
|
|
174
|
-
| `isReady()` | Returns `true` if SDK is initialized |
|
|
175
|
-
| `configure(config)` | Update configuration after initialization |
|
|
176
|
-
| `reset()` | Reset SDK state (for testing) |
|
|
177
|
-
|
|
178
|
-
### Custom Event Methods
|
|
179
|
-
|
|
180
|
-
| Method | Description |
|
|
181
|
-
| -------------------------- | ----------------------------------------------- |
|
|
182
|
-
| `logEvent(event)` | Fire a custom event |
|
|
183
|
-
| `defineEventNode(input)` | Register a custom node definition |
|
|
184
|
-
| `defineEventNodes(inputs)` | Register multiple node definitions |
|
|
185
|
-
| `getEventDefinitions()` | Get all registered event definitions |
|
|
186
|
-
| `getEventHierarchy()` | Get full event tree as `PlayableEventHierarchy` |
|
|
187
|
-
|
|
188
|
-
### Utility Methods
|
|
189
|
-
|
|
190
|
-
| Method | Description |
|
|
191
|
-
| ----------------------------------- | ------------------------------------- |
|
|
192
|
-
| `dispatchGainScoreEvent(score)` | Dispatch `pa:gain_score` window event |
|
|
193
|
-
| `dispatchLoseScoreEvent(score)` | Dispatch `pa:lose_score` window event |
|
|
194
|
-
| `dispatchWinEvent()` | Dispatch `pa:win_game` window event |
|
|
195
|
-
| `dispatchLoseEvent()` | Dispatch `pa:lose_game` window event |
|
|
196
|
-
| `dispatchCustomEvent(type, detail)` | Dispatch any custom window event |
|
|
197
|
-
| `getVersion()` | Get SDK version string |
|
|
198
|
-
| `getAdNetworkInfo()` | Get `PlayableAdsType` enum value |
|
|
199
|
-
| `isPlaySound` | `false` for Adwords, Facebook, IronSource; otherwise `true` |
|
|
200
|
-
|
|
201
|
-
### `registerPlayableEventNode(key, parent?)`
|
|
202
|
-
|
|
203
|
-
```typescript
|
|
204
|
-
import {
|
|
205
|
-
registerPlayableEventNode,
|
|
206
|
-
DefaultPlayableEventNodes,
|
|
207
|
-
} from "@falcongames/falcon-playable-ads-sdk";
|
|
208
|
-
|
|
209
|
-
// parent defaults to DefaultPlayableEventNodes.INTERACTION
|
|
210
|
-
const MY_EVENT = registerPlayableEventNode("my_event");
|
|
211
|
-
|
|
212
|
-
// Custom parent
|
|
213
|
-
const MY_CHILD = registerPlayableEventNode("my_child", MY_EVENT);
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
### `DefaultPlayableEventNodes`
|
|
217
|
-
|
|
218
|
-
```typescript
|
|
219
|
-
import { DefaultPlayableEventNodes } from "@falcongames/falcon-playable-ads-sdk";
|
|
220
|
-
|
|
221
|
-
DefaultPlayableEventNodes.LOADED;
|
|
222
|
-
DefaultPlayableEventNodes.FRAME;
|
|
223
|
-
DefaultPlayableEventNodes.INTERACTION;
|
|
224
|
-
DefaultPlayableEventNodes.END_GAME;
|
|
225
|
-
DefaultPlayableEventNodes.CTA;
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
## Extending with Custom HTTP Messages
|
|
229
|
-
|
|
230
|
-
```typescript
|
|
231
|
-
import { CSHttpMessage } from "@falcongames/falcon-playable-ads-sdk";
|
|
232
|
-
|
|
233
|
-
class MyCustomMessage extends CSHttpMessage {
|
|
234
|
-
static event = "my_custom_event";
|
|
235
|
-
playerId: string = "";
|
|
236
|
-
score: number = 0;
|
|
237
|
-
|
|
238
|
-
constructor(playerId: string, score: number) {
|
|
239
|
-
super();
|
|
240
|
-
this.playerId = playerId;
|
|
241
|
-
this.score = score;
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
new MyCustomMessage("player-123", 1000).send();
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
See `src/examples/` for more examples.
|
|
249
|
-
|
|
250
|
-
## Dynamic Playables
|
|
251
|
-
|
|
252
|
-
A **dynamic playable** is a single creative that holds several config variants; at run time the
|
|
253
|
-
backend serves one variant by round-robin. Old (non-dynamic) creatives are unaffected — the feature
|
|
254
|
-
only activates when the build marks the creative as dynamic.
|
|
255
|
-
|
|
256
|
-
### Build signal
|
|
257
|
-
|
|
258
|
-
The build must mark the creative by replacing the `{{IS_DYNAMIC}}` placeholder with `true` (it stays
|
|
259
|
-
`false`/unreplaced for normal creatives). `creativeId` and `baseURL` must also be set (they already
|
|
260
|
-
are for event tracking), so the SDK can derive the serve URL:
|
|
261
|
-
|
|
262
|
-
```
|
|
263
|
-
{baseURL}/playable/creatives/{creativeId}/serve
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
Optionally inject a full URL via `{{DYNAMIC_CONFIG_URL}}` to override that derivation.
|
|
267
|
-
|
|
268
|
-
```typescript
|
|
269
|
-
FalconPlayableSDK.initialize({
|
|
270
|
-
baseURL: "{{BASE_URL}}",
|
|
271
|
-
creativeId: "{{CREATIVE_ID}}",
|
|
272
|
-
isDynamic: true, // build replaces {{IS_DYNAMIC}} → true for dynamic creatives
|
|
273
|
-
});
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
### Fetching the variant
|
|
277
|
-
|
|
278
|
-
When dynamic, `initialize()` automatically fetches the config (fire-and-forget) and dispatches a
|
|
279
|
-
`falcon:dynamic-config` window event. For strict ordering, await it before starting the game:
|
|
280
|
-
|
|
281
|
-
```typescript
|
|
282
|
-
import FalconPlayableSDK, { DynamicVariant } from "@falcongames/falcon-playable-ads-sdk";
|
|
283
|
-
|
|
284
|
-
FalconPlayableSDK.initialize();
|
|
285
|
-
|
|
286
|
-
const variant: DynamicVariant | null =
|
|
287
|
-
await FalconPlayableSDK.fetchDynamicConfig(); // null for non-dynamic creatives
|
|
288
|
-
|
|
289
|
-
if (variant) {
|
|
290
|
-
// variant.values = { fieldKey: { type, value } } — the overridden fields only.
|
|
291
|
-
applyOverridesOntoBase(variant.values); // your playable applies the delta onto its base config
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
// Or react to the event instead of awaiting:
|
|
295
|
-
window.addEventListener("falcon:dynamic-config", (e) => {
|
|
296
|
-
applyOverridesOntoBase((e as CustomEvent<DynamicVariant>).detail.values);
|
|
297
|
-
});
|
|
298
|
-
```
|
|
299
|
-
|
|
300
|
-
`fetchDynamicConfig()` returns `null` (and does nothing) for non-dynamic creatives, so it is safe to
|
|
301
|
-
call unconditionally. The fetched variant is also exposed on `window.__FALCON_DYNAMIC_CONFIG__`.
|
|
302
|
-
|
|
303
|
-
> The SDK only **fetches** the variant; applying `values` onto the base config is the playable's
|
|
304
|
-
> responsibility (it knows its own config shape).
|
|
305
|
-
|
|
306
|
-
## Development
|
|
307
|
-
|
|
308
|
-
```bash
|
|
309
|
-
npm install # Install dependencies
|
|
310
|
-
npm run build # Compile TypeScript
|
|
311
|
-
npm run watch # Watch mode
|
|
312
|
-
```
|
|
313
|
-
|
|
314
|
-
## License
|
|
315
|
-
|
|
316
|
-
ISC
|
|
1
|
+
# Falcon Playable Ads SDK
|
|
2
|
+
|
|
3
|
+
A TypeScript SDK for tracking events in playable advertisements.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @falcongames/falcon-playable-ads-sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import FalconPlayableSDK from "@falcongames/falcon-playable-ads-sdk";
|
|
15
|
+
|
|
16
|
+
// `initialize()` is async: await it so a dynamic playable's config is fetched before the game
|
|
17
|
+
// starts. For non-dynamic creatives it resolves immediately. (Calling without await still works.)
|
|
18
|
+
await FalconPlayableSDK.initialize();
|
|
19
|
+
|
|
20
|
+
// Lifecycle events
|
|
21
|
+
FalconPlayableSDK.onLoaded(); // Ad finished loading
|
|
22
|
+
FalconPlayableSDK.onFrame(); // First frame renderedinside ad
|
|
23
|
+
FalconPlayableSDK.onEndGame(); // Game/ad ended
|
|
24
|
+
FalconPlayableSDK.onCTA(); // User clicked CTA button
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
If your ESNext setup imports the SDK as a namespace, you can also call the
|
|
28
|
+
top-level exports directly:
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
import * as FalconPlayableSDK from "@falcongames/falcon-playable-ads-sdk";
|
|
32
|
+
|
|
33
|
+
FalconPlayableSDK.initialize();
|
|
34
|
+
FalconPlayableSDK.onCTA();
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Default Event Flow
|
|
38
|
+
|
|
39
|
+
The SDK has a built-in event hierarchy:
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
LOADED → FRAME → INTERACTION → [custom events...]
|
|
43
|
+
↓
|
|
44
|
+
END_GAME → CTA
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`END_GAME` and `CTA` are **terminal nodes** — they always fire after all custom events, regardless of how deep the hierarchy is.
|
|
48
|
+
|
|
49
|
+
## Custom Events
|
|
50
|
+
|
|
51
|
+
### 1. Register a custom event node
|
|
52
|
+
|
|
53
|
+
Use `registerPlayableEventNode` to define and register a custom event. It is automatically added to the collection — no extra step needed.
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
import {
|
|
57
|
+
FalconPlayableSDK,
|
|
58
|
+
registerPlayableEventNode,
|
|
59
|
+
DefaultPlayableEventNodes,
|
|
60
|
+
} from "@falcongames/falcon-playable-ads-sdk";
|
|
61
|
+
|
|
62
|
+
// Default parent is INTERACTION
|
|
63
|
+
const LEVEL_START = registerPlayableEventNode("level_start");
|
|
64
|
+
|
|
65
|
+
// Or specify a custom parent
|
|
66
|
+
const LEVEL_COMPLETE = registerPlayableEventNode("level_complete", LEVEL_START);
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### 2. Fire a custom event
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
FalconPlayableSDK.logEvent(LEVEL_START);
|
|
73
|
+
FalconPlayableSDK.logEvent(LEVEL_COMPLETE);
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 3. Define events via SDK (registers + tracks definition)
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
const levelStart = FalconPlayableSDK.defineEventNode({
|
|
80
|
+
key: "level_start",
|
|
81
|
+
parent: DefaultPlayableEventNodes.INTERACTION,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// Define multiple at once
|
|
85
|
+
FalconPlayableSDK.defineEventNodes([
|
|
86
|
+
{ key: "level_start" },
|
|
87
|
+
{ key: "level_complete", parent: levelStart },
|
|
88
|
+
]);
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### 4. Inspect the event hierarchy
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
const hierarchy = FalconPlayableSDK.getEventHierarchy();
|
|
95
|
+
|
|
96
|
+
// hierarchy.roots — the main event tree (LOADED → ... → custom events)
|
|
97
|
+
// hierarchy.terminalNode — END_GAME → CTA (detached)
|
|
98
|
+
|
|
99
|
+
console.log(JSON.stringify(hierarchy, null, 2));
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Example output:
|
|
103
|
+
|
|
104
|
+
```json
|
|
105
|
+
{
|
|
106
|
+
"roots": [
|
|
107
|
+
{
|
|
108
|
+
"eventId": "loaded",
|
|
109
|
+
"parentEventId": null,
|
|
110
|
+
"isDefault": true,
|
|
111
|
+
"children": [
|
|
112
|
+
{
|
|
113
|
+
"eventId": "frame",
|
|
114
|
+
"parentEventId": "loaded",
|
|
115
|
+
"isDefault": true,
|
|
116
|
+
"children": [
|
|
117
|
+
{
|
|
118
|
+
"eventId": "interaction",
|
|
119
|
+
"parentEventId": "frame",
|
|
120
|
+
"isDefault": true,
|
|
121
|
+
"children": [
|
|
122
|
+
{
|
|
123
|
+
"eventId": "level_start",
|
|
124
|
+
"parentEventId": "interaction",
|
|
125
|
+
"isDefault": false,
|
|
126
|
+
"children": []
|
|
127
|
+
}
|
|
128
|
+
]
|
|
129
|
+
}
|
|
130
|
+
]
|
|
131
|
+
}
|
|
132
|
+
]
|
|
133
|
+
}
|
|
134
|
+
],
|
|
135
|
+
"terminalNode": {
|
|
136
|
+
"eventId": "end_game",
|
|
137
|
+
"parentEventId": null,
|
|
138
|
+
"isDefault": true,
|
|
139
|
+
"children": [
|
|
140
|
+
{
|
|
141
|
+
"eventId": "cta",
|
|
142
|
+
"parentEventId": "end_game",
|
|
143
|
+
"isDefault": true,
|
|
144
|
+
"children": []
|
|
145
|
+
}
|
|
146
|
+
]
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Circular parent detection
|
|
152
|
+
|
|
153
|
+
The SDK throws an error if a circular dependency is detected when registering a node:
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
const A = registerPlayableEventNode("a");
|
|
157
|
+
const B = registerPlayableEventNode("b", A);
|
|
158
|
+
// Error: Circular event definition detected: "a" is an ancestor of itself.
|
|
159
|
+
registerPlayableEventNode("a", B);
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## API Reference
|
|
163
|
+
|
|
164
|
+
### Lifecycle Methods
|
|
165
|
+
|
|
166
|
+
| Method | Description |
|
|
167
|
+
| -------------------- | --------------------------------------------------------------- |
|
|
168
|
+
| `initialize(config)` | Initialize SDK — must be called first |
|
|
169
|
+
| `onLoaded()` | Ad finished loading |
|
|
170
|
+
| `onFrame()` | First frame rendered |
|
|
171
|
+
| `onInternalClick()` | User clicked inside ad (fires `pa:internal_click` window event) |
|
|
172
|
+
| `onEndGame()` | Game/ad ended |
|
|
173
|
+
| `onCTA()` | User clicked CTA — routes to store automatically |
|
|
174
|
+
| `isReady()` | Returns `true` if SDK is initialized |
|
|
175
|
+
| `configure(config)` | Update configuration after initialization |
|
|
176
|
+
| `reset()` | Reset SDK state (for testing) |
|
|
177
|
+
|
|
178
|
+
### Custom Event Methods
|
|
179
|
+
|
|
180
|
+
| Method | Description |
|
|
181
|
+
| -------------------------- | ----------------------------------------------- |
|
|
182
|
+
| `logEvent(event)` | Fire a custom event |
|
|
183
|
+
| `defineEventNode(input)` | Register a custom node definition |
|
|
184
|
+
| `defineEventNodes(inputs)` | Register multiple node definitions |
|
|
185
|
+
| `getEventDefinitions()` | Get all registered event definitions |
|
|
186
|
+
| `getEventHierarchy()` | Get full event tree as `PlayableEventHierarchy` |
|
|
187
|
+
|
|
188
|
+
### Utility Methods
|
|
189
|
+
|
|
190
|
+
| Method | Description |
|
|
191
|
+
| ----------------------------------- | ------------------------------------- |
|
|
192
|
+
| `dispatchGainScoreEvent(score)` | Dispatch `pa:gain_score` window event |
|
|
193
|
+
| `dispatchLoseScoreEvent(score)` | Dispatch `pa:lose_score` window event |
|
|
194
|
+
| `dispatchWinEvent()` | Dispatch `pa:win_game` window event |
|
|
195
|
+
| `dispatchLoseEvent()` | Dispatch `pa:lose_game` window event |
|
|
196
|
+
| `dispatchCustomEvent(type, detail)` | Dispatch any custom window event |
|
|
197
|
+
| `getVersion()` | Get SDK version string |
|
|
198
|
+
| `getAdNetworkInfo()` | Get `PlayableAdsType` enum value |
|
|
199
|
+
| `isPlaySound` | `false` for Adwords, Facebook, IronSource; otherwise `true` |
|
|
200
|
+
|
|
201
|
+
### `registerPlayableEventNode(key, parent?)`
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
import {
|
|
205
|
+
registerPlayableEventNode,
|
|
206
|
+
DefaultPlayableEventNodes,
|
|
207
|
+
} from "@falcongames/falcon-playable-ads-sdk";
|
|
208
|
+
|
|
209
|
+
// parent defaults to DefaultPlayableEventNodes.INTERACTION
|
|
210
|
+
const MY_EVENT = registerPlayableEventNode("my_event");
|
|
211
|
+
|
|
212
|
+
// Custom parent
|
|
213
|
+
const MY_CHILD = registerPlayableEventNode("my_child", MY_EVENT);
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### `DefaultPlayableEventNodes`
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
import { DefaultPlayableEventNodes } from "@falcongames/falcon-playable-ads-sdk";
|
|
220
|
+
|
|
221
|
+
DefaultPlayableEventNodes.LOADED;
|
|
222
|
+
DefaultPlayableEventNodes.FRAME;
|
|
223
|
+
DefaultPlayableEventNodes.INTERACTION;
|
|
224
|
+
DefaultPlayableEventNodes.END_GAME;
|
|
225
|
+
DefaultPlayableEventNodes.CTA;
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
## Extending with Custom HTTP Messages
|
|
229
|
+
|
|
230
|
+
```typescript
|
|
231
|
+
import { CSHttpMessage } from "@falcongames/falcon-playable-ads-sdk";
|
|
232
|
+
|
|
233
|
+
class MyCustomMessage extends CSHttpMessage {
|
|
234
|
+
static event = "my_custom_event";
|
|
235
|
+
playerId: string = "";
|
|
236
|
+
score: number = 0;
|
|
237
|
+
|
|
238
|
+
constructor(playerId: string, score: number) {
|
|
239
|
+
super();
|
|
240
|
+
this.playerId = playerId;
|
|
241
|
+
this.score = score;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
new MyCustomMessage("player-123", 1000).send();
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
See `src/examples/` for more examples.
|
|
249
|
+
|
|
250
|
+
## Dynamic Playables
|
|
251
|
+
|
|
252
|
+
A **dynamic playable** is a single creative that holds several config variants; at run time the
|
|
253
|
+
backend serves one variant by round-robin. Old (non-dynamic) creatives are unaffected — the feature
|
|
254
|
+
only activates when the build marks the creative as dynamic.
|
|
255
|
+
|
|
256
|
+
### Build signal
|
|
257
|
+
|
|
258
|
+
The build must mark the creative by replacing the `{{IS_DYNAMIC}}` placeholder with `true` (it stays
|
|
259
|
+
`false`/unreplaced for normal creatives). `creativeId` and `baseURL` must also be set (they already
|
|
260
|
+
are for event tracking), so the SDK can derive the serve URL:
|
|
261
|
+
|
|
262
|
+
```
|
|
263
|
+
{baseURL}/playable/creatives/{creativeId}/serve
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
Optionally inject a full URL via `{{DYNAMIC_CONFIG_URL}}` to override that derivation.
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
FalconPlayableSDK.initialize({
|
|
270
|
+
baseURL: "{{BASE_URL}}",
|
|
271
|
+
creativeId: "{{CREATIVE_ID}}",
|
|
272
|
+
isDynamic: true, // build replaces {{IS_DYNAMIC}} → true for dynamic creatives
|
|
273
|
+
});
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### Fetching the variant
|
|
277
|
+
|
|
278
|
+
When dynamic, `initialize()` automatically fetches the config (fire-and-forget) and dispatches a
|
|
279
|
+
`falcon:dynamic-config` window event. For strict ordering, await it before starting the game:
|
|
280
|
+
|
|
281
|
+
```typescript
|
|
282
|
+
import FalconPlayableSDK, { DynamicVariant } from "@falcongames/falcon-playable-ads-sdk";
|
|
283
|
+
|
|
284
|
+
FalconPlayableSDK.initialize();
|
|
285
|
+
|
|
286
|
+
const variant: DynamicVariant | null =
|
|
287
|
+
await FalconPlayableSDK.fetchDynamicConfig(); // null for non-dynamic creatives
|
|
288
|
+
|
|
289
|
+
if (variant) {
|
|
290
|
+
// variant.values = { fieldKey: { type, value } } — the overridden fields only.
|
|
291
|
+
applyOverridesOntoBase(variant.values); // your playable applies the delta onto its base config
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Or react to the event instead of awaiting:
|
|
295
|
+
window.addEventListener("falcon:dynamic-config", (e) => {
|
|
296
|
+
applyOverridesOntoBase((e as CustomEvent<DynamicVariant>).detail.values);
|
|
297
|
+
});
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
`fetchDynamicConfig()` returns `null` (and does nothing) for non-dynamic creatives, so it is safe to
|
|
301
|
+
call unconditionally. The fetched variant is also exposed on `window.__FALCON_DYNAMIC_CONFIG__`.
|
|
302
|
+
|
|
303
|
+
> The SDK only **fetches** the variant; applying `values` onto the base config is the playable's
|
|
304
|
+
> responsibility (it knows its own config shape).
|
|
305
|
+
|
|
306
|
+
## Development
|
|
307
|
+
|
|
308
|
+
```bash
|
|
309
|
+
npm install # Install dependencies
|
|
310
|
+
npm run build # Compile TypeScript
|
|
311
|
+
npm run watch # Watch mode
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
## License
|
|
315
|
+
|
|
316
|
+
ISC
|
|
@@ -12,6 +12,8 @@ export declare class FalconPlayableSDK {
|
|
|
12
12
|
private constructor();
|
|
13
13
|
static getInstance(): FalconPlayableSDK;
|
|
14
14
|
initialize(config?: SDKConfig): Promise<void>;
|
|
15
|
+
isMraidReady(): boolean;
|
|
16
|
+
waitForMraidReady(): Promise<boolean>;
|
|
15
17
|
isDynamicPlayable(): boolean;
|
|
16
18
|
fetchDynamicConfig(): Promise<DynamicVariant | null>;
|
|
17
19
|
isReady(): boolean;
|
|
@@ -39,6 +41,7 @@ export declare class FalconPlayableSDK {
|
|
|
39
41
|
get isPlaySound(): boolean;
|
|
40
42
|
reset(): void;
|
|
41
43
|
private trackPlayable;
|
|
44
|
+
private initMraid;
|
|
42
45
|
private ensureInitialized;
|
|
43
46
|
private routeToStore;
|
|
44
47
|
private notifyGameReadyToNetwork;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FalconPlayableSDK.d.ts","sourceRoot":"","sources":["../src/FalconPlayableSDK.ts"],"names":[],"mappings":"AACA,OAAO,EACL,SAAS,EACT,gBAAgB,EAEhB,eAAe,EAEhB,MAAM,oBAAoB,CAAC;AAC5B,OAA8B,EAC5B,iCAAiC,EACjC,sBAAsB,EACtB,uBAAuB,EACvB,4BAA4B,EAC5B,0BAA0B,EAC1B,sBAAsB,EACvB,MAAM,wDAAwD,CAAC;AAYhE,OAAO,EAGL,cAAc,EACf,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"FalconPlayableSDK.d.ts","sourceRoot":"","sources":["../src/FalconPlayableSDK.ts"],"names":[],"mappings":"AACA,OAAO,EACL,SAAS,EACT,gBAAgB,EAEhB,eAAe,EAEhB,MAAM,oBAAoB,CAAC;AAC5B,OAA8B,EAC5B,iCAAiC,EACjC,sBAAsB,EACtB,uBAAuB,EACvB,4BAA4B,EAC5B,0BAA0B,EAC1B,sBAAsB,EACvB,MAAM,wDAAwD,CAAC;AAYhE,OAAO,EAGL,cAAc,EACf,MAAM,2BAA2B,CAAC;AAYnC,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAkC;IACzD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,uBAAuB,CAI5C;IAEH,OAAO,CAAC,aAAa,CAAkB;IACvC,OAAO,CAAC,MAAM,CAAmB;IAEjC,OAAO,CAAC,YAAY,CAAuB;IAEpC,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAInC,eAAe,IAAI,MAAM,GAAG,IAAI;IAQvC,OAAO;WAOO,WAAW,IAAI,iBAAiB;IAejC,UAAU,CACrB,MAAM,GAAE,SAYP,GACA,OAAO,CAAC,IAAI,CAAC;IA2DT,YAAY,IAAI,OAAO;IAQvB,iBAAiB,IAAI,OAAO,CAAC,OAAO,CAAC;IAOrC,iBAAiB,IAAI,OAAO;IAStB,kBAAkB,IAAI,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAY1D,OAAO,IAAI,OAAO;IAQlB,SAAS,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI;IAgBlC,MAAM,IAAI,IAAI;IAQd,QAAQ,IAAI,IAAI;IA0BhB,OAAO,IAAI,IAAI;IASf,eAAe,IAAI,IAAI;IAQvB,KAAK,IAAI,IAAI;IAUb,SAAS,IAAI,IAAI;IAOjB,QAAQ,CACb,KAAK,EAAE,sBAAsB,GAC5B,0BAA0B,GAAG,IAAI;IAK7B,eAAe,CAAC,CAAC,SAAS,MAAM,EACrC,KAAK,EAAE,4BAA4B,CAAC,CAAC,CAAC,GACrC,uBAAuB;IAKnB,gBAAgB,CACrB,WAAW,CAAC,EACR,QAAQ,CAAC,4BAA4B,CAAC,GACtC,iCAAiC,GACpC,uBAAuB,EAAE;IAKrB,mBAAmB,IAAI,uBAAuB,EAAE;IAKhD,iBAAiB,IAAI,sBAAsB;IAK3C,sBAAsB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IAI5C,sBAAsB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IAI5C,gBAAgB,IAAI,IAAI;IAIxB,iBAAiB,IAAI,IAAI;IAIzB,mBAAmB,CAAC,CAAC,EAC1B,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,CAAC,EACV,OAAO,CAAC,EAAE,eAAe,CAAC,CAAC,CAAC,GAC3B,OAAO;IAOH,UAAU,IAAI,MAAM;IAIpB,SAAS,IAAI,gBAAgB;IAI7B,gBAAgB,IAAI,eAAe;IAMnC,kBAAkB,IAAI,eAAe;IAI5C,IAAW,WAAW,IAAI,OAAO,CAIhC;IAKM,KAAK,IAAI,IAAI;IAQpB,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,SAAS;IAOjB,OAAO,CAAC,iBAAiB;IAQzB,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,wBAAwB;IAIhC,OAAO,CAAC,sBAAsB;CAG/B;AAED,eAAe,iBAAiB,CAAC"}
|