Streaks
Track consecutive user engagement with configurable streak mechanics, grace periods, and freezes.
Streaks track consecutive user engagement over time. Define a qualifying event (like app_open or workout_completed), and Amba automatically tracks current count, longest count, and streak status.
How it works
- Admin defines a streak definition with a qualifying event and period
- When a user tracks the qualifying event, their streak is automatically updated
- If the user misses a period, the streak resets (unless a grace period or freeze is configured)
- Streak evaluation also runs daily in the background to catch broken streaks
Worked example: define once, qualify per user action
The full loop is two steps. You define the streak once (admin / MCP), then your app calls qualify per qualifying user action.
Snippets below import from
@layers/amba-webfor brevity. The wrappedAmba.streaksAPI is identical across@layers/amba-web,@layers/amba-node,@layers/amba-react-native, and@layers/amba-expo— substitute the package that matches your platform.
1. Define a streak (one-time, via MCP — usually from your dev shell or admin tool):
2. Qualify the streak from your app on every user action:
3. Handle the "streak isn't defined yet" case cleanly:
SDK usage
Get user's streaks
Each Streak carries:
Use status to drive UI copy ("You're on a 7-day streak!" vs. "Your streak is safe — we used a shield"), and freezes_remaining to show the user how many shields they have in reserve.
Qualify a streak manually
Automatic qualification
When you track an event that matches a streak's qualifying_event, the streak is automatically qualified:
Streak mechanics
Period
daily— user must qualify once per calendar dayweekly— user must qualify once per calendar week
Grace period
Set grace_period_hours to give users extra time before their streak breaks. For example, a 6-hour grace period means the user has until 6 AM the next day.
Streak freezes
When freeze_enabled is true, users can freeze their streak to prevent it from breaking. max_freezes controls how many freezes a user can hold at once.
Shields (freezes)
In partner-facing copy we call freezes "shields" — same field on the wire (freezes_remaining), different word for the user. A streak with 1 shield that misses its qualifying period is automatically converted from active to frozen instead of broken, and freezes_remaining is decremented by 1. The streak's current_count is preserved — never punish a missed day with a red number; show "your streak is safe" copy instead.
Field semantics
Streak configuration (set when creating a streak via amba_streaks_create):
| Field | Type | Meaning |
|---|---|---|
freeze_enabled | boolean | Master switch. If false, missing the period always breaks the streak. |
max_freezes | integer | Cap on how many shields a user can hold. Both auto-grant and admin grant clamp at this value. |
freezes_per_n_events | integer | null | Auto-grant rule: every N consecutive qualifying events grants 1 shield. null disables auto-grant — shields only come from explicit admin grants. |
Per-user streak state (returned by the client SDK):
| Field | Type | Meaning |
|---|---|---|
freezes_remaining | integer | Number of shields currently in the user's pool. Drops by 1 when a shield is consumed on a miss. |
status | enum | 'active' | 'frozen' | 'broken'. frozen is the moment a shield protected the streak. |
Auto-grant rule
Set freezes_per_n_events = 5, max_freezes = 2 to get the partner spec verbatim: every 5 completed missions grants the user 1 shield, capped at 2 concurrent shields.
The grant fires on the increment that crosses the threshold (i.e. when current_count % freezes_per_n_events === 0). Resets and restarts do NOT grant a shield.
Shield consumption emits streak_shielded
When the daily streak-evaluation finds a streak that missed its window and the user still has at least one shield, the streak flips to frozen, freezes_remaining decrements by 1, and a streak_shielded engagement event is emitted:
Use this event to render in-app "your streak is safe" copy or to drive a re-engagement push.
Granting shields manually
Grant additional shields to a specific user (admin-only) via the streak admin tooling:
Grants the user count additional shields, clamped at the streak's max_freezes. Returns the updated streak state. 404 if the user hasn't qualified for this streak yet — they must trigger the qualifying event at least once before a grant can land.
Admin API reference
| Method | Path | Description |
|---|---|---|
POST | /admin/streaks | Create streak definition |
GET | /admin/streaks | List streak definitions |
Client API reference
| Method | Path | Description |
|---|---|---|
GET | /client/streaks | Get user's streak states |
POST | /client/streaks/:id/qualify | Record qualifying event |
POST /client/streaks/:id/qualify
Records a qualifying event for a streak. Handles:
- Already qualified today (returns current state, no-op)
- Consecutive day (increments count)
- Broken streak (resets to 1)
Response:
MCP tools
| Tool | Description |
|---|---|
amba_create_streak | Create a streak definition with qualifying event, period, grace, and freeze settings |
Example
Reading streaks in React Native / Expo
The component below is React Native — runs identically on bare RN and Expo. Swap the import to match your SDK package: @layers/amba-react-native for bare RN, @layers/amba-expo for Expo managed.