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

# Promotions

> Smart app review prompts with PlaytoliaPromotion

<Frame>
  <img src="https://mintcdn.com/byte-caa21824/kHzHZiv95UwoIUXD/images/feature_promotions_ios_demo.PNG?fit=max&auto=format&n=kHzHZiv95UwoIUXD&q=85&s=b2a2b4a66037d25683e99cef8a371926" alt="Feature Promotions Ios Demo" width="2622" height="1206" data-path="images/feature_promotions_ios_demo.PNG" />
</Frame>

`PlaytoliaPromotion` manages in-app review requests using platform-native review dialogs (Google In-App Review on Android, `SKStoreReviewController` on iOS). It tracks session counts, install age, and cooldown periods to avoid annoying players.

### How it works

The SDK automatically tracks sessions and timestamps. When you call a review method, it checks eligibility rules before showing the native dialog. If the player isn't eligible, nothing happens — no error, no dialog.

### Configuring review trigger rules

Set thresholds that control when reviews can be requested:

```c# theme={null}
PlaytoliaPromotion.ConfigureReview(
    minSessions: 5,            // player must have opened the app at least 5 times
    minDaysSinceInstall: 7,    // at least 7 days since first session
    maxRequestsPerYear: 3,     // no more than 3 review prompts per year
    cooldownDays: 120           // at least 120 days between prompts
);
```

<Info>
  Call `ConfigureReview` early — e.g. in your initialization script. The defaults (5 sessions, 7 days, 3/year, 120-day cooldown) apply if you don't call it.
</Info>

### Requesting a review

```c# theme={null}
// Standard request — checks all eligibility rules
PlaytoliaPromotion.RequestReview();

// After a positive event (e.g. winning a match, completing a level)
// Skips session count and days-since-install checks, but still respects
// cooldown, max-per-year, and never-ask-again
PlaytoliaPromotion.RequestReviewAfterPositiveEvent();
```

Both methods accept an optional `force` parameter that bypasses **all** eligibility checks:

```c# theme={null}
// Skip all SDK-side checks and go straight to the native dialog
PlaytoliaPromotion.RequestReview(force: true);
PlaytoliaPromotion.RequestReviewAfterPositiveEvent(force: true);
```

<Warning>
  Both Google and Apple may silently suppress the review dialog even when forcing. This is platform-controlled and cannot be overridden. Use `force` for debugging or special cases, not to spam players.
</Warning>

### Checking eligibility

```c# theme={null}
if (PlaytoliaPromotion.CanRequestReview())
{
    // Player is eligible for a review prompt
}
```

### "Never ask again" opt-out

Let players permanently opt out of review prompts:

```c# theme={null}
PlaytoliaPromotion.SetNeverAskAgain(true);
```

### Reading state

```c# theme={null}
var state = PlaytoliaPromotion.GetState();
// state.SessionCount              — total app opens
// state.FirstSessionTimestamp     — epoch millis of first session
// state.LastReviewRequestTimestamp — epoch millis of last review prompt
// state.ReviewRequestCount        — total review prompts shown
// state.NeverAskAgain             — player opted out
```

### Listening to changes

```c# theme={null}
void Start()    => PlaytoliaPromotion.AddListener(OnPromotionChanged);
void OnDestroy() => PlaytoliaPromotion.RemoveListener(OnPromotionChanged);

void OnPromotionChanged()
{
    var state = PlaytoliaPromotion.GetState();
    // update UI or check eligibility
}
```

<CardGroup cols={2}>
  <Card icon="bell" href="/for-unity/push-notifications" title="Push Notifications">
    Notifications setup
  </Card>

  <Card icon="code" href="/sdk-reference/promotions" title="SDK Reference">
    PlaytoliaPromotion reference
  </Card>
</CardGroup>
