# Personalized Content

**URL:** https://heroiclabs.com/docs/satori/guides/personalization/
**Summary:** A guide for creating personalized content with Satori
**Keywords:** personalized content, satori, personalization
**Categories:** satori, personalization, guides

---


# Personalized Content

In this guide you will learn how to create personalized content for your game using Satori feature flags, audiences and live events. 

To achieve this you will do the following:

* [Create a feature flag](#create-a-feature-flag)
* [Create a metric](#create-a-metric)
* [Create a live event](#create-a-live-event)
* [Access personalized content on the client](#accessing-personalized-content)

This example focuses on creating a personalized cash shop where veteran players will receive a discount on some items for a period of time.

However, this combination of [feature flags](../../concepts/remote-configuration/), [audiences](../../concepts/segmentation/) and [live events](../../concepts/live-events/) (or [experiments](../../concepts/experiments/)) can be used by non-developers to completely customize the player experience in different manners, at any time, without the need for extra development effort or a new build and release of the game.

## Create a feature flag

Create a feature flag that defines your global cash shop as a JSON string. 

{{< note "important" "Data source and format" >}}
The following JSON schema and data serves only as an example. You can define your game data in any format you like and source it from where suits your needs best. This example uses a JSON string and grabs the data from a Satori feature flag to showcase the power of feature flags and how they allow you to personalize your game's data for targeted audiences on the fly.
{{< / note >}}

1. Navigate to **Feature Flags** in the Satori console.
2. Click **New Feature Flag**.
3. For **Flag Name** enter: `storeConfig`.
4. For **Default Value** enter:

```json
{
  "items": {
    "coinsPack1": "sku-iap-usd-4-99",
    "coinsPack2": "sku-iap-usd-9-99",
    "booster1": "sku-iap-usd-4-99"
  }
}
```

## Create a metric

Create a metric to track total player spend during the live event using the built in `purchaseComplete` event.

1. Navigate to **Metrics**.
2. Click **New Metric**.
3. For **Name** enter: `purchaseComplete` and give an appropriate **Description**.
4. For **Type** change it to: `Revenue`.
5. Keep **Order** as `High`.

This metric will allow you to track total player spend during the live event.

## Create a live event

Create a live event that will run for one week and will offer Veteran Players a discount on the store.

1. Navigate to **Live Events**.
2. Click **Create Live Event**.
3. For **Name** enter: `VeteranDiscountWeek` and give it an appropriate **Description**.
4. For **Value** enter: `N/A`.
5. For **Audiences** choose: `Veteran-Players`.
6. For **Monitor Metrics** choose: `purchaseComplete`.
7. Give an appropriate **Start Time** and **End Time**
8. For **Duration** enter: `604800` (1 week in seconds).
9. In the **Feature Flags** section search for the `storeConfig` feature flag and click **Add Flag**.
10. Give the flag a new **Value** to provide discounted SKU codes:

```json
{
  "items": {
    "coinsPack1": "sku-iap-usd-1-99",
    "coinsPack2": "sku-iap-usd-4-99",
    "booster1": "sku-iap-usd-1-99"
  }
}
```

11. Click **Create**.

## Accessing personalized content

Since the cash shop configuration exists as a feature flag the user can access it by calling:

```csharp
var flag = await client.GetFlagAsync(session, "storeConfig");
Debug.Log(flag.Value);
```

Doing so will retrieve the flag's value for the authenticated identity, typically this will be it's default value. However, if the user is part of the `Veteran-Players` audience, they will automatically receive the updated value for the flag as configured in the `VeteranDiscountWeek` Live Event (provided it is currently active as per your Start/End dates). This means veteran players can start receiving discounts on cash shop items as soon as the live event is active.

## Other use-cases

There are countless ways that Satori can be used to personalize content for your players using its sophisticated suite of features. Some of these are explored below.

### Personalized DLC

By combining [feature flags](../../concepts/remote-configuration/) and [audiences](../../concepts/segmentation/) it is possible to provide players with additional downloadable content for your game if they meet a certain criteria.

For example, you could create an `availableDlc` feature flag and then create a [feature flag variant](../../concepts/remote-configuration/#editing-feature-flags) that targets the built-in `All-Spenders` audience to provide additional DLC content to paying players.

In this example, the feature flag could contain an array of URIs that point to downloadable resource bundles for your game. These could be used in conjunction with asset systems such as [Unity's Addressables](../../../nakama/guides/deployment/asset-management/).

**Default flag value:**
```json
{
  "availableDlc": [
    "https://dlc.example.com/character-pack-1.gz",
    "https://dlc.example.com/character-pack-2.gz"
  ]
}
```

**All Spenders flag value:**
```json
{
  "availableDlc": [
    "https://dlc.example.com/character-pack-1.gz",
    "https://dlc.example.com/character-pack-2.gz",
    "https://dlc.example.com/epilogue-chapter.gz",
    "https://dlc.example.com/bonus-soundtrack.gz"
  ]
}
```

### Progression based feature access

You could provide access to features in your game only to players who have made a specific amount of progress.

To achieve this you would create a [custom property](../../concepts/segmentation/understand-player-properties/#creating-custom-properties) such as `playerProgress` which you would update from the client as they progress through your game. This property could represent a value that indicates percent completion.

You would then create an audience with an appropriate filter, such as the one below which checks that the player's progress is greater than or equal to 75%, and give it a name like `Significant-Progress`.

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

Then create a [feature flag](../../concepts/remote-configuration/) for your feature, for example `deathmatchMode` and give it a default value of `false` so that all existing players do not currently have access.

You can then create a feature flag variant for `Significant-Progress` players where the value of the flag is now `true`.

You would then use the value of this feature flag in your game client to determine whether or not the player should have access to that particular feature.

### Welcome back screen

Some games operate in seasons and you may find that players sometimes churn out of your game once the season is over and then return much later and may have missed a significant portion of content.

It's often a nice touch to offer these players a "Welcome back" screen that can tell them about all the content or features they may have missed while they were away.

Using [feature flags](../../concepts/remote-configuration/) and [audiences](../../concepts/segmentation/) you could create an audience for players who have not been seen for more than 6 months using the filter:

```
Now() - updateTime >= Duration("6m")
```

You can then create a feature flag called `showWelcomeBackScreen` with a default value of `false` and create a variant value of `true` that targets this audience.

In the client, you can check the value of the `showWelcomeBackScreen` flag for the player and if it is true, present them with the appropriate information.

For an extra personal touch you could get the value of the player's `seenLast` [computed property](../../concepts/segmentation/understand-player-properties/#computed-properties) which has a value that indicates the UNIX timestamp of the time the player was last seen in your game. You can then use this to determine exactly what content the player may have missed and show them a highly personalized catch up screen.