Events
Seven lifecycle events emitted by the player. Wire them at init time, or attach later with player.on(eventName, fn).
ready
Fires when the iframe has loaded and the game is ready to receive input.{
game: string; // game ID, e.g. "sudoku"
mode: "pinned" | "daily" | "random" | null;
content: string | null; // pub_… or cha_… (null for default channels)
instanceId: string | null; // resolved publication identity for this load
gameType: string; // game folder name
externalUserId: string | null;
externalUsername: string | null;
}
Playgent.init({
/* … */
onReady: ({ game, content }) => console.log("ready", game, content),
});
view
Fires when the iframe enters the viewport (first time, by default).{
game: string;
content: string;
mode: "pinned" | "daily" | "random";
url: string; // current parent page URL
intersectionRatio: number; // 0 to 1
externalUserId: string | null;
externalUsername: string | null;
}
Threshold and once-vs-every-time behavior is configurable with viewThreshold and viewOnce.
start
Fires when the user clicks Play and the game begins.{
game: string;
mode: "pinned" | "daily" | "random" | null;
content: string | null;
instanceId: string | null;
gameType: string;
externalUserId: string | null;
externalUsername: string | null;
}
hint
Fires when the user presses the hint button during play.{
game: string;
mode: "pinned" | "daily" | "random" | null;
content: string | null;
instanceId: string | null;
gameType: string;
hintsUsed: number; // total hints used so far in this session
hintsRemaining: number; // remaining hints for this puzzle
externalUserId: string | null;
externalUsername: string | null;
}
Fires once per hint click. Counters reflect post-click state, so the very first hint click emits hintsUsed: 1. Not emitted when hints are disabled for the player or when no hints remain.
complete
Fires when the user finishes the game (wins, solves, or completes the puzzle).{
game: string;
mode: "pinned" | "daily" | "random" | null;
content: string | null;
instanceId: string | null;
gameType: string;
score: number | null;
won: boolean | null;
timeMs: number;
shareText: string | null; // pre-templated text for player.share()
externalUserId: string | null;
externalUsername: string | null;
}
This is the event you'll wire into your analytics pipeline most often.
end
Fires when the user presses the call-to-action button on the end screen.{
game: string;
mode: "pinned" | "daily" | "random" | null;
content: string | null;
instanceId: string | null;
gameType: string;
score: number | null;
won: boolean | null;
timeMs: number;
shareText: string | null;
externalUserId: string | null;
externalUsername: string | null;
}
Mirrors the complete payload, but fires only when the player presses the end-screen CTA — wire this when you want to react to that user action (open a custom modal, route inside your app, log engagement). The button itself is configured via ctaText, ctaButtonText, and ctaUrl; if ctaUrl is set the URL still opens in a new tab when the button is pressed, but the event fires either way. The complete event still fires automatically when the game ends, regardless of whether the user presses the CTA.
error
Fires when configuration is invalid, content is missing, or the game fails to load.{
code: string; // see /sdk/errors
message: string; // human-readable
recoverable: boolean; // true → SDK shows a Retry button
}
Attaching listeners later
const player = Playgent.init({ /* no callbacks */ });
player.on("complete", (data) => track(data));
player.on("error", (err) => log(err));
player.off("complete");