# Playtests

> Share a private link that serves any build you choose, then read what testers said, with play time, device and errors attached.

A playtest is one private link to one build of your game. Testers play it, answer your questions and leave notes, and you read all of it in an inbox. It is the one place on the site where strangers are asked to find your bugs on purpose.

Playtests are for developers. If you were sent a link to test something, jump to [For testers](#for-testers).

## The loop

1. [Upload a build](/docs/publish).
2. Start a playtest and send the link to people.
3. Read the feedback in your inbox.
4. Fix things, upload again, and choose **Send to testers**.
5. Mark the feedback **Addressed**. Testers see which build fixed it.
6. Repeat.

## Start a playtest

You need [developer access](/docs/publish) and at least one uploaded build.

1. Open `/dev/<slug>` and find the **Playtest** panel.
2. Press **Start a playtest**. The button stays disabled until the game has a build.
3. Copy the **Playtest link**.

A game has one playtest. It works on a draft or a released game. It starts on the live build, or on the newest build if nothing is live yet. You can change that at any time (see [Choose the build](#choose-the-build)).

## The link and who can use it

The link is `https://www.fradiation.games/t/<token>`. The token is 12 random lowercase letters and digits. It is the only access control: anyone who has the link can open it. The page is not listed anywhere, is marked `noindex`, and sends no referrer.

Under **Who can test** you pick one of two settings and press **Save**:

| Setting | Effect |
| --- | --- |
| Anyone with the link | Guests can play and leave feedback with no account. This is the default. |
| Badges only | The server only accepts sessions and feedback from testers signed in with a handle. Guests see a sign-in prompt instead of the feedback form. |

> [!NOTE]
> Badges only limits who can record sessions and leave feedback. Anyone with the link can still load the page and start the game.

Other controls in the panel:

- **Close playtest.** The link shows "This playtest is closed." Feedback so far stays in your inbox. **Reopen** brings back the same link.
- **Hold to reset link.** Creates a new link. The old one stops working (it returns a 404). Use it when the link went further than you meant. Sessions and feedback are kept.

Reset, the note, the questions and **Who can test** are only available while the playtest is open. Testers see changes the next time they load the link.

## Choose the build

The build testers get is independent of the live build. A released game can keep its live build while testers play the next update.

- **When you upload.** Once the game has a playtest, the upload form has a **Playtest** choice: **Send to testers** (the default) or **Keep their build**. It is separate from **Go live now** and **Upload only**.
- **From the builds list.** The build testers have is tagged **Testing**. Any other ready build has a **Test** button that points testers at it. Use it to roll testers forward or back.

Testers get the new build the next time they load the link, not in the middle of a session. The build testers have is never deleted by [build retention](/docs/builds).

## Note and questions

Both live in the **Playtest** panel while the playtest is open.

| Field | Limit | Where testers see it |
| --- | --- | --- |
| Note to testers | 1,000 characters, optional | Above the game, labelled with your handle. Say what to try and what is broken on purpose. |
| Questions | Up to 5, 200 characters each | As extra fields in the feedback form. Answers can be 2,000 characters. |

Blank and duplicate questions are dropped. Only answers to questions that are currently set are stored, so if you reword a question while a tester has the page open, their answer to the old wording is discarded. Change questions between rounds.

## What is captured

A session starts when a tester presses **Start** on the game. Your own plays on your own playtest link do not create sessions.

| What | Detail |
| --- | --- |
| Play time | Counted only while the tab is visible. Reported every 20 seconds and when the page is hidden or closed. Counts up to 6 hours per session. |
| Browser | Chrome, Edge, Firefox or Safari with the major version. Anything else is "Other". |
| Operating system | iOS and Android with the major version. Windows, macOS, ChromeOS and Linux by family only. |
| Mobile | Yes or no. |
| Screen | Width, height and pixel ratio, for example `1920×1080 @1x`. |
| GPU renderer | The graphics renderer name the browser reports through WebGL, up to 160 characters. |
| CPU cores | The core count the browser reports. |
| Memory | The rounded device memory figure, only in browsers that report one. |
| Errors and events | Uncaught errors, plus anything the game sends through the [SDK](/docs/sdk). See below. |

That is the complete list. The server accepts only these fields and drops anything else a browser sends. Playtest data has no field for the full user-agent string, the exact browser version or an IP address.

Screen size, GPU, cores and memory together narrow a device down more than a browser name does. They are stored so you can reproduce a bug ("crashes on Safari 18, iPhone"), and only you and site admins can read them. There is no setting to turn device capture off. Testers are told what is sent under the game before they press **Start**, again next to the send button, and in [For testers](#for-testers).

## SDK hooks

The [SDK](/docs/sdk) reports to your inbox automatically once it is loaded. Two calls add more.

```js
fradiation.track("reached-level", { level: 3 });
fradiation.askForFeedback("How was that boss?");
```

```csharp
Fradiation.Track("reached-level", "{\"level\":3}");
Fradiation.AskForFeedback("How was that boss?");
```

- **`track(name, data?)`** adds a moment to the session timeline. The name is cut to 80 characters. Ignored outside playtests.
- **`askForFeedback(prompt?)`** scrolls the tester to the feedback form and focuses the notes field. The prompt (up to 200 characters) is shown above the form and saved with the feedback. It returns `{ opened }`, which is `false` outside playtests and on your own view of the link.
- **Errors** are captured with no code from you: uncaught errors and unhandled promise rejections, deduplicated, at most 20 per page load.
- **Mutations and scores** the game reports during a playtest are logged on the timeline and not kept. Testers get a "test" toast.

Timeline limits: 300 events per session, 1.5 KB of data per event (larger data is dropped and the name kept), and 60 events per 10 seconds per game frame. The game gets `mode: "playtest"` from `ready()`.

## The inbox

Open it from the **Inbox** button in the Playtest panel, or at `/dev/<slug>/feedback`. Your game list at `/dev` shows "N new" next to games with unread feedback. The inbox holds the newest 300 feedback items and 200 sessions.

The top of the page shows testers, sessions, total play time, errors and feedback counts.

### Feedback tab

- Items are grouped by the build the tester played, newest build first. Each group shows that build's patch notes and, for the current one, "in the playtest now".
- Each item shows who sent it, when, the fun rating (0 to 5 in half steps), difficulty (too easy, about right, too hard), whether they would play again, answers, notes, and the prompt if the game asked for feedback.
- Expand the context line to see play time, browser, OS, screen, GPU, error count and the event timeline.
- Signed-in testers appear as `@handle` with a link to their profile. Guests appear as "Name (guest)" if they gave a name, otherwise "Guest" and four characters of their tester id.

Filters:

| Filter | Shows |
| --- | --- |
| New | Items you haven't touched. The default when there are any. |
| Not addressed | New and read items. |
| All | Everything. The default when nothing is new. |

### Sessions tab

Every session, including testers who never wrote anything: who, when, build, play time, errors, how many feedback items came from it, device and timeline.

### Read and addressed

Each item has **Mark read** (while it is new) and **Addressed**. An addressed item has **Reopen**, which sets it back to read and clears its fix.

## Fixed in a build

Marking an item **Addressed** tells the tester where it was fixed. What is recorded depends on which build testers have when you press the button.

| Testers have | What happens | Tester sees |
| --- | --- | --- |
| A different build than the one the feedback was about | The build they have now is recorded as the fix. | Fixed in `a1b2c3d` |
| The same build the feedback was about | The fix is pending. Your inbox says "Addressed · ships with the next test build". | Fix coming |

A pending fix is stamped by the next build you send to testers, through **Send to testers** at upload or **Test** in the builds list. That build becomes the "Fixed in" build for every pending item at that moment.

> [!TIP]
> Either order works: mark items addressed and then send the fix, or send the fix and then mark them. Only mark what you fixed, because the next send stamps everything pending.

Build ids are the first 7 characters of the build hash.

## What returning testers see

- **New build since you played.** When the build now in the playtest differs from the one in their last session, they see a panel with the new build's patch notes ("No patch notes for this one." if you left them blank). Write patch notes when you upload.
- **Your feedback.** A list of their latest 20 feedback items with a status: Sent, Read, Fix coming or Fixed in `<build>`.
- **Your note**, still above the game.

Guests are remembered by a cookie, so they see this in the same browser. Signed-in testers see it on any device.

## Limits

| Limit | Value |
| --- | --- |
| Playtests per game | 1 |
| Note | 1,000 characters |
| Questions | 5, at 200 characters each |
| Feedback text | Notes 4,000 characters, each answer 2,000, guest name 40 |
| Feedback per tester | 20 per playtest per rolling 24 hours |
| Sessions per tester | 60 per playtest per rolling 24 hours |
| Play time counted | 6 hours per session |
| Session updates | A session stops accepting updates 24 hours after it starts |
| Timeline events | 300 per session, 1.5 KB of data each |
| Uncaught errors | 20 per page load, duplicates counted once |
| Inbox | Newest 300 feedback items and 200 sessions |

Uploading and build limits are in [Publishing](/docs/publish) and [Builds](/docs/builds).

## For testers

You were sent a link. Open it and press **Start**.

- **No account needed.** Guests can play and send feedback. Some playtests are badges only and ask you to sign in first.
- **The form.** Rate how fun it was, say whether it was too easy or too hard, say whether you would play again, answer the developer's questions and write whatever else you want. Fill in at least one thing. You can send more than once.
- **What the developer sees.** Your answers, your play time, your browser and OS (family and major version), screen size, graphics renderer, CPU cores, memory, any errors the game hit, and events the game logs. Signed-in testers show as `@handle`, which links to their public profile. Guests show as the name they typed, or "Guest" with four characters of an id.
- **The guest cookie.** Guests are told apart by a first-party cookie named `fradiation_tester`, set when you press **Start** or send feedback. It lasts a year. Clear it and you are a new tester.
- **What the developer does not see.** Your email or anything else private from your account. A guest is only a name you chose and an id. See [Privacy](/privacy).
- **Rads.** Testers signed in with a handle earn 10 rads per feedback (the first 10 in any 24 hours) and the Test Subject mutation the first time. Playing a playtest pays nothing, and mutations and scores from the game are not kept. See [Rads and mutations](/docs/rads).
- **Coming back.** When the developer sends a new build, you see what changed and what happened to your feedback.
