@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.
Files changed (106) hide show
  1. package/README.md +316 -316
  2. package/dist/FalconPlayableSDK.d.ts +3 -0
  3. package/dist/FalconPlayableSDK.d.ts.map +1 -1
  4. package/dist/FalconPlayableSDK.js +14 -0
  5. package/dist/FalconPlayableSDK.js.map +1 -1
  6. package/dist/adNetworkNotifier.d.ts +0 -0
  7. package/dist/adNetworkNotifier.d.ts.map +0 -0
  8. package/dist/adNetworkNotifier.js +0 -0
  9. package/dist/adNetworkNotifier.js.map +0 -0
  10. package/dist/adNetworkUtils.d.ts +0 -0
  11. package/dist/adNetworkUtils.d.ts.map +0 -0
  12. package/dist/adNetworkUtils.js +0 -0
  13. package/dist/adNetworkUtils.js.map +0 -0
  14. package/dist/config/SDKConfig.d.ts +0 -0
  15. package/dist/config/SDKConfig.d.ts.map +0 -0
  16. package/dist/config/SDKConfig.js +0 -0
  17. package/dist/config/SDKConfig.js.map +0 -0
  18. package/dist/dynamic/DynamicPlayable.d.ts +0 -0
  19. package/dist/dynamic/DynamicPlayable.d.ts.map +0 -0
  20. package/dist/dynamic/DynamicPlayable.js +0 -0
  21. package/dist/dynamic/DynamicPlayable.js.map +0 -0
  22. package/dist/http_transport/event_core/CSHttpCoreEventMessage.d.ts +0 -0
  23. package/dist/http_transport/event_core/CSHttpCoreEventMessage.d.ts.map +0 -0
  24. package/dist/http_transport/event_core/CSHttpCoreEventMessage.js +0 -0
  25. package/dist/http_transport/event_core/CSHttpCoreEventMessage.js.map +0 -0
  26. package/dist/http_transport/http_core/CSHttpMessage.d.ts +0 -0
  27. package/dist/http_transport/http_core/CSHttpMessage.d.ts.map +0 -0
  28. package/dist/http_transport/http_core/CSHttpMessage.js +0 -0
  29. package/dist/http_transport/http_core/CSHttpMessage.js.map +0 -0
  30. package/dist/http_transport/http_core/FHttpMessage.d.ts +0 -0
  31. package/dist/http_transport/http_core/FHttpMessage.d.ts.map +0 -0
  32. package/dist/http_transport/http_core/FHttpMessage.js +0 -0
  33. package/dist/http_transport/http_core/FHttpMessage.js.map +0 -0
  34. package/dist/http_transport/http_core/FHttpMessageScanner.d.ts +0 -0
  35. package/dist/http_transport/http_core/FHttpMessageScanner.d.ts.map +0 -0
  36. package/dist/http_transport/http_core/FHttpMessageScanner.js +0 -0
  37. package/dist/http_transport/http_core/FHttpMessageScanner.js.map +0 -0
  38. package/dist/http_transport/http_core/SCHttpMessage.d.ts +0 -0
  39. package/dist/http_transport/http_core/SCHttpMessage.d.ts.map +0 -0
  40. package/dist/http_transport/http_core/SCHttpMessage.js +0 -0
  41. package/dist/http_transport/http_core/SCHttpMessage.js.map +0 -0
  42. package/dist/http_transport/playable_events/FPlayableEventManager.d.ts +0 -0
  43. package/dist/http_transport/playable_events/FPlayableEventManager.d.ts.map +0 -0
  44. package/dist/http_transport/playable_events/FPlayableEventManager.js +0 -0
  45. package/dist/http_transport/playable_events/FPlayableEventManager.js.map +0 -0
  46. package/dist/http_transport/playable_events/GlobalInteractionTracker.d.ts +0 -0
  47. package/dist/http_transport/playable_events/GlobalInteractionTracker.d.ts.map +0 -0
  48. package/dist/http_transport/playable_events/GlobalInteractionTracker.js +0 -0
  49. package/dist/http_transport/playable_events/GlobalInteractionTracker.js.map +0 -0
  50. package/dist/http_transport/playable_events/PlayableEventDefinitionCollection.d.ts +0 -0
  51. package/dist/http_transport/playable_events/PlayableEventDefinitionCollection.d.ts.map +0 -0
  52. package/dist/http_transport/playable_events/PlayableEventDefinitionCollection.js +0 -0
  53. package/dist/http_transport/playable_events/PlayableEventDefinitionCollection.js.map +0 -0
  54. package/dist/http_transport/playable_events/defaultNodes.d.ts +0 -0
  55. package/dist/http_transport/playable_events/defaultNodes.d.ts.map +0 -0
  56. package/dist/http_transport/playable_events/defaultNodes.js +0 -0
  57. package/dist/http_transport/playable_events/defaultNodes.js.map +0 -0
  58. package/dist/http_transport/playable_events/types.d.ts +0 -0
  59. package/dist/http_transport/playable_events/types.d.ts.map +0 -0
  60. package/dist/http_transport/playable_events/types.js +0 -0
  61. package/dist/http_transport/playable_events/types.js.map +0 -0
  62. package/dist/http_transport/types/EventTypes.d.ts +0 -0
  63. package/dist/http_transport/types/EventTypes.d.ts.map +0 -0
  64. package/dist/http_transport/types/EventTypes.js +0 -0
  65. package/dist/http_transport/types/EventTypes.js.map +0 -0
  66. package/dist/http_transport/utils/detectNetwork.d.ts +0 -0
  67. package/dist/http_transport/utils/detectNetwork.d.ts.map +0 -0
  68. package/dist/http_transport/utils/detectNetwork.js +0 -0
  69. package/dist/http_transport/utils/detectNetwork.js.map +0 -0
  70. package/dist/http_transport/utils/detectPlatform.d.ts +0 -0
  71. package/dist/http_transport/utils/detectPlatform.d.ts.map +0 -0
  72. package/dist/http_transport/utils/detectPlatform.js +0 -0
  73. package/dist/http_transport/utils/detectPlatform.js.map +0 -0
  74. package/dist/http_transport/utils/generateId.d.ts +0 -0
  75. package/dist/http_transport/utils/generateId.d.ts.map +0 -0
  76. package/dist/http_transport/utils/generateId.js +0 -0
  77. package/dist/http_transport/utils/generateId.js.map +0 -0
  78. package/dist/http_transport/utils/generateReferralCode.d.ts +0 -0
  79. package/dist/http_transport/utils/generateReferralCode.d.ts.map +0 -0
  80. package/dist/http_transport/utils/generateReferralCode.js +0 -0
  81. package/dist/http_transport/utils/generateReferralCode.js.map +0 -0
  82. package/dist/index.d.ts +4 -1
  83. package/dist/index.d.ts.map +1 -1
  84. package/dist/index.js +6 -2
  85. package/dist/index.js.map +1 -1
  86. package/dist/mraid.d.ts +7 -0
  87. package/dist/mraid.d.ts.map +1 -0
  88. package/dist/mraid.js +146 -0
  89. package/dist/mraid.js.map +1 -0
  90. package/dist/storeRouter.d.ts +0 -0
  91. package/dist/storeRouter.d.ts.map +1 -1
  92. package/dist/storeRouter.js +9 -8
  93. package/dist/storeRouter.js.map +1 -1
  94. package/dist/types/index.d.ts +0 -0
  95. package/dist/types/index.d.ts.map +0 -0
  96. package/dist/types/index.js +0 -0
  97. package/dist/types/index.js.map +0 -0
  98. package/dist/utils/Logger.d.ts +0 -0
  99. package/dist/utils/Logger.d.ts.map +0 -0
  100. package/dist/utils/Logger.js +0 -0
  101. package/dist/utils/Logger.js.map +0 -0
  102. package/dist/utils/dispatchWindowCustomEvent.d.ts +0 -0
  103. package/dist/utils/dispatchWindowCustomEvent.d.ts.map +0 -0
  104. package/dist/utils/dispatchWindowCustomEvent.js +0 -0
  105. package/dist/utils/dispatchWindowCustomEvent.js.map +0 -0
  106. 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;AAMnC,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;IAsDT,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;IAOpB,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,iBAAiB;IAQzB,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,wBAAwB;IAIhC,OAAO,CAAC,sBAAsB;CAG/B;AAED,eAAe,iBAAiB,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"}