# Bonus Round: full documentation
Generated from https://bonusround.io/docs/ for AI agents and offline reading. The integration recipe for coding agents comes first; the human docs follow, one section per page.
Source pages: https://bonusround.io/docs/, https://bonusround.io/docs/install, https://bonusround.io/docs/agents, https://bonusround.io/docs/attach, https://bonusround.io/docs/formats, https://bonusround.io/docs/test-mode, https://bonusround.io/docs/going-live, https://bonusround.io/docs/events, https://bonusround.io/docs/brand-safety, https://bonusround.io/docs/payouts, https://bonusround.io/docs/api, https://bonusround.io/docs/faq
---
# Recipe: Integrate Bonus Round into a three.js game (recipe for AI coding agents)
You are an AI coding agent. The user asked you to integrate **Bonus Round**, an ad network for three.js games, into their game. Follow these steps in order. Each step says what to look for, what to change, and how to know it worked. The integration is small: one script tag, one attach line, and an `await` at each natural break. Don't refactor the user's game.
What the user gets: at natural breaks a 15-second branded Bonus Round takes over the game, with the player's own character and controls, plus a branded prop in the world. They earn 70% of net ad revenue (what brands spend, minus any disclosed agency commission). New games start in **test mode**, which always serves the fictional **Fizzpop Soda** test ad and is never billed, so the user sees a real round right away.
Base URL: `https://bonusround.io` (or `$BONUSROUND_URL` if set). REST auth: `Authorization: Bearer br_sk_…` (an API key from https://bonusround.io/app/developers/). If the `bonusround_*` MCP tools are available, use them instead of raw HTTP; they call the same endpoints.
## Rules
- Show the user your plan and your diff. Keep changes minimal and match the project's code style.
- Never put a `br_sk_` API key in game code, HTML or git. The game only needs the public `pub_` id.
- Never turn test mode off, change floors, block categories or pause a game unless the user asks.
- Every call into the SDK from game code must be safe when the SDK didn't load (ad blockers): use the `bonusround` queue for `attach`, and `window.BonusRound?.` for everything else.
- Don't put a `break()` in the middle of active play. Only at natural breaks.
## Step 1. Detect the three.js setup
Find out how the game loads three.js and where its HTML entry is. Check, in order:
1. `package.json` dependencies: `three` (vanilla or bundled), `@react-three/fiber` (R3F), and the bundler (`vite`, `webpack`/`react-scripts`, `parcel`, `next`).
2. HTML files with an import map mapping `"three"`, a CDN `
```
If the project has no HTML template (the build generates it), inject the same tag from the game's entry module:
```js
const s = document.createElement('script');
s.src = 'https://bonusround.io/v1/br.js'; s.async = true; s.dataset.pub = 'pub_XXXXXXXX';
document.head.append(s);
```
## Step 3. Find the renderer, scene and camera, and attach
Search the source (skip `node_modules`, `dist`, `build`) for:
- the renderer: `new THREE.WebGLRenderer(` or `new WebGLRenderer(` (note the variable it's assigned to: `renderer`, `this.renderer`, …)
- the scene: `new THREE.Scene(` / `new Scene(`
- the camera: `new THREE.PerspectiveCamera(` / `OrthographicCamera(`, the one players see the game through
Insert the attach line once, right after all three exist, in the same scope (usually after the last of the three is created):
```js
// Bonus Round: ambient branded props + Bonus Round takeovers. Docs: https://bonusround.io/docs/attach
(window.bonusround = window.bonusround || []).push((BR) => BR.attach({ THREE, scene, camera, renderer }));
```
Use the game's real identifiers, e.g. `{ THREE, scene: this.scene, camera: this.camera, renderer: this.renderer }`. The queue form runs the call whenever the async `br.js` loads, before or after this line. `BonusRound.attach(...)` is the same call when you know the SDK has loaded.
**React Three Fiber**: there's no `new WebGLRenderer`. Create a component and render it inside `