# Presenting Paywalls

Register Superwall placements from Unity C# scripts.

Placements are the main way to present paywalls. [Create a placement](/docs/dashboard/dashboard-campaigns/campaigns-placements#adding-a-placement)
in the Superwall dashboard, add it to a campaign, then register the same placement name from your
Unity code.

Register a Placement [#register-a-placement]

Call `RegisterPlacement` when the user tries to access a feature that may be paywalled.

```csharp C#
using System.Collections.Generic;
using UnityEngine;
using Superwall;

public sealed class LevelGate : MonoBehaviour
{
    [SerializeField] private int levelNumber = 3;

    public void OnStartLevelPressed()
    {
        var handler = new PaywallPresentationHandler
        {
            OnPresent = info =>
            {
                Debug.Log($"Paywall presented: {info.Name}");
            },
            OnDismiss = (info, result) =>
            {
                Debug.Log($"Paywall dismissed: {result.Type}");
            },
            OnError = error =>
            {
                Debug.LogError($"Paywall error: {error}");
            },
            OnSkip = reason =>
            {
                Debug.Log($"Paywall skipped: {reason}");
            }
        };

        Superwall.Shared.RegisterPlacement(
            "start_level",
            parameters: new Dictionary<string, object>
            {
                { "level", levelNumber },
                { "source", "level_select" }
            },
            handler: handler,
            feature: StartLevel
        );
    }

    private void StartLevel()
    {
        Debug.Log("Feature unlocked");
        // Load the premium level, award the item, start the mode, etc.
    }
}
```

When the `feature` Callback Runs [#when-the-feature-callback-runs]

Superwall decides whether the placement should show a paywall based on the campaign configuration
downloaded at app start.

The `feature` callback runs when the user has access:

* The user already has an active subscription.
* The user purchases or restores from a gated paywall.
* The paywall is configured as non-gated.
* No paywall is configured for the placement.

If a gated paywall is dismissed without a purchase or restore, the `feature` callback does not run.

Check the Presentation Result [#check-the-presentation-result]

Use `GetPresentationResult` when you need to inspect what Superwall would do for a placement without
presenting it. In games, this is useful for keeping unlockable UI in sync with your dashboard
configuration, such as showing lock icons on levels, dimming premium cosmetics, or adding an upgrade
badge to a game mode before the player taps it.

```csharp C#
Superwall.Shared.GetPresentationResult("start_level", completion: result =>
{
    switch (result.Type)
    {
        case PresentationResult.ResultType.Paywall:
            Debug.Log("A paywall is available for this placement.");
            break;
        case PresentationResult.ResultType.Holdout:
            Debug.Log("The user is in a holdout.");
            break;
        case PresentationResult.ResultType.NoAudienceMatch:
            Debug.Log("No audience matched.");
            break;
        case PresentationResult.ResultType.PlacementNotFound:
            Debug.LogWarning("Placement was not found in the dashboard.");
            break;
    }
});
```

> **Tip**

`GetPresentationResult` uses the same campaign and audience logic that would decide whether a
paywall appears. Use it to render upsell UI ahead of time, then call `RegisterPlacement` when the
player actually tries to unlock or start the gated content.