Inngame / Guides

How to add a support chat to an HTML5 game

Web games get a lot of players and almost no way to hear from them. A comment on the portal page is public, slow, and usually says "it froze". A chat inside the game reaches you while the player is still there, and it can tell you which browser, which level and which error, without asking.

Published 31 October 2026 by the Inngame team. The first half applies whatever tool you use; the second half shows how it's done with Inngame, which we make.

What makes web games different

A support chat for a downloaded game and one for a browser game solve the same problem, but the browser adds its own constraints:

Building it yourself

The front end is the easy part: a panel, a list and a text field. The work is behind it: a server that stores conversations per player, real-time delivery (WebSocket with a fallback when it drops), photo storage with moderation if your audience is young, an inbox for your team, and a way to delete a player's data when they ask. If you only need a contact form, a mailto: link is honest and costs nothing. If you want replies inside the game, the backend is where the time goes.

Adding it with Inngame, step by step

1. Create the app and get the key

Sign up, create an app in the inbox, and copy its public key from Settings → Apps → General. The key identifies the game; it is not a secret.

2. Add one script tag

Host inngame.js with your game, or load it from our site, and add it after your game's scripts:

<script src="inngame.js" data-app-key="app_…"></script>

That's a working chat: a round button in the corner, the interface in the browser's language (25 languages), and your team's replies translated for the player.

3. Open it from your own menu

A floating button can sit on top of your controls. Hide it and open the chat from your pause or settings screen instead, with a badge for unread replies:

Inngame.init({ appKey: "app_…", launcher: false, appVersion: "1.4.0" });
helpButton.onclick = () => Inngame.open();
Inngame.on("unread", (n) => helpBadge.textContent = n || "");
Inngame.on("open", () => game.pause());
Inngame.on("close", () => game.resume());

4. Send the context your team needs

Every message already carries the page URL, browser, viewport, language, time zone and the last 50 console errors and warnings. Add your game's state with a function; it runs when the player sends a message, so it's always current:

Inngame.init({
  appKey: "app_…",
  context: () => ({ level: state.level, coins: state.coins, seed: state.seed }),
});

5. Know who the player is

If your game has accounts, identify the player after login so their conversation follows them to another browser. Pass a token signed by your server to make it a verified identity; without it, the id is only a label.

await Inngame.identify({ userId: account.id, name: account.nickname, token: account.inngameJwt });

6. Let your team give things back

When a bug costs a player their progress, your team can send an item card from the inbox. The player taps Claim, and your callback runs only if the server confirms this claim won, so a double tap or a second tab never grants it twice:

Inngame.init({
  appKey: "app_…",
  onItemGranted: (item) => inventory.add(item.id, item.quantity),
});

Events for automations (Inngame.track("level_failed", { level: 3 })), store review cards and satisfaction ratings are in the web SDK docs.

Before you ship: a test checklist

Start the 14-day trial

Questions

Does it work inside the itch.io or CrazyGames iframe?

Yes. The chat is drawn inside your game's page, so it stays within the iframe the portal gives you. Use launcher: false and open it from your own menu if a floating button would cover your game's controls.

Will the player keep their conversation between visits?

Usually. The SDK keeps a device token in localStorage. Some browsers partition or clear storage for games embedded on another site, and then a returning player starts a new anonymous conversation. Calling identify with your own account id keeps the history attached to their account.

How big is the script?

About 64 KB, 22 KB gzipped, with no dependencies. It loads after your game and does nothing until it gets a session.

Can I use it with Phaser, PixiJS, Godot or Construct exports?

Yes. It doesn't touch your canvas or game loop: it adds one element with its own Shadow DOM, so your CSS and its CSS can't clash.

What happens if the player is offline?

The chat shows an offline banner and the message waits. It is kept in the browser, even if the page is closed, and sent when the connection comes back or on the next visit, never twice.

Related: Support players in every language · Discord or in-game support? · Support chat in a Unity game · A Helpshift alternative for indie game studios · Player data requests · Web SDK docs · Inngame for HTML5 games · Inngame for web apps