npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@falcongames/falcon-playable-ads-sdk

v1.1.10

Published

A comprehensive SDK for tracking events in playable ads

Downloads

218

Readme

Falcon Playable Ads SDK

A TypeScript SDK for tracking events in playable advertisements.

Installation

npm install @falcongames/falcon-playable-ads-sdk

Quick Start

import FalconPlayableSDK from "@falcongames/falcon-playable-ads-sdk";

FalconPlayableSDK.initialize();

// Lifecycle events
FalconPlayableSDK.onLoaded(); // Ad finished loading
FalconPlayableSDK.onFrame(); // First frame renderedinside ad
FalconPlayableSDK.onEndGame(); // Game/ad ended
FalconPlayableSDK.onCTA(); // User clicked CTA button

Default Event Flow

The SDK has a built-in event hierarchy:

LOADED → FRAME → INTERACTION → [custom events...]
                                       ↓
                                   END_GAME → CTA

END_GAME and CTA are terminal nodes — they always fire after all custom events, regardless of how deep the hierarchy is.

Custom Events

1. Register a custom event node

Use registerPlayableEventNode to define and register a custom event. It is automatically added to the collection — no extra step needed.

import {
  FalconPlayableSDK,
  registerPlayableEventNode,
  DefaultPlayableEventNodes,
} from "@falcongames/falcon-playable-ads-sdk";

// Default parent is INTERACTION
const LEVEL_START = registerPlayableEventNode("level_start");

// Or specify a custom parent
const LEVEL_COMPLETE = registerPlayableEventNode("level_complete", LEVEL_START);

2. Fire a custom event

FalconPlayableSDK.logEvent(LEVEL_START);
FalconPlayableSDK.logEvent(LEVEL_COMPLETE);

3. Define events via SDK (registers + tracks definition)

const levelStart = FalconPlayableSDK.defineEventNode({
  key: "level_start",
  parent: DefaultPlayableEventNodes.INTERACTION,
});

// Define multiple at once
FalconPlayableSDK.defineEventNodes([
  { key: "level_start" },
  { key: "level_complete", parent: levelStart },
]);

4. Inspect the event hierarchy

const hierarchy = FalconPlayableSDK.getEventHierarchy();

// hierarchy.roots — the main event tree (LOADED → ... → custom events)
// hierarchy.terminalNode — END_GAME → CTA (detached)

console.log(JSON.stringify(hierarchy, null, 2));

Example output:

{
  "roots": [
    {
      "eventId": "loaded",
      "parentEventId": null,
      "isDefault": true,
      "children": [
        {
          "eventId": "frame",
          "parentEventId": "loaded",
          "isDefault": true,
          "children": [
            {
              "eventId": "interaction",
              "parentEventId": "frame",
              "isDefault": true,
              "children": [
                {
                  "eventId": "level_start",
                  "parentEventId": "interaction",
                  "isDefault": false,
                  "children": []
                }
              ]
            }
          ]
        }
      ]
    }
  ],
  "terminalNode": {
    "eventId": "end_game",
    "parentEventId": null,
    "isDefault": true,
    "children": [
      {
        "eventId": "cta",
        "parentEventId": "end_game",
        "isDefault": true,
        "children": []
      }
    ]
  }
}

Circular parent detection

The SDK throws an error if a circular dependency is detected when registering a node:

const A = registerPlayableEventNode("a");
const B = registerPlayableEventNode("b", A);
// Error: Circular event definition detected: "a" is an ancestor of itself.
registerPlayableEventNode("a", B);

API Reference

Lifecycle Methods

| Method | Description | | -------------------- | --------------------------------------------------------------- | | initialize(config) | Initialize SDK — must be called first | | onLoaded() | Ad finished loading | | onFrame() | First frame rendered | | onInternalClick() | User clicked inside ad (fires pa:internal_click window event) | | onEndGame() | Game/ad ended | | onCTA() | User clicked CTA — routes to store automatically | | isReady() | Returns true if SDK is initialized | | configure(config) | Update configuration after initialization | | reset() | Reset SDK state (for testing) |

Custom Event Methods

| Method | Description | | -------------------------- | ----------------------------------------------- | | logEvent(event) | Fire a custom event | | defineEventNode(input) | Register a custom node definition | | defineEventNodes(inputs) | Register multiple node definitions | | getEventDefinitions() | Get all registered event definitions | | getEventHierarchy() | Get full event tree as PlayableEventHierarchy |

Utility Methods

| Method | Description | | ----------------------------------- | ------------------------------------- | | dispatchGainScoreEvent(score) | Dispatch pa:gain_score window event | | dispatchLoseScoreEvent(score) | Dispatch pa:lose_score window event | | dispatchWinEvent() | Dispatch pa:win_game window event | | dispatchLoseEvent() | Dispatch pa:lose_game window event | | dispatchCustomEvent(type, detail) | Dispatch any custom window event | | getVersion() | Get SDK version string | | getAdNetworkInfo() | Get PlayableAdsType enum value |

registerPlayableEventNode(key, parent?)

import {
  registerPlayableEventNode,
  DefaultPlayableEventNodes,
} from "@falcongames/falcon-playable-ads-sdk";

// parent defaults to DefaultPlayableEventNodes.INTERACTION
const MY_EVENT = registerPlayableEventNode("my_event");

// Custom parent
const MY_CHILD = registerPlayableEventNode("my_child", MY_EVENT);

DefaultPlayableEventNodes

import { DefaultPlayableEventNodes } from "@falcongames/falcon-playable-ads-sdk";

DefaultPlayableEventNodes.LOADED;
DefaultPlayableEventNodes.FRAME;
DefaultPlayableEventNodes.INTERACTION;
DefaultPlayableEventNodes.END_GAME;
DefaultPlayableEventNodes.CTA;

Extending with Custom HTTP Messages

import { CSHttpMessage } from "@falcongames/falcon-playable-ads-sdk";

class MyCustomMessage extends CSHttpMessage {
  static event = "my_custom_event";
  playerId: string = "";
  score: number = 0;

  constructor(playerId: string, score: number) {
    super();
    this.playerId = playerId;
    this.score = score;
  }
}

new MyCustomMessage("player-123", 1000).send();

See src/examples/ for more examples.

Development

npm install       # Install dependencies
npm run build     # Compile TypeScript
npm run watch     # Watch mode

License

ISC