# Personalize content

**URL:** https://heroiclabs.com/docs/satori/concepts/remote-configuration/personalize-content/
**Summary:** Audiences define who receives content. Feature flags define what they receive. Together, they let you customize the player experience for any segment, at any time, without a new build or code deployment.
**Keywords:** personalize content, feature flag variants, audience targeting, discount shop, DLC unlock, player progression gate, welcome back screen, satori personalization
**Categories:** satori, remote-configuration

---


# Personalize content

Audiences define who receives content. Feature flags define what they receive. Together, they let you customise the player experience for any segment, at any time, without a new build or code deployment.

This guide walks through four common personalization patterns. Each one follows the same approach: create an audience, create a feature flag, add a variant that targets that audience, and read the flag from your game client. For background on how flags and audiences work, see [Understand feature flags](/satori/concepts/remote-configuration/understand-feature-flags/) and [Understand audiences](/satori/concepts/segmentation/understand-audiences/).

## Offer veteran players a discounted shop during an event

Create a personalized cash shop where veteran players receive a discount on selected items during a live event.

### Create the feature flag

1. Go to **Feature Flags** and select **New Feature Flag**.
2. For **Name**, enter `storeConfig`.
3. For **Value**, enter a JSON object representing your default shop catalog:

```json
{
  "items": [
    { "id": "sword_01", "price": 500 },
    { "id": "shield_01", "price": 300 },
    { "id": "potion_01", "price": 100 }
  ]
}
```

4. Select **Create**.

This default value is what every player sees unless a variant or override applies.

### Create the audience

1. Go to **Audiences** and select **Create New Audience**.
2. For **Name**, enter `Veteran-Players`.
3. Add the following filter:

```text
PropertiesComputed("sessionStartCount", 0) >= 100
```

4. Select **Create**.

### Create a live event with a flag override

Rather than editing the flag directly, attach the discounted catalog to a live event. This keeps your default shop intact and limits the discount to a defined window. To learn more, see [Live events](/satori/concepts/live-events/).

1. Go to **Live Events** and select **Create Live Event**.
2. For **Name**, enter `VeteranDiscountWeek`. Set **Audiences** to `Veteran-Players`.
3. Set the **Duration** to one week.
4. In the **Feature Flags** section, search for `storeConfig` and select **Add Flag**.
5. Enter the discounted catalog as the override value:

```json
{
  "items": [
    { "id": "sword_01", "price": 350 },
    { "id": "shield_01", "price": 200 },
    { "id": "potion_01", "price": 75 }
  ]
}
```

6. Optionally, add a **Monitor Metric** such as `purchaseComplete` to track revenue during the event.

While the live event is active, veteran players receive the discounted catalog. When the event ends, they return to the default shop automatically.

### Read the flag from the client

Your game client reads `storeConfig` the same way regardless of whether the player is receiving the default, a variant, or a live event override. Satori resolves the correct value server-side.

```csharp
var flag = await client.GetFlagAsync(session, "storeConfig", "{}");
// Parse flag.Value as your shop catalog and render accordingly
```

## Unlock exclusive DLC for paying players

Provide additional downloadable content to players who have made at least one purchase, using the built-in All-Spenders audience.

1. Go to **Feature Flags** and create a flag named `availableDlc`.
2. Set the default value to an empty array: `[]`.
3. Create a variant with the DLC content:

```json
["https://your-cdn.com/bundles/expansion-pack-01", "https://your-cdn.com/bundles/bonus-skins-01"]
```

4. Set the variant's **Audience** to `All-Spenders` (a built-in Satori audience).

Players who have completed at least one purchase receive the DLC URIs. Your client reads the flag, checks the array, and downloads any bundles the player doesn't already have. Non-spenders receive the empty array and see no additional content.

## Gate a feature behind player progression

Restrict access to a game mode until players have reached a progression milestone.

### Set up the custom property

Report progression to Satori from your game client. Update a custom property called `playerProgress` as the player advances. This property represents a completion percentage (0 to 100).

```csharp
await client.UpdatePropertiesAsync(session,
    new Dictionary<string, string>(),                               // default properties
    new Dictionary<string, string> { { "playerProgress", "75" } }  // custom properties
);
```

### Create the audience

1. Go to **Audiences** and create an audience named `Significant-Progress`.
2. Add the following filter:

```text
PropertiesCustom("playerProgress", "0") >= "75"
```

### Create the feature flag

1. Create a flag named `deathmatchMode` with a default value of `false`.
2. Create a variant with a value of `true` and set its **Audience** to `Significant-Progress`.

Players who have reached 75% or more progression see `deathmatchMode` resolve to `true`. Your client checks this flag and enables or hides the game mode accordingly.

## Show returning players a welcome back screen

Greet players who haven't played in a long time with a personalized re-entry experience.

### Create the audience

1. Go to **Audiences** and create an audience named `Returning-After-6-Months`.
2. Add the following filter:

```text
Now() - PropertiesComputed("sessionStartSeenLast", 0) > Duration("180d")
```

This targets players whose last session was more than six months ago.

### Create the feature flag

1. Create a flag named `showWelcomeBackScreen` with a default value of `false`.
2. Create a variant with a value of `true` and set its **Audience** to `Returning-After-6-Months`.

### Personalize the message

For an extra touch, read the player's `sessionStartSeenLast` computed property from the client to show how long they've been away:

```csharp
var properties = await client.ListPropertiesAsync(session);
// Use sessionStartSeenLast to display: "Welcome back! It's been 7 months."
```

Once the player starts a new session and Satori recomputes their properties, they'll fall out of the `Returning-After-6-Months` audience and won't see the welcome screen again.

## What else you can personalize

These four examples follow the same pattern: an audience defines the segment, a feature flag delivers the content, and optionally a live event or experiment controls the timing. Apply this pattern to regional pricing, seasonal UI themes, tutorial flows for new players, ad frequency for different engagement tiers, or any other content that benefits from segmentation.

For time-bound personalization, attach your flag to a live event. For data-driven testing of which personalization performs better, attach it to an experiment.
