---
title: Feedback after first spins
description: A worked gameplay example using existing progress facts, local activity and availability.
package: "@userreason/js"
version: "0.5.4"
url: https://docs.userreason.com/examples/first-spins-feedback/
updated: 2026-10-16
---

# Feedback after first spins

Suppose a game wants to ask players whose accounts are less than 24 hours old and who have Career access how their first spins felt. It should ask after at least three completed spins, at the next idle moment. This is one product's requirement: its account-age window, feature and count are not defaults for other surveys.

The approach also applies to other products: expose reusable application facts, choose an opportunity, and configure the audience remotely. Start with [Your first survey](https://docs.userreason.com/get-started/first-prompt/index.md) for a complete definition and the create/review/publish flow.

## Use the game's existing facts

First establish what "three spins" means. Three spins observed in this browser are different from three spins in the current campaign or across the player's lifetime. For this example, use the game's existing count of settled spins in the current campaign.

| Requirement | Reusable application input |
| - | - |
| Account less than 24 hours old | Current account age in hours, derived from the application's account creation time. |
| Career access | The application's current feature-access flag. |
| At least three completed spins in this campaign | Its existing settled-spin count. |
| Ask at the next idle moment | Availability based on gameplay, blocking dialogs and other interruptions. |

After SDK initialization and identity resolution, call this adapter from the application's existing state updates:

```ts
import UserReason from '@userreason/js';

export function updateGameFeedback(state: {
  accountAgeHours: number;
  careerAvailable: boolean;
  campaignSpinCount: number;
  busy: boolean;
}): void {
  UserReason.setContext({
    accountAgeHours: state.accountAgeHours,
    careerAvailable: state.careerAvailable,
    campaignSpinCount: state.campaignSpinCount,
  });
  UserReason.setAvailable(!state.busy);
}

export function reportCompletedSpin(): Promise<boolean> {
  return UserReason.event('spin.completed');
}
```

Update these facts before reporting a confirmed spin completion. Recalculate account age when updating context, including when resuming the app; a value captured once at sign-in becomes stale. Update availability whenever busy state changes. Keep the application's normal identity lifecycle, and repopulate context when the account changes.

Register `spin.completed` with the **Activity** preset so this high-volume stream stays local. This example needs no uploaded spin history: its count already belongs to the game. If a separate question needs retained history, collect an appropriate lower-volume milestone rather than mirroring every spin.

## Configure this survey remotely

For the complete survey from [Your first survey](https://docs.userreason.com/get-started/first-prompt/index.md), replace its `rules` value with:

```json
{
  "schema_version": 1,
  "audience": {
    "type": "all",
    "rules": [
      { "type": "field", "source": "application_context", "key": "accountAgeHours", "comparison": { "operator": "gte", "value": 0 } },
      { "type": "field", "source": "application_context", "key": "accountAgeHours", "comparison": { "operator": "lt", "value": 24 } },
      { "type": "field", "source": "application_context", "key": "careerAvailable", "comparison": { "operator": "eq", "value": true } },
      { "type": "field", "source": "application_context", "key": "campaignSpinCount", "comparison": { "operator": "gte", "value": 3 } }
    ]
  },
  "triggers": [{ "type": "event", "event_key": "spin.completed" }],
  "frequency": { "mode": "site_default" }
}
```

Adapt the questions to ask "How did your first spins feel?" and optionally "What could we improve?" Keep the site's frequency settings unless the research requires a different exposure policy.

There is no upper spin-count bound because this question should remain relevant if more spins finish while the game is busy. A study specifically about the third through fifth spins could add that upper bound, accepting that some players will pass the window before they are available. Thresholds belong to this survey's research requirements, not the SDK integration.

If the intended requirement really is three observations in this browser, a [local activity rule](https://docs.userreason.com/prompts/targeting/index.md#local-activity-counts-and-delay) can replace the application's count condition. It cannot establish campaign-wide or cross-device progress. Application context is unverified browser input; use [verified identity and facts](https://docs.userreason.com/sdk/identity/index.md#verified-identity) when eligibility needs a trusted assertion.

## Check before publishing

Run `userreason prompt validate --file prompt.json` on the complete definition. Check that the installed SDK supports the required capabilities and that the event's policy stays local. Validation saves nothing and does not prove that a real visitor can see the survey.

In a development browser, verify both qualifying and excluded players: missing Career access, an older account, fewer than three spins and busy gameplay. Confirm that returning to an idle state can display an eligible survey, and that dismissal and response limits still apply. Change the survey remotely for another research question; the reusable state and availability adapter should usually remain sufficient.
