> ## Documentation Index
> Fetch the complete documentation index at: https://documentation.onesignal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Loyalty Journey: Mobile Gaming

> Build an automated loyalty program that rewards continued engagement, drives tier progression and turns retained players into high value advocates.

A Loyalty Journey is an automated messaging flow that starts after players finish your Welcome Journey. Its goal is to reward continued play, move players through loyalty tiers and turn retained players into high value advocates.

This tutorial covers two implementation cases:

* **Case 1 – Basic:** Session count and two tags (`loyalty_tier`, `lifetime_points`) set via the OneSignal SDK or API. Fixed milestone rewards. No webhooks.
* **Case 2 – Advanced:** Same linear tier progression structure as Case 1. Adds webhooks that sync to your backend, tier-locked monetization offers, deeper Liquid personalization and a winback email escalation for players inactive 14+ days.

You can start with Case 1 and graduate to Case 2 once your data infrastructure is in place. Both cases are designed to begin after a player completes your [Welcome Journey](./welcome-journey-mobile-gaming) (typically Day 7+).

***

## Loyalty program goals

| Goal                         | Description                                                                                            |
| ---------------------------- | ------------------------------------------------------------------------------------------------------ |
| Reward consistent engagement | Recognize returning players with escalating rewards tied to activity milestones                        |
| Drive tier progression       | Move players through Bronze → Silver → Gold → Platinum with clear rewards at each threshold            |
| Increase purchase frequency  | Use perks locked to each tier and limited time offers to convert engaged free players                  |
| Strengthen social bonds      | Use guild membership, friend referrals and cooperative play to make it harder for players to walk away |
| Reduce drop-off              | Detect engagement dips early and step in before the player goes quiet                                  |
| Build advocacy               | Encourage high tier players to recruit friends, leave reviews and participate in community events      |

***

## Prerequisites

**For both cases:**

* Familiarity with [Journeys overview](./journeys-overview) concepts
* An active OneSignal app with push notifications configured
* OneSignal [mobile SDK](./mobile-sdk-setup) installed
* Players have completed your [onboarding flow](./welcome-journey-mobile-gaming) (7+ sessions recommended)

**For Case 1, you also need:**

* Segment: Session count > 6 (players who have completed onboarding)
* Tags `loyalty_tier` and `lifetime_points` set on the player's profile via the [mobile SDK `addTags` method](./mobile-sdk-reference#addtag-addtags) or the [Update user API endpoint](/reference/update-user)

**For Case 2, you also need:**

* [External ID](./users#external-id) configured so player profiles are unified across devices and channels
* [Data tags](#user-properties-tags) representing loyalty state, purchase history and engagement metrics
* [Custom events](#events-to-track) firing from your game backend for purchases, level-ups, daily logins, social actions and milestone completions
* [Journey webhooks](./journeys-webhook) enabled on your account (contact OneSignal sales for access)

***

## Loyalty tier structure

Both journeys use a four tier system. The thresholds and perks below are examples. Define what makes sense for your game's economy.

| Tier     | Points threshold | Example perks                                                      |
| -------- | ---------------- | ------------------------------------------------------------------ |
| Bronze   | 0                | Daily login bonus, basic cosmetic rewards                          |
| Silver   | 500              | 2x daily bonus, exclusive Silver cosmetics, priority matchmaking   |
| Gold     | 2,000            | 3x daily bonus, Gold exclusive gear, early access to events        |
| Platinum | 5,000            | 5x daily bonus, Platinum badge, VIP shop, direct developer channel |

Your game backend calculates and stores the official point total. The journey reads that value through tags to route players and personalize messages.

***

## Case 1: Basic loyalty journey

Target players using session count and two tags set on each player's profile via the OneSignal SDK or API. This case requires no custom event tracking and can run alongside your existing onboarding journey.

### How this journey works

The journey rewards players who completed onboarding by recognizing their progress through Bronze → Silver → Gold → Platinum and bringing them back if they go quiet. After session 6 the player enters the journey at Bronze and sees a welcome in-app message.

The journey then runs three nearly identical tier sections in order: Bronze → Silver, Silver → Gold, Gold → Platinum. Each section watches three signals in parallel and routes the player down whichever fires first:

* **Approaching the next tier:** send a points-to-go push, then wait for the tier to be reached
* **Already in the next tier (catch-up):** skip the push and go straight to the celebration in-app message
* **Inactive for 7+ days:** send a re-engagement push, then wait for the tier to be reached

When the player reaches the next tier, all branches converge at a celebration in-app message. The pattern repeats for the next section. After the Platinum celebration, the journey ends with a referral push.

This case doesn't require custom events or backend webhooks. Your app or backend updates the `loyalty_tier` and `lifetime_points` tags via the OneSignal SDK (`addTags`) or server-side API and the journey reacts to segment membership changes automatically.

### At a glance

| Step                         | Channel | Timing                                                   | Message                                                |
| ---------------------------- | ------- | -------------------------------------------------------- | ------------------------------------------------------ |
| Loyalty welcome              | In-App  | Journey entry                                            | Tier map + program introduction                        |
| Tier approaching nudge       | Push    | When the player enters the approaching segment           | Points to next tier calculation                        |
| Tier celebration IAM         | In-App  | When the player enters the next tier segment             | Full screen milestone achievement                      |
| Engagement dip re-engagement | Push    | When the player enters the Low weekly engagement segment | Tier specific progress nudge with a bonus points offer |
| Platinum referral            | Push    | After the Platinum celebration IAM                       | Friend invite with bonus points                        |

### Journey settings

Configure these settings on the **Settings** tab of the journey before building the steps. See [Journey settings](./journeys-settings) for full reference.

| Setting                                | Value                                                                                                                                                                                                                                                                            |
| -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Entry rules: Audience segment**      | Session count > 6 AND `loyalty_tier` exists                                                                                                                                                                                                                                      |
| **Entry rules: Future additions only** | Checked. Only players who newly cross session 6 enter the journey. Existing Silver, Gold and Platinum players at launch never enter, which is intentional. The welcome step is meant for new loyalty enrollees.                                                                  |
| **Exit rules**                         | None. The journey naturally ends after the Platinum referral push. Setting an exit rule on the Platinum segment would remove players before they reach the Platinum celebration in-app message, per [exit rule behavior](./journeys-settings#exit-when-a-user-enters-a-segment). |
| **Re-entry rules**                     | Not enabled. With future additions only checked, players who exit (at Platinum or via expiration) cannot re-enter this journey. Route exiters into a separate VIP journey (Platinum graduates) or winback journey (expiration exits) with their own entry criteria.              |

### Required segments

Wait Until conditions route players based on segment membership. Create these segments before building this journey.

| Segment name              | Filters                                                 |
| ------------------------- | ------------------------------------------------------- |
| Bronze approaching Silver | `loyalty_tier` = `bronze` AND `lifetime_points` > 399   |
| Silver tier               | `loyalty_tier` = `silver`                               |
| Low weekly engagement     | `Last session` > 4 days ago                             |
| Silver approaching Gold   | `loyalty_tier` = `silver` AND `lifetime_points` > 1,599 |
| Gold tier                 | `loyalty_tier` = `gold`                                 |
| Gold approaching Platinum | `loyalty_tier` = `gold` AND `lifetime_points` > 3,999   |
| Platinum tier             | `loyalty_tier` = `platinum`                             |

<Note>
  **In-app message timing:** In-app message steps display on the player's next session, not immediately when they reach the step. A new session starts when the app has been out of focus for 30+ seconds and is brought back. If a player is already active when they hit an in-app message step, they won't see it until the next session. Each in-app message also displays only once per player.
</Note>

<Note>
  **Wait Until expirations:** Each tier section's multi-condition Wait Until uses a **21-day** expiration to give slow but active players time to reach the approaching segment. The single-condition Wait Untils after each push use a **10-day** expiration since the player was already nudged. All expiration branches **exit the journey**: players won't re-enter (future additions only is enabled), so route stalled players to a separate winback journey if you want to recover them.
</Note>

### Journey steps

The journey opens with a welcome in-app message, then runs three tier sections in order: Bronze → Silver, Silver → Gold and Gold → Platinum. Each tier section is self-contained and ends at its tier celebration in-app message.

Each tier section opens with a multi-condition Wait Until that forks into four branches. Build the nodes for each branch separately in the journey builder. All non-exit branches converge at the tier celebration in-app message before the next tier section begins.

Each Wait Until's expiration branch exits the journey if the player doesn't progress: 21 days at the start of each tier section, 10 days after each push. The journey settings disable re-entry, so route stalled players to a separate winback journey.

#### Welcome (before the first tier section)

<Steps>
  <Step title="In-App Message: Loyalty welcome">
    Include a visual showing all four tiers so the player can see the full progression path. Set the trigger to **On app open** and the delivery schedule to **1 week**.

    *"You're in. Welcome to \[Game Name] Elite Rewards. Bronze status, locked in. Play. Win. Climb. Silver unlocks at 500 points and that's just the first rung."*
  </Step>
</Steps>

#### Tier section: Bronze → Silver

##### **The fork: multi-condition Wait Until**

<Steps>
  <Step title="Wait Until: multi-condition fork">
    Three segment conditions plus a **21-day expiration**. Each condition creates its own branch. The Wait Until watches all three segments in parallel and routes the player down whichever branch matches the first segment they enter. If the player is already in more than one segment when they reach this step, the condition listed first wins.

    | Condition                                         | Branch the player goes down |
    | ------------------------------------------------- | --------------------------- |
    | User enters **Bronze approaching Silver** segment | Approaching branch          |
    | User enters **Silver tier** segment               | Catch-up branch             |
    | User enters **Low weekly engagement** segment     | Low engagement branch       |
    | Expiration (21 days with no segment entry)        | Exit the journey            |
  </Step>
</Steps>

##### **Branch 1: Bronze approaching Silver**

Build these nodes on the **Bronze approaching Silver** branch coming out of the fork.

<Steps>
  <Step title="Time Window">
    Every day, 9 AM to 9 PM in the user's timezone, so messages don't deliver overnight.
  </Step>

  <Step title="Push Notification">
    *"Silver is \{\{ 500 | minus: lifetime\_points }} points away. 2x daily bonus. Silver gear. Play tonight. Unlock tomorrow."*
  </Step>

  <Step title="Wait Until">
    One condition plus a **10-day expiration**:

    * User enters **Silver tier** segment → continue to the convergence section below
    * Expiration → Exit the journey
  </Step>
</Steps>

##### **Branch 2: Silver tier (catch-up)**

For players who reach Silver in one jump and skip the approaching segment. For example, a player who earns 500 points in a single burst (a big purchase or daily reward bundle) and crosses straight from Bronze into Silver. Don't add any nodes on this branch. Connect it directly to the Silver tier celebration in-app message in the convergence section below.

##### **Branch 3: Low weekly engagement**

Build these nodes on the **Low weekly engagement** branch coming out of the fork.

<Steps>
  <Step title="Time Window">
    Every day, 9 AM to 9 PM.
  </Step>

  <Step title="Push Notification">
    *"Bronze status is yours. Silver waits at 500 points. You're at \{\{ lifetime\_points }}. Log in today and earn 50 bonus points to start closing the gap."*
  </Step>

  <Step title="Wait Until">
    One condition plus a **10-day expiration**:

    * User enters **Silver tier** segment → continue to the convergence section below
    * Expiration → Exit the journey
  </Step>
</Steps>

##### **Convergence: Silver tier celebration IAM**

All non-exit branches reach this node. After the celebration in-app message, continue to the next tier section.

<Steps>
  <Step title="In-App Message: Silver tier celebration">
    Full screen celebration with the Silver badge and a preview of new perks. Set the trigger to **On app open** and the delivery schedule to **1 week**.

    *"Silver status: achieved. Daily bonus: doubled. Silver collection: yours. Next target: Gold at 2,000 points."*
  </Step>
</Steps>

#### Tier section: Silver → Gold

##### **The fork: multi-condition Wait Until**

<Steps>
  <Step title="Wait Until: multi-condition fork">
    Three segment conditions plus a **21-day expiration**.

    | Condition                                       | Branch the player goes down |
    | ----------------------------------------------- | --------------------------- |
    | User enters **Silver approaching Gold** segment | Approaching branch          |
    | User enters **Gold tier** segment               | Catch-up branch             |
    | User enters **Low weekly engagement** segment   | Low engagement branch       |
    | Expiration (21 days with no segment entry)      | Exit the journey            |
  </Step>
</Steps>

##### **Branch 1: Silver approaching Gold**

Build these nodes on the **Silver approaching Gold** branch.

<Steps>
  <Step title="Time Window">
    Every day, 9 AM to 9 PM in the user's timezone.
  </Step>

  <Step title="Push Notification">
    *"Gold is calling. \{\{ 2000 | minus: lifetime\_points }} points between you and early event access, 3x bonuses and Gold only gear. Close the gap."*
  </Step>

  <Step title="Wait Until">
    One condition plus a **10-day expiration**:

    * User enters **Gold tier** segment → continue to the convergence section below
    * Expiration → Exit the journey
  </Step>
</Steps>

##### **Branch 2: Gold tier (catch-up)**

For players who reach Gold in one jump and skip the approaching segment. Don't add any nodes on this branch. Connect it directly to the Gold tier celebration in-app message in the convergence section below.

##### **Branch 3: Low weekly engagement**

Build these nodes on the **Low weekly engagement** branch.

<Steps>
  <Step title="Time Window">
    Every day, 9 AM to 9 PM.
  </Step>

  <Step title="Push Notification">
    *"Your Silver perks are still active. 2x daily bonuses sitting unclaimed. Log in to grab them and start the climb to Gold."*
  </Step>

  <Step title="Wait Until">
    One condition plus a **10-day expiration**:

    * User enters **Gold tier** segment → continue to the convergence section below
    * Expiration → Exit the journey
  </Step>
</Steps>

##### **Convergence: Gold tier celebration IAM**

All non-exit branches reach this node.

<Steps>
  <Step title="In-App Message: Gold tier celebration">
    Set the trigger to **On app open** and the delivery schedule to **1 week**.

    *"GOLD. Top 10% of all players. 3x daily bonus: active. Gold exclusive gear: unlocked. Early event access: yours. One tier left. Platinum waits at 5,000 points."*
  </Step>
</Steps>

#### Tier section: Gold → Platinum

##### **The fork: multi-condition Wait Until**

<Steps>
  <Step title="Wait Until: multi-condition fork">
    Three segment conditions plus a **21-day expiration**.

    | Condition                                         | Branch the player goes down |
    | ------------------------------------------------- | --------------------------- |
    | User enters **Gold approaching Platinum** segment | Approaching branch          |
    | User enters **Platinum tier** segment             | Catch-up branch             |
    | User enters **Low weekly engagement** segment     | Low engagement branch       |
    | Expiration (21 days with no segment entry)        | Exit the journey            |
  </Step>
</Steps>

##### **Branch 1: Gold approaching Platinum**

Build these nodes on the **Gold approaching Platinum** branch.

<Steps>
  <Step title="Time Window">
    Every day, 9 AM to 9 PM in the user's timezone.
  </Step>

  <Step title="Push Notification">
    *"The summit is in sight. \{\{ 5000 | minus: lifetime\_points }} points to Platinum. VIP shop. 5x bonuses. The badge less than 1% of players will ever wear."*
  </Step>

  <Step title="Wait Until">
    One condition plus a **10-day expiration**:

    * User enters **Platinum tier** segment → continue to the convergence section below
    * Expiration → Exit the journey
  </Step>
</Steps>

##### **Branch 2: Platinum tier (catch-up)**

For players who reach Platinum in one jump and skip the approaching segment. Don't add any nodes on this branch. Connect it directly to the Platinum tier celebration in-app message in the convergence section below.

##### **Branch 3: Low weekly engagement**

Build these nodes on the **Low weekly engagement** branch.

<Steps>
  <Step title="Time Window">
    Every day, 9 AM to 9 PM.
  </Step>

  <Step title="Push Notification">
    *"You're \{\{ 5000 | minus: lifetime\_points }} points from Platinum. Top 1% territory. Don't lose momentum. Log in today and grab 50 bonus points."*
  </Step>

  <Step title="Wait Until">
    One condition plus a **10-day expiration**:

    * User enters **Platinum tier** segment → continue to the convergence section below
    * Expiration → Exit the journey
  </Step>
</Steps>

##### **Convergence: Platinum tier celebration IAM and referral**

All non-exit branches reach these nodes.

<Steps>
  <Step title="In-App Message: Platinum tier celebration">
    Make this the most visually impressive celebration in the game. Set the trigger to **On app open** and the delivery schedule to **1 week**.

    *"PLATINUM. You made it. Top 1% of all players. VIP shop: open. 5x bonuses: banking. Platinum badge: engraved. Welcome to the inner circle."*
  </Step>

  <Step title="Time Window">
    Every day, 9 AM to 9 PM, in front of the referral push.
  </Step>

  <Step title="Push Notification">
    *"Platinum perk: every friend you invite starts with 200 bonus points. You bank a reward too. Share your link. Stack the board."*
  </Step>
</Steps>

The journey ends here. Move Platinum players into a separate VIP journey for ongoing perks and event invitations.

### Success metrics to track

* Tier progression rate (% of players reaching Silver within 30 days)
* Push CTR on tier approaching notifications
* Re-engagement rate after a Low weekly engagement push
* Platinum conversion rate

### Best practices for Case 1

* **Introduce the loyalty program with a clear visual.** An in-app message with a tier map shows players the full progression path and what they earn at each tier. Players are more likely to engage when they know what they're working toward.
* **Let players progress at their own pace.** Wait Until on segment entry reacts the moment a player crosses a threshold or lapses, so messages land when they're relevant instead of on a fixed weekly check. Players who never trigger a condition exit cleanly at the Wait Until expiration.
* **Celebrate every tier transition in-app.** Push notifications announce proximity; in-app messages celebrate achievement. The tier up moment should feel like unlocking a new level in the game itself.
* **Move Platinum players into a separate VIP journey.** The Loyalty Journey's job ends at Platinum. Once a player hits that tier, move them into a separate journey focused on VIP perks, exclusive events and referral programs.

#### Add more channels and message types

Push is the backbone of Case 1, but adding a second channel gives you coverage when push is disabled and richer moments inside the game.

* **Add email as a backup channel for inactivity.** Some players disable push or never grant permission. Place an Email step after the Low weekly engagement push so every inactive player receives the message in at least one channel. The email can carry a tier progress summary with a visual progress bar and a comeback incentive. Push delivers only to subscribed push subscriptions; email reaches everyone with an email subscription.
* **Use in-app messages to deepen tier celebrations.** When an approaching push opens the app, the next session is a high intent moment to surface a full celebration with a rich in-app message. Place the in-app message step after the corresponding push so it triggers on the session the player opens in response.

<CardGroup cols={2}>
  <Card title="Journey messages" icon="paper-plane" href="./journeys-messages">
    Full list of message channels you can add as Journey steps: push, email, SMS and in-app messages.
  </Card>

  <Card title="Journey actions" icon="bolt" href="./journeys-actions">
    Steps that aren't messages: Wait, Time Window, Yes/No Branch, Tag User, Webhook and more.
  </Card>
</CardGroup>

***

## Case 2: Advanced loyalty journey

Same linear tier progression structure as Case 1. Adds webhooks that sync to your backend, tier-locked monetization offers, deeper Liquid personalization and a winback email escalation for players inactive 14+ days.

### How this journey works

Same Bronze → Silver → Gold → Platinum structure as Case 1, plus an enrollment phase up front and richer follow-ups after each tier. After session 6 the player enters at Bronze, sees a personalized welcome in-app message and is initialized via a Tag User node before the tier sections begin.

The journey then runs three tier sections. Each section watches three signals in parallel:

* **Approaching the next tier:** send a points-to-go push, then wait for the tier to be reached
* **Already in the next tier (catch-up):** skip the push and go straight to the celebration in-app message
* **Inactive for 7+ days:** send a re-engagement push. If the player is still inactive at 14 days, escalate to a winback email.

When the player reaches the next tier, all branches converge at a celebration in-app message followed by a webhook to your backend to activate perks. Silver adds a guild prompt for unaffiliated players, Gold adds a tier-locked offer split for buyers vs. non-buyers and Platinum ends with a graduation tag, referral push and Ambassador recognition for players with 3+ referrals.

This case requires custom events, backend webhooks and richer player data. Your backend keeps tags up to date via the OneSignal SDK or API; the journey fires webhooks back to activate perks on each tier transition.

### At a glance

| Phase                             | Step                                                                                                                                      | Channel                                    | Trigger                  |
| --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------ | ------------------------ |
| Phase 1: Enrollment               | Loyalty welcome                                                                                                                           | In-App                                     | Journey entry            |
| Phase 1: Enrollment               | Initialize tier and points                                                                                                                | Tag User                                   | After welcome            |
| Phase 1: Enrollment               | Register enrollment                                                                                                                       | Webhook                                    | After 15-minute Wait     |
| Phase 1: Enrollment               | Push opt-in prompt                                                                                                                        | In-App                                     | After webhook            |
| Phase 2: Bronze → Silver          | Approaching push, re-engagement push, winback email, Silver celebration IAM, perk sync webhook, guild prompt IAM                          | Push + Email + In-App + Webhook            | Wait Until segment entry |
| Phase 3: Silver → Gold            | Approaching push, re-engagement push, winback email, Gold celebration IAM, perk sync webhook, tier-locked offer IAM                       | Push + Email + In-App + Webhook            | Wait Until segment entry |
| Phase 4: Gold → Platinum + finale | Approaching push, re-engagement push, winback email, Platinum celebration IAM, VIP webhook, graduation tag, referral push, Ambassador IAM | Push + Email + In-App + Webhook + Tag User | Wait Until segment entry |

### Journey settings

Configure these settings on the **Settings** tab of the journey before building the steps. See [Journey settings](./journeys-settings) for full reference.

| Setting                                | Value                                                                                                                                                                                                                                                        |
| -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Entry rules: Audience segment**      | Session count > 6 AND `loyalty_tier` exists                                                                                                                                                                                                                  |
| **Entry rules: Future additions only** | Checked. Only players who newly cross session 6 enter. Existing Silver, Gold and Platinum players at launch never enter, which is intentional. The welcome step is meant for new loyalty enrollees.                                                          |
| **Exit rules**                         | None. The journey naturally ends after the Platinum referral and Ambassador recognition steps. Setting an exit rule on the Platinum segment would remove players before they reach the Platinum celebration in-app message.                                  |
| **Re-entry rules**                     | Not enabled. With future additions only checked, players who exit cannot re-enter this journey. Tag Platinum graduates on the way out and use that tag as the entry segment for a separate VIP journey. Use a separate winback journey for expiration exits. |

### Required data

Set the following user properties and events via [SDK calls](./mobile-sdk-setup) or the [server-side API](/reference/create-user).

#### User properties (tags)

| Property             | Type    | Description                                         | How to set                                        |
| -------------------- | ------- | --------------------------------------------------- | ------------------------------------------------- |
| `loyalty_tier`       | String  | Current tier: bronze, silver, gold, platinum        | Server API: Update when points cross a threshold  |
| `lifetime_points`    | Number  | Total loyalty points earned all-time                | Server API: Increment on point earning activities |
| `total_spend`        | Number  | Cumulative in-app purchase amount (cents)           | Server API: Increment on each purchase            |
| `purchase_count`     | Number  | Total number of purchases                           | Server API: Increment on each purchase            |
| `last_purchase_date` | Date    | Unix timestamp of the most recent purchase          | Server API: Update on each purchase               |
| `player_level`       | Number  | Current in-game level                               | Server API or SDK: Update after each level-up     |
| `player_class`       | String  | Character class or play style                       | SDK: Set when player selects their class/hero     |
| `has_guild`          | Boolean | Whether the player is in a guild/clan               | Server API or SDK: Set on guild join event        |
| `friends_count`      | Number  | Number of in-game friends                           | Server API: Update on friend add/remove           |
| `referral_count`     | Number  | Number of friends referred who completed onboarding | Server API: Increment on successful referral      |

#### Events to track

These events power backend logic that updates the tags above. The journey itself reacts to segment entry (which the tag updates trigger) rather than to events directly.

| Event                 | Description                                                                                                                    | How to set                                                       |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------- |
| `points_earned`       | Player earns loyalty points from any activity                                                                                  | Server API: Fire with `amount` and `source` properties           |
| `tier_up`             | Player crosses a tier threshold                                                                                                | Server API: Fire with `new_tier` and `old_tier` properties       |
| `iap_purchase`        | Player completes an in-app purchase                                                                                            | Server API: Fire with `amount`, `item` and `currency` properties |
| `level_up`            | Player reaches a new level                                                                                                     | SDK or Server: Fire with level number as property                |
| `referral_complete`   | A referred friend completes onboarding                                                                                         | Server API: Fire with `referred_user_id`                         |
| `guild_contribution`  | Player contributes to a guild activity                                                                                         | SDK: Fire with `contribution_type` and `amount`                  |
| `event_participation` | Player participates in a limited time event. Used by a separate [event-driven journey](./event-driven-journeys), not this one. | SDK: Fire with `event_id` and `score`                            |

#### Required segments

Wait Until and Yes/No Branch nodes route players based on segment membership. Create these segments before building this journey.

| Segment name              | Filters                                                 |
| ------------------------- | ------------------------------------------------------- |
| Bronze approaching Silver | `loyalty_tier` = `bronze` AND `lifetime_points` > 399   |
| Silver tier               | `loyalty_tier` = `silver`                               |
| Silver approaching Gold   | `loyalty_tier` = `silver` AND `lifetime_points` > 1,599 |
| Gold tier                 | `loyalty_tier` = `gold`                                 |
| Gold approaching Platinum | `loyalty_tier` = `gold` AND `lifetime_points` > 3,999   |
| Platinum tier             | `loyalty_tier` = `platinum`                             |
| 7-day inactive            | `Last session` > 6 days ago                             |
| 14-day inactive           | `Last session` > 13 days ago                            |
| No guild                  | `has_guild` = `false`                                   |
| No purchases              | `purchase_count` = 0                                    |
| 3+ referrals made         | `referral_count` > 2                                    |

<Tip>
  Calculate points and tier changes on your game backend, not in the client app. This prevents players from manipulating their own point totals. The values stored in OneSignal are copies of your backend data, used to target and personalize messages.
</Tip>

### Journey map

This journey runs as a single linear flow: an enrollment chain at the top, three tier sections (Bronze → Silver, Silver → Gold, Gold → Platinum) that follow the same shape as Case 1 and a Platinum finale. Each tier section adds a webhook to sync perks to your backend along with tier-locked monetization or social prompts.

<Note>
  **In-app message timing:** In-app message steps display on the player's next session, not immediately when they reach the step. A new session starts when the app has been out of focus for 30+ seconds and is brought back. If a player is already active when they hit an in-app message step, they won't see it until the next session. Each in-app message also displays only once per player.
</Note>

<Note>
  **Wait Until expirations:** Each multi-condition fork at the start of a tier section uses a **21-day** expiration. The single-condition Wait Untils after each push and email use a **10-day** expiration. All expiration branches **exit the journey**: use a separate winback journey to recover stalled players.
</Note>

#### Phase 1: Loyalty program enrollment

<Steps>
  <Step title="In-App Message: Personalized loyalty welcome">
    Include an interactive tier map showing current progress and upcoming rewards for each tier. Personalize using [Liquid syntax](./using-liquid-syntax). Set the trigger to **On app open** and the delivery schedule to **1 week**.

    *"\{\{ player\_level }} levels down, \{\{ player\_class | default: 'hero' }}. That was the warmup. Elite Rewards is where the grind pays off. Earn points for daily logins, wins, purchases, guild missions. First stop: Silver at 500 points."*
  </Step>

  <Step title="Tag User: Initialize loyalty state">
    Add a [Tag User](./journeys-actions#tag-user) node that sets `loyalty_tier` = `bronze` and `lifetime_points` = `0`. The Tag User node is a journey action that applies tags to the player as they pass through this step. No SDK call from your app is needed here.

    Outside the journey, your app or backend keeps these same tags up to date as players earn points by calling the [mobile SDK `addTags` method](./mobile-sdk-reference#addtag-addtags) or the [Update user API endpoint](/reference/update-user).
  </Step>

  <Step title="Wait: 15 minutes">
    Add a [Wait](./journeys-actions#wait) node set to **15 minutes**. This gives the tags time to update before the Webhook fires, so your backend receives the correct values.
  </Step>

  <Step title="Webhook: Register enrollment in backend">
    Add a [Webhook](./journeys-webhook) step that sends the player's `external_id` and enrollment time to your game backend. The backend can use this to start tracking point earning activities and apply any enrollment bonus.
  </Step>

  <Step title="In-App Message: Push opt-in prompt">
    Include the **Push Permission Prompt** [click action](./iam-click-actions) on the message. The prompt automatically displays only to players whose push subscription isn't subscribed. Set the trigger to **On app open** and the delivery schedule to **1 week**.

    *"Miss a tier up. Miss an event. Miss a bonus. Turn on notifications so you never miss a win."*
  </Step>
</Steps>

#### Phase 2: Bronze → Silver progression

This phase mirrors Case 1's tier section pattern, enriched with a webhook to activate Silver perks on your backend and a guild prompt for unaffiliated players.

The phase opens with a multi-condition Wait Until that forks into four branches. Build the nodes for each branch separately in the journey builder. All non-exit branches converge at the Silver tier celebration in-app message.

##### **The fork: multi-condition Wait Until**

<Steps>
  <Step title="Wait Until: multi-condition fork">
    Three segment conditions plus a **21-day expiration**. Each condition creates its own branch. The Wait Until watches all three segments in parallel and routes the player down whichever branch matches the first segment they enter. If the player is already in more than one segment when they reach this step, the condition listed first wins.

    | Condition                                         | Branch the player goes down |
    | ------------------------------------------------- | --------------------------- |
    | User enters **Bronze approaching Silver** segment | Approaching branch          |
    | User enters **Silver tier** segment               | Catch-up branch             |
    | User enters **7-day inactive** segment            | Inactive branch             |
    | Expiration (21 days with no segment entry)        | Exit the journey            |
  </Step>
</Steps>

##### **Branch 1: Bronze approaching Silver**

Build these nodes on the **Bronze approaching Silver** branch coming out of the fork.

<Steps>
  <Step title="Time Window">
    Every day, 9 AM to 9 PM in the user's timezone.
  </Step>

  <Step title="Push Notification">
    *"Silver is \{\{ 500 | minus: lifetime\_points }} points away. 2x daily bonus. Silver gear. Play tonight. Unlock tomorrow."*
  </Step>

  <Step title="Wait Until">
    One condition plus a **10-day expiration**:

    * User enters **Silver tier** segment → continue to the convergence section below
    * Expiration → Exit the journey
  </Step>
</Steps>

##### **Branch 2: Silver tier (catch-up)**

For players who reach Silver in one jump and skip the approaching segment. For example, a player who earns 500 points in a single burst (a big purchase or daily reward bundle) and crosses straight from Bronze into Silver. Don't add any nodes on this branch. Connect it directly to the Silver tier celebration in-app message in the convergence section below.

##### **Branch 3: 7-day inactive**

Build these nodes on the **7-day inactive** branch coming out of the fork.

<Steps>
  <Step title="Time Window">
    Every day, 9 AM to 9 PM.
  </Step>

  <Step title="Push Notification">
    *"Bronze status is yours, \{\{ player\_class | default: 'hero' }}. Silver waits at 500 points. You're at \{\{ lifetime\_points }}. Log in today and earn 50 bonus points to start closing the gap."*
  </Step>

  <Step title="Wait Until">
    Two conditions plus a **10-day expiration**:

    * User enters **Silver tier** segment → continue to the convergence section below
    * User enters **14-day inactive** segment → continue to the **14-day sub-branch** below
    * Expiration → Exit the journey
  </Step>
</Steps>

On the **14-day sub-branch** of the Wait Until above:

<Steps>
  <Step title="Email">
    Subject: *"Your \{\{ loyalty\_tier | capitalize }} rewards are waiting, \{\{ player\_class | default: 'hero' }}"*. Include a visual progress bar showing current points vs. the next tier threshold, a summary of unclaimed rewards and a limited time comeback bonus code.
  </Step>

  <Step title="Wait Until">
    One condition plus a **10-day expiration**:

    * User enters **Silver tier** segment → continue to the convergence section below
    * Expiration → Exit the journey
  </Step>
</Steps>

##### **Convergence: Silver tier celebration IAM and follow-ups**

All non-exit branches reach these nodes.

<Steps>
  <Step title="In-App Message: Silver tier celebration">
    Full screen celebration with the Silver badge animation. List all newly unlocked perks. Set the trigger to **On app open** and the delivery schedule to **1 week**.

    *"SILVER UNLOCKED. 2x daily bonus: active. Silver cosmetics: yours. You just joined the top 40% of players. Gold is calling at 2,000 points."*
  </Step>

  <Step title="Webhook">
    Send the player's `external_id`, tier and point total to your backend. Activate Silver perks: 2x daily bonus, cosmetic unlocks, priority matchmaking.
  </Step>

  <Step title="Yes/No Branch">
    Condition: user is in the **No guild** segment.

    * **Yes:** In-App Message: *"Silver members earn 2x points on guild missions. Join a guild. Climb faster. Gold's waiting."*
    * **No:** Skip to Phase 3.
  </Step>
</Steps>

#### Phase 3: Silver → Gold progression

Same shape as Phase 2 with Silver to Gold segments, plus a tier-locked monetization offer after the Gold celebration in-app message.

##### **The fork: multi-condition Wait Until**

<Steps>
  <Step title="Wait Until: multi-condition fork">
    Three segment conditions plus a **21-day expiration**.

    | Condition                                       | Branch the player goes down |
    | ----------------------------------------------- | --------------------------- |
    | User enters **Silver approaching Gold** segment | Approaching branch          |
    | User enters **Gold tier** segment               | Catch-up branch             |
    | User enters **7-day inactive** segment          | Inactive branch             |
    | Expiration (21 days with no segment entry)      | Exit the journey            |
  </Step>
</Steps>

##### **Branch 1: Silver approaching Gold**

Build these nodes on the **Silver approaching Gold** branch coming out of the fork.

<Steps>
  <Step title="Time Window">
    Every day, 9 AM to 9 PM in the user's timezone.
  </Step>

  <Step title="Push Notification">
    *"Gold is calling. \{\{ 2000 | minus: lifetime\_points }} points between you and early event access, 3x bonuses and Gold only gear. Close the gap."*
  </Step>

  <Step title="Wait Until">
    One condition plus a **10-day expiration**:

    * User enters **Gold tier** segment → continue to the convergence section below
    * Expiration → Exit the journey
  </Step>
</Steps>

##### **Branch 2: Gold tier (catch-up)**

For players who reach Gold in one jump and skip the approaching segment. Don't add any nodes on this branch. Connect it directly to the Gold tier celebration in-app message in the convergence section below.

##### **Branch 3: 7-day inactive**

Build these nodes on the **7-day inactive** branch coming out of the fork.

<Steps>
  <Step title="Time Window">
    Every day, 9 AM to 9 PM.
  </Step>

  <Step title="Push Notification">
    *"Your Silver perks are still active, \{\{ player\_class | default: 'hero' }}. 2x daily bonuses sitting unclaimed. Log in to grab them and start the climb to Gold."*
  </Step>

  <Step title="Wait Until">
    Two conditions plus a **10-day expiration**:

    * User enters **Gold tier** segment → continue to the convergence section below
    * User enters **14-day inactive** segment → continue to the **14-day sub-branch** below
    * Expiration → Exit the journey
  </Step>
</Steps>

On the **14-day sub-branch** of the Wait Until above:

<Steps>
  <Step title="Email">
    Use the same template as Phase 2's winback email.
  </Step>

  <Step title="Wait Until">
    One condition plus a **10-day expiration**:

    * User enters **Gold tier** segment → continue to the convergence section below
    * Expiration → Exit the journey
  </Step>
</Steps>

##### **Convergence: Gold tier celebration IAM and follow-ups**

All non-exit branches reach these nodes.

<Steps>
  <Step title="In-App Message: Gold tier celebration">
    Set the trigger to **On app open** and the delivery schedule to **1 week**.

    *"GOLD. Top 10% of all players. Gold exclusive gear: unlocked. 3x daily bonus: active. Early event access: yours. One tier left. Platinum waits at 5,000 points."*
  </Step>

  <Step title="Webhook">
    Send the player's `external_id`, tier and point total to your backend. Activate Gold perks.
  </Step>

  <Step title="Yes/No Branch">
    Condition: user is in the **No purchases** segment.

    * **Yes:** In-App Message: *"Gold only drop. The \{\{ player\_class | default: 'hero' }} Starter Pack. 70% off. Locked to Gold tier and above. Your loyalty earned you this price."*
    * **No:** In-App Message: *"Gold buyers only: Premium Season Pass at 30% off. Every Gold exclusive drop this season, locked in for less."*
  </Step>
</Steps>

#### Phase 4: Gold → Platinum progression and Platinum finale

Same shape as Phase 3 with Gold to Platinum segments. Ends with a Platinum referral push and Ambassador recognition for high referral players.

##### **The fork: multi-condition Wait Until**

<Steps>
  <Step title="Wait Until: multi-condition fork">
    Three segment conditions plus a **21-day expiration**.

    | Condition                                         | Branch the player goes down |
    | ------------------------------------------------- | --------------------------- |
    | User enters **Gold approaching Platinum** segment | Approaching branch          |
    | User enters **Platinum tier** segment             | Catch-up branch             |
    | User enters **7-day inactive** segment            | Inactive branch             |
    | Expiration (21 days with no segment entry)        | Exit the journey            |
  </Step>
</Steps>

##### **Branch 1: Gold approaching Platinum**

Build these nodes on the **Gold approaching Platinum** branch coming out of the fork.

<Steps>
  <Step title="Time Window">
    Every day, 9 AM to 9 PM in the user's timezone.
  </Step>

  <Step title="Push Notification">
    *"The summit is in sight. \{\{ 5000 | minus: lifetime\_points }} points to Platinum. VIP shop. 5x bonuses. The badge less than 1% of players will ever wear."*
  </Step>

  <Step title="Wait Until">
    One condition plus a **10-day expiration**:

    * User enters **Platinum tier** segment → continue to the convergence section below
    * Expiration → Exit the journey
  </Step>
</Steps>

##### **Branch 2: Platinum tier (catch-up)**

For players who reach Platinum in one jump and skip the approaching segment. Don't add any nodes on this branch. Connect it directly to the Platinum tier celebration in-app message in the convergence section below.

##### **Branch 3: 7-day inactive**

Build these nodes on the **7-day inactive** branch coming out of the fork.

<Steps>
  <Step title="Time Window">
    Every day, 9 AM to 9 PM.
  </Step>

  <Step title="Push Notification">
    *"You're \{\{ 5000 | minus: lifetime\_points }} points from Platinum, \{\{ player\_class | default: 'hero' }}. Top 1% territory. Don't lose momentum. Log in today and grab 50 bonus points."*
  </Step>

  <Step title="Wait Until">
    Two conditions plus a **10-day expiration**:

    * User enters **Platinum tier** segment → continue to the convergence section below
    * User enters **14-day inactive** segment → continue to the **14-day sub-branch** below
    * Expiration → Exit the journey
  </Step>
</Steps>

On the **14-day sub-branch** of the Wait Until above:

<Steps>
  <Step title="Email">
    Use the same template as Phase 2's winback email.
  </Step>

  <Step title="Wait Until">
    One condition plus a **10-day expiration**:

    * User enters **Platinum tier** segment → continue to the convergence section below
    * Expiration → Exit the journey
  </Step>
</Steps>

##### **Convergence: Platinum celebration IAM, VIP handoff and referral**

All non-exit branches reach these nodes. The journey ends after the Ambassador check.

<Steps>
  <Step title="In-App Message: Platinum tier celebration">
    Make this the most visually spectacular celebration in the game: a unique animation, exclusive sound effect, or a personalized message from the development team. Set the trigger to **On app open** and the delivery schedule to **1 week**.

    *"PLATINUM. You made it. Top 1% of all players in \[Game Name]. Platinum badge: engraved. VIP shop: open. 5x bonuses: banking. Direct developer channel: yours. Welcome to the inner circle."*
  </Step>

  <Step title="Webhook">
    Send the player's `external_id` and full loyalty profile to your backend. Activate all Platinum perks and flag this player for VIP handling in customer support, community management and future beta invitations.
  </Step>

  <Step title="Tag User">
    Set a tag like `loyalty_program` = `platinum_graduate`. Use this tag as the entry segment for a separate VIP journey, so Platinum players continue receiving VIP tier messaging after this journey ends.
  </Step>

  <Step title="Time Window">
    Every day, 9 AM to 9 PM, in front of the referral push.
  </Step>

  <Step title="Push Notification">
    *"Bring your crew to Platinum. Every friend you invite starts with 200 bonus points. You bank 500 per invite. Share the link. Stack the board."*
  </Step>

  <Step title="Yes/No Branch">
    Condition: user is in the **3+ referrals made** segment.

    * **Yes:** In-App Message: *"You've pulled \{\{ referral\_count }} friends into \[Game Name]. That's Ambassador level. Badge earned. 1,000 bonus points deposited."*
    * **No:** Skip. The journey ends here.
  </Step>
</Steps>

#### Handling tier decay

If your loyalty program includes tier decay, handle it with care:

1. **Warning push (7 days before deadline):** *"Your \{\{ loyalty\_tier | capitalize }} status expires in 7 days. Bank \{\{ points\_needed }} more points this month to keep your perks."*
2. **Grace period (3 days):** Give a 3-day grace period before downgrading. Send a final push: *"Last chance. Your \{\{ loyalty\_tier | capitalize }} perks expire tomorrow. Log in to save your tier."*
3. **Downgrade with dignity:** *"Your tier has been adjusted to \{\{ new\_tier | capitalize }}. Progress isn't lost. Earn \{\{ points\_to\_restore }} points to restore your \{\{ old\_tier | capitalize }} status."*

<Note>
  Consider using a "highest tier achieved" badge that persists even if the active tier drops. Tier decay creates urgency but can frustrate loyal players who take a break. A permanent badge honors their history.
</Note>

### Success metrics to track

* Average days to reach each tier
* Re-engagement rate after 7-day inactivity push
* First purchase rate at Gold tier
* Winback email conversion rate at 14-day inactivity
* Referral conversion rate from Platinum players

### Best practices for Case 2

* **Add a Webhook after every tier celebration in-app message.** OneSignal doesn't unlock perks. Your game does. A Webhook step notifies your game server the moment a player reaches a new tier, so their rewards activate right away instead of waiting for the next sync.
* **Lock offers to specific tiers.** A Gold only deal converts better than a random promotion because players perceive it as earned. Non-buyers at Gold need a reason to make their first purchase; existing buyers need a value upgrade.
* **Handle tier decay with empathy.** Warn early, offer a grace period and frame any downgrade as temporary. A "highest tier achieved" badge preserves the player's sense of accomplishment even during inactive periods.
* **Celebrate every tier transition in-app.** The tier up moment should feel like unlocking a new level in the game itself. Push announces proximity; the in-app message delivers the reward.
* **Hand off Platinum graduates to a VIP journey.** This journey ends at Platinum. Tag Platinum players on the way out and use that tag as the entry segment for a separate VIP journey focused on exclusive events, beta invitations and referral programs.

#### Add more channels and message types

The rich data in Case 2 makes it possible to expand beyond push and in-app messages and add channel moments tied to specific player behavior.

* **Add SMS for high value moments.** Once a player crosses a value threshold like first purchase or Platinum tier, SMS becomes a high attention channel for time sensitive offers: a limited time event invite, a flash sale on a class matched pack, or an exclusive Platinum drop. Reserve SMS for VIP tier audiences to keep send volume low and engagement high.
* **Extend email beyond winback.** Email isn't only a re-engagement fallback. Use Email steps after tier celebration in-app messages and on a recurring schedule (Days 30, 60, 90 of loyalty program membership). Deliver class specific tips, loyalty program recaps and exclusive member content for players who prefer less frequent in-app messaging.
* **Layer on a separate event-driven journey for limited time events.** Use the `event_participation` event as the entry trigger for a dedicated [event-driven journey](./event-driven-journeys) that recognizes participation, rewards points and gates exclusive challenges to Gold and Platinum players. Keeping it separate avoids tangling event responses into the linear tier flow.

<CardGroup cols={2}>
  <Card title="Custom events" icon="bolt" href="./custom-events">
    The behavioral foundation of Case 2. Track purchases, tier changes, daily sessions and more.
  </Card>

  <Card title="Journey webhooks" icon="webhook" href="./journeys-webhook">
    Sync tier state, perks and loyalty data to your game backend in real time.
  </Card>
</CardGroup>

***

## Case 1 vs. Case 2 at a glance

|                     | Case 1: Basic                                                                                     | Case 2: Advanced                                                                                                                                                                                                         |
| ------------------- | ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Data required**   | Session Count + 2 tags (`loyalty_tier`, `lifetime_points`)                                        | 10+ tags + 7+ events                                                                                                                                                                                                     |
| **Setup effort**    | Low. Your app or backend sets two tags via the OneSignal SDK or API. Fixed thresholds.            | High. Your backend calculates points, tracks events and updates tags                                                                                                                                                     |
| **Tier tracking**   | Wait Until on segment entry, driven by tag changes                                                | Wait Until on segment entry, driven by backend tag updates and synced via webhooks                                                                                                                                       |
| **Push logic**      | Segment-driven: push fires when the player enters an approaching, tier, or low engagement segment | Same segment-driven structure, with richer Liquid personalization and tier-locked offers layered in                                                                                                                      |
| **Journey actions** | [Wait Until](./journeys-actions#wait-until) + [Time Window](./journeys-actions#time-window)       | [Wait Until](./journeys-actions#wait-until) + [Time Window](./journeys-actions#time-window) + [Yes/No Branch](./journeys-actions#yesno-branch) + [Tag User](./journeys-actions#tag-user) + [Webhook](./journeys-webhook) |
| **Personalization** | Tier name and point count only                                                                    | Class, level, spend history, guild status, play time, referral count, purchase behavior                                                                                                                                  |
| **Monetization**    | n/a                                                                                               | Tier-locked offers after the Gold celebration IAM, buyer/non-buyer segmentation                                                                                                                                          |
| **Social features** | n/a                                                                                               | Guild prompt at Silver, referral push at Platinum, Ambassador recognition for high referral players                                                                                                                      |
| **Re-engagement**   | Single 7-day inactivity branch in each tier section                                               | Two-step escalation per tier section: 7-day push, then email winback if 14-day inactive                                                                                                                                  |
| **Tier decay**      | n/a                                                                                               | Warning push, 3-day grace period, downgrade message with points needed to restore                                                                                                                                        |
| **Backend sync**    | One way. Your app or backend writes tags to OneSignal via SDK/API; OneSignal doesn't push back    | Webhook fires after each tier celebration IAM to activate perks on your backend                                                                                                                                          |
| **Best for**        | Small games, solo developers, MVPs, early loyalty experiments                                     | Established games, growth teams, games with in-app purchases and social features                                                                                                                                         |

***

## Getting started

Start with Case 1 if you're setting up a loyalty program for the first time. It goes live with minimal setup and covers the core tier progression window without requiring event instrumentation or backend webhooks. As your data infrastructure matures, layer in Case 2 elements progressively. You don't need all 10 tags and 7 events on day one. Even adding webhooks to sync Silver, Gold and Platinum perks to your backend meaningfully strengthens the loyalty experience.

The Loyalty Journey picks up where the Welcome Journey ends. By Day 7+ players have established a habit. From there the journey rewards that habit, moves players through tiers and turns the most engaged into advocates.

***

## Track performance

<Card title="Goals" icon="bullseye" href="./goals">
  Set a target metric on your journey and track progress in real time on the Journey report.
</Card>
