Step 1
Parent page loads iframe
Your site renders an iframe pointing at /embed/{gameSlug}/frame/ with tenantId and optional mode or campaignId query params.
Embed API docs
Start with the live demo, watch the parent-page events, then copy the iframe and listener patterns into your site. The same flow works for every Games I Know iframe game.
Get an embed keyMake a move in the Tic Tac Toe iframe. The event log shows GAME_STARTED, gameplay events, and completion payloads exactly as a parent page receives them.
Platform-wide event contract
Games I Know sends embed events for every game on the platform: Tic Tac Toe, Four in a Row, Bingo, and I Know today, and every new embeddable game we add in the future. You do not need a separate integration per title. Build one parent-page listener against the standard contract (ready, GAME_STARTED, gameplay events, completion with winner data, and signed results) and reuse it across all current and upcoming embed games.
Use this path when you already know where the game should appear on your website.
Use /embed/{gameSlug}/frame/ with your tenantId. Do not iframe the SEO landing page.
Go to stepFilter on data.source === "gamesiknow", then handle GAME_STARTED, GAME_COMPLETED, and version 1 gameplay events.
Go to stepSend resultId and signedToken to your backend before granting credits, rewards, or unlocks.
Go to stepUse your real tenantId from the partner dashboard.
<iframe
src="https://gamesiknow.com/embed/tic-tac-toe/frame/?tenantId=YOUR_TENANT_ID"
title="Tic Tac Toe by Games I Know"
width="100%"
height="640"
style="border:0;border-radius:16px;max-width:420px;display:block;margin:0 auto;"
loading="lazy"
allow="fullscreen"
referrerpolicy="no-referrer-when-downgrade"
allowfullscreen
></iframe>A Games I Know embed is a sandboxed iframe on your domain. It validates your tenant and domain against the API, then communicates with your parent page through window.postMessage.
Step 1
Your site renders an iframe pointing at /embed/{gameSlug}/frame/ with tenantId and optional mode or campaignId query params.
Step 2
The iframe calls GET /embed/config (or /api/embed/config). Games I Know checks your partner account, allowed domain, game access, and AI quota. A server-side embed_loaded analytics event is recorded.
Step 3
The iframe posts a ready event to the parent page so you can show a loading state or resize the frame using payload.embedHeight.
Step 4
When gameplay begins, every embeddable game posts GAME_STARTED to the parent page and records game_started server-side automatically. You do not call any analytics API from your website.
Step 5
During the match, version 1 gameplay events such as move and mode_change update your UI or internal analytics.
Step 6
On completion, every embeddable game posts GAME_COMPLETED to the parent with outcome, winner, and players so your page can show results immediately. The iframe also signs the result via POST /embed/results and includes resultId and signedToken in GAME_COMPLETED when signing succeeds. Your backend can verify those tokens with a partner server key before granting rewards.
Two postMessage formats
Lifecycle events use a flat object with event: "GAME_STARTED" or event: "GAME_COMPLETED". Gameplay events wrap data in version: 1 with nested payload. Always filter on data.source === "gamesiknow".
Most integrations are four decisions: register the domain, generate a token, install the iframe, then listen for start and completion events.
Add every domain that will host a Games I Know embed. Domains are normalized so example.com and www.example.com are handled consistently.
Create a separate embed token for each website. This keeps analytics clean and prepares the account for future domain-based pricing.
Copy the iframe or responsive wrapper into your CMS custom HTML block, website builder embed area, or custom frontend template.
Handle GAME_STARTED and GAME_COMPLETED postMessage events on your parent page to show match state and winner details. Verify signed results from your backend with a partner server key before awarding rewards.
Width
Use 100% so the embed fills the available content column.
Height
640px for most games. Tic Tac Toe also works at 600px. Use payload.embedHeight from ready events to auto-resize.
Games
Use /embed/tic-tac-toe/frame/, /embed/four-in-a-row/frame/, /embed/bingo/frame/, or /embed/i-know/frame/.
Mode
Omit mode for player choice, or pass mode=ai when you want the embed to request AI first.
Player chooses match type inside the game when AI quota is available.
<iframe
src="https://gamesiknow.com/embed/tic-tac-toe/frame/?tenantId=TENANT_ID"
width="100%"
height="640"
style="border:0;border-radius:16px;max-width:420px;display:block;margin:0 auto;"
allow="fullscreen"
loading="lazy"
title="Tic Tac Toe by Games I Know"
></iframe>Requests AI first. Falls back to PvP silently when quota is exhausted.
<iframe
src="https://gamesiknow.com/embed/tic-tac-toe/frame/?tenantId=TENANT_ID&mode=ai&campaignId=homepage-widget"
width="100%"
height="640"
style="border:0;border-radius:16px;max-width:420px;display:block;margin:0 auto;"
allow="fullscreen"
loading="lazy"
title="Tic Tac Toe vs AI by Games I Know"
></iframe>Frame URLs use /embed/{gameSlug}/frame/. SEO landing pages without gameplay live at /embed/{gameSlug}/.
| Parameter | Required | Description |
|---|---|---|
| tenantId | Yes | Your partner tenant ID from the Games I Know partner dashboard. Also accepted as partnerId for legacy integrations. |
| mode | No | Set to ai to request forced AI mode. Server-side quota and domain rules still apply. Falls back to player vs player when AI is unavailable. |
| campaignId | No | Optional campaign label echoed in postMessage events and stored in partner analytics for A/B tests or page-level segmentation. |
The same contract applies across Tic Tac Toe, Four in a Row, Bingo, I Know, and upcoming embed releases.
Rule 1
Filter source
Ignore messages unless data.source is gamesiknow.
Rule 2
Handle lifecycle
Use GAME_STARTED and GAME_COMPLETED for match state, winner name, and outcome.
Rule 3
Verify for rewards
Forward resultId and signedToken to your backend before granting rewards.
| Event | When it fires | Format | Key fields |
|---|---|---|---|
| ready | Embed initialized and config loaded. | Gameplay (version 1) for all games, or flat for some lifecycle wrappers. | matchId, mode, embedHeight |
| GAME_STARTED | Every embeddable game (current and future). Fires when a match begins (for example, first move or AI round start). | Flat lifecycle | game, partnerId, campaignId, mode, matchId (implicit via gameplay stream) |
| GAME_COMPLETED | Every embeddable game when a match ends. Includes outcome, winner, winnerPlayerName, and players so the parent page can show results immediately. Also includes resultId and signedToken when server-side signing succeeds. | Flat lifecycle | outcome, winner, winnerPlayerName, winnerPlayerId, players, score, durationSeconds, resultId, signedToken |
| EMBED_FULLSCREEN_CHANGE | Player toggles in-embed fullscreen. | Flat lifecycle | payload.active boolean |
Shape: { source, game, version: 1, event, payload }
Every embeddable game posts GAME_COMPLETED to the parent with outcome, winner, and players when a match ends. When signing succeeds, GAME_COMPLETED also includes resultId and signedToken for backend verification.
{
"source": "gamesiknow",
"event": "GAME_STARTED",
"game": "tic-tac-toe",
"partnerId": "partner_your_tenant",
"campaignId": "homepage-widget",
"mode": "ai"
}{
"source": "gamesiknow",
"event": "GAME_COMPLETED",
"game": "tic-tac-toe",
"resultId": "res_abc123xyz",
"partnerId": "partner_your_tenant",
"campaignId": "homepage-widget",
"status": "completed",
"outcome": "player_1",
"score": 100,
"durationSeconds": 24,
"winnerPlayerId": "player_1",
"winnerPlayerName": "Player X",
"winner": {
"playerId": "player_1",
"participant": "player_1",
"type": "human",
"label": "Player 1",
"name": "Player X",
"score": 100
},
"players": [
{
"playerId": "player_1",
"participant": "player_1",
"type": "human",
"label": "Player 1",
"name": "Player X",
"score": 100,
"status": "winner"
},
{
"playerId": "player_2",
"participant": "ai_bot",
"type": "ai",
"label": "AI BOT",
"name": "AI Bot",
"score": 60,
"status": "lost"
}
],
"signedToken": "eyJ..."
}player_1
First human player won.
player_2
Second human player won.
ai_bot
AI opponent won.
draw
No winner.
Supported on Tic Tac Toe and Four in a Row only. Target the iframe contentWindow with the game slug and action.
// Parent page -> iframe (Tic Tac Toe or Four in a Row)
const iframe = document.querySelector("iframe");
iframe.contentWindow.postMessage(
{ game: "tic-tac-toe", action: "reset" },
"https://gamesiknow.com"
);
iframe.contentWindow.postMessage(
{ game: "tic-tac-toe", action: "get_state" },
"https://gamesiknow.com"
);Copy this listener onto the page that hosts your iframe. It handles ready state, game start, gameplay events, signed completion, and fullscreen changes.
Filter by source, handle GAME_STARTED and GAME_COMPLETED for winner UI and gameplay events during the match.
/**
* Games I Know embed listener (parent page)
* Handles lifecycle events (GAME_STARTED, GAME_COMPLETED) and
* version 1 gameplay events (move, mode_change, ...).
*/
const TRUSTED_ORIGIN = "https://gamesiknow.com"; // or your self-hosted origin
window.addEventListener("message", (event) => {
if (TRUSTED_ORIGIN !== "*" && event.origin !== TRUSTED_ORIGIN) return;
const data = event.data;
if (!data || data.source !== "gamesiknow") return;
// --- Lifecycle events (flat top-level event name) ---
if (data.event === "GAME_STARTED") {
console.log("Match started", {
game: data.game,
mode: data.mode,
partnerId: data.partnerId,
campaignId: data.campaignId,
});
return;
}
if (data.event === "GAME_COMPLETED") {
const winnerLabel = data.winner?.name ?? data.winnerPlayerName ?? null;
console.log("Match completed", {
game: data.game,
outcome: data.outcome, // player_1 | player_2 | ai_bot | draw
winner: data.winner,
winnerName: winnerLabel,
players: data.players,
});
if (winnerLabel) {
document.getElementById("game-winner")!.textContent = `${winnerLabel} won!`;
} else if (data.outcome === "draw") {
document.getElementById("game-winner")!.textContent = "Draw";
}
// For rewards: send resultId + signedToken to YOUR backend (never call verify from the browser)
if (data.resultId && data.signedToken) {
fetch("/api/reward-winner", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
resultId: data.resultId,
signedToken: data.signedToken,
userId: currentUserId,
}),
});
}
return;
}
if (data.event === "EMBED_FULLSCREEN_CHANGE") {
document.body.classList.toggle("embed-fullscreen-active", Boolean(data.payload?.active));
return;
}
// --- Gameplay events (version 1 envelope) ---
if (data.version === 1 && typeof data.event === "string") {
switch (data.event) {
case "ready":
resizeEmbed(data.payload?.embedHeight);
break;
case "mode_change":
console.log("Mode changed", data.payload?.mode);
break;
case "move":
console.log("Move", data.payload);
break;
default:
console.log("Gameplay event", data.event, data.payload);
}
}
});
function resizeEmbed(height) {
const iframe = document.querySelector('iframe[src*="/embed/"]');
if (iframe && typeof height === "number") iframe.style.height = `${height}px`;
}Integration checklist
Use GAME_COMPLETED on the parent page to show who won. For rewards, verify signed results from your backend with a partner server key - never call the verify API from browser JavaScript.
Server-side only. Use resultId and signedToken from GAME_COMPLETED with Authorization: Bearer gik_psk_…
POST https://api.gamesiknow.com/embed/results/verify
Authorization: Bearer gik_psk_your_secret_key
Content-Type: application/json
{
"resultId": "res_abc123xyz",
"signedToken": "signed_token_from_game_completed"
}
Call from your backend server only. The partner server key must belong to the same tenant as the signed result. Browser requests are rejected.{
"ok": true,
"resultId": "res_abc123xyz",
"partnerId": "partner_your_tenant",
"gameSlug": "tic-tac-toe",
"outcome": "player_1",
"score": 100,
"durationSeconds": 24
}Your backend receives tokens from the parent page, verifies with Games I Know, then grants the reward.
// Example: Node.js / Express handler on YOUR server
app.post("/api/reward-winner", async (req, res) => {
const { resultId, signedToken, userId } = req.body;
const verify = await fetch("https://api.gamesiknow.com/embed/results/verify", {
method: "POST",
headers: {
"content-type": "application/json",
authorization: `Bearer ${process.env.GAMESIKNOW_PARTNER_SERVER_KEY}`,
},
body: JSON.stringify({ resultId, signedToken }),
});
if (!verify.ok) return res.status(403).json({ error: "Invalid result" });
const result = await verify.json();
if (result.outcome !== "player_1") {
return res.status(400).json({ error: "Player did not win" });
}
await grantReward(userId, result);
return res.json({ ok: true });
});Games I Know records these events automatically when your iframe loads and players interact. They appear in your partner dashboard. To pull the same data into your own database, create a partner server key on the Install page and call GET /partners/analytics from your backend server only.
Generate a partner server key in Partner Dashboard → Install. Store it as a server secret. Use the query parameters below to filter the export.
GET https://api.gamesiknow.com/partners/analytics
Authorization: Bearer gik_psk_your_secret_key
Optional query parameters:
domain Registered website hostname (example.com)
campaignId Value from your iframe campaignId parameter
gameSlug tic-tac-toe | four-in-a-row | bingo | i-know
from Start date in UTC (YYYY-MM-DD)
to End date in UTC (YYYY-MM-DD)
Example:
/partners/analytics?domain=www.example.com&gameSlug=tic-tac-toe&from=2026-05-01&to=2026-05-31
Call from your backend server only. Never expose your partner server key in browser JavaScript.Every embeddable game sends the same core events. Compare timing and extras per title below.
| Game | GAME_STARTED | Completion signal | Signed | Forced AI | Height | Parent commands |
|---|---|---|---|---|---|---|
| Tic Tac Toe | First move or AI start | GAME_COMPLETED | Yes | Yes | 640px | reset, get_state |
| Four in a Row | First move or AI start | GAME_COMPLETED | Yes | Yes | 640px | reset, get_state |
| Bingo | Match begins (AI or PvP) | GAME_COMPLETED | Yes | Yes | 640px | None yet |
| I Know | Match begins (AI or PvP) | GAME_COMPLETED | Yes | Yes | 640px | None yet |
This page is the technical reference. Use these guides when you need platform-specific install steps or vertical placement advice. All guides use the same iframe and event model documented above.
Framework-specific iframe placement, event listeners, and production notes.
Copy-paste embed guides for no-code and low-code site builders.
Placement and UX recommendations for common website types.
Looking for general overview pages such as iframe games, HTML5 widgets, or free embeddable games? Browse all embed guides on the hub.
Answers for integration details, current game support, commands, signed results, and future game compatibility.
Yes. Games I Know embeds use standard iframe HTML, so they work in WordPress custom HTML blocks, Webflow embed elements, Wix and Squarespace custom code areas, static HTML, React, Next.js, and other custom sites. Register the website domain in your partner dashboard first, then paste the generated frame snippet into the page where the game should appear.
/embed/{gameSlug}/ is the public landing page for a game embed. /embed/{gameSlug}/frame/ is the iframe runtime that should be pasted into your website. Always use the /frame/ URL in iframe code because it loads the playable game, validates your tenant and domain, and sends parent-page events.
Yes. Games I Know iframe games are designed for mobile, tablet, laptop, and desktop browsers. Use width="100%" and a recommended height of about 640px for most embeds. You can also listen for the ready event and use payload.embedHeight if you want your parent page to resize the iframe automatically.
Games I Know iframe embeds are free during the embed beta. There is no credit card requirement to get started, and the current beta embeds do not include ads. Create a free partner account, register your domain, and generate the iframe snippet from the dashboard.
Yes. A partner account gives you a tenant ID and domain-restricted iframe snippet. The iframe sends tenantId with the frame URL so Games I Know can validate the partner, allowed domain, game access, AI quota, analytics campaign, and result verification flow.
The embed is domain restricted. If someone copies your iframe snippet onto an unauthorized website, Games I Know checks the request origin against the domains configured for your partner account and blocks unapproved use. Use separate campaign IDs when you want cleaner analytics per website or campaign.
Tic Tac Toe, Four in a Row, Bingo, and I Know support iframe embeds today. Each game sends the standard embed event contract for ready state, game start, gameplay, completion, winner data, analytics, and result verification. New embeddable games are expected to follow the same event pattern so partners do not need to rebuild their integration.
Every embeddable game uses two postMessage formats. Lifecycle events use a flat shape with source: gamesiknow and event values such as ready, GAME_STARTED, GAME_COMPLETED, and EMBED_FULLSCREEN_CHANGE. Gameplay events use version: 1 with nested event names such as ready, mode_change, move, reset, undo, and state. Always filter on data.source === "gamesiknow".
Yes. Listen for GAME_STARTED when a match begins, use gameplay events such as move and mode_change during play, and use GAME_COMPLETED when a match ends. GAME_COMPLETED includes outcome, winner, players, score, duration, and result identifiers where signing is available. Server-side analytics also record loads, starts, completions, blocked attempts, and CTA clicks.
Use GAME_COMPLETED when a match ends. Every embeddable game sends this lifecycle event with outcome, winner, winnerPlayerName, and players. When GAME_COMPLETED includes resultId and signedToken, forward those to your backend and call POST /embed/results/verify with your partner server key before granting rewards or credits.
Add window.addEventListener("message", handler) on the page that hosts the iframe. In the handler, ignore messages unless event.data.source === "gamesiknow". Branch on event.data.event for lifecycle events, or on event.data.event plus event.data.version === 1 for gameplay events. Optionally validate event.origin against your allowed Games I Know origin.
Use GAME_COMPLETED on the parent page to show who won immediately (outcome, winner, winnerPlayerName, players). For rewards, send resultId and signedToken from GAME_COMPLETED to your backend, then call POST /embed/results/verify with Authorization: Bearer gik_psk_… using a partner server key from your dashboard. The verify endpoint is server-side only - never call it from browser JavaScript. Only grant rewards after verification succeeds.
Required: tenantId (your partner tenant ID). Optional: mode=ai to request forced AI mode when quota allows, and campaignId to segment analytics. Frame URLs follow /embed/{gameSlug}/frame/?tenantId=YOUR_TENANT_ID.
Yes. Add mode=ai to the iframe URL to request AI mode first. Server-side quota and domain rules still apply, so the embed can fall back to player choice or player vs player when AI mode is unavailable or quota is exhausted.
Tic Tac Toe and Four in a Row accept parent messages with game set to the game slug and action set to reset or get_state. The iframe responds with a state gameplay event. Other embed games do not expose parent commands yet.
Confirm the website domain is active before generating a token.
Use a separate token or campaignId for every website or campaign group.
Listen for GAME_STARTED and GAME_COMPLETED on the parent page.
Keep the Games I Know branding visible inside the embed.
Verify signed results on your backend before awarding prizes or credits.
Test forced AI mode and PvP fallback when AI quota is exhausted.
Share the website, CMS, and desired game placement. We can review your embed event wiring with you.