# .NET experiments installation - Docs

1.  1

    ## Install PostHog .NET SDK

    Required

    The `PostHog` package supports any .NET platform that targets .NET Standard 2.1 or .NET 8+, including MAUI, Blazor, and console applications. The `PostHog.AspNetCore` package provides additional conveniences for ASP.NET Core applications such as streamlined registration, request-scoped caching, and integration with [.NET Feature Management](https://learn.microsoft.com/en-us/azure/azure-app-configuration/feature-management-dotnet-reference).

    > **Note:** We actively test with ASP.NET Core. Other platforms should work but haven't been specifically tested. If you encounter issues, please [report them on GitHub](https://github.com/PostHog/posthog-dotnet/issues).

    > **Not supported:** Classic UWP (requires .NET Standard 2.0 only). Microsoft has [deprecated UWP](https://learn.microsoft.com/en-us/windows/apps/windows-app-sdk/migrate-to-windows-app-sdk/migrate-to-windows-app-sdk-ovw) in favor of the Windows App SDK. For Unity projects, see our dedicated [Unity SDK](/docs/libraries/unity.md) (currently in beta).

    Terminal

    PostHog AI

    ```bash
    dotnet add package PostHog.AspNetCore
    ```

    In your `Program.cs` (or `Startup.cs` for ASP.NET Core 2.x) file, add the following code:

    C#

    PostHog AI

    ```csharp
    using PostHog;
    var builder = WebApplication.CreateBuilder(args);
    // Add PostHog to the dependency injection container as a singleton.
    builder.AddPostHog();
    ```

    Make sure to configure PostHog with your project token, instance address, and optional personal API key. For example, in `appsettings.json`:

    JSON

    PostHog AI

    ```json
    {
      "PostHog": {
        "ProjectApiKey": "<ph_project_token>",
        "HostUrl": "https://us.i.posthog.com"
      }
    }
    ```

    > **Note:** If the host is not specified, the default host `https://us.i.posthog.com` is used.

    Use a secrets manager to store your personal API key. For example, when developing locally you can use the `UserSecrets` feature of the `dotnet` CLI:

    Terminal

    PostHog AI

    ```bash
    dotnet user-secrets init
    dotnet user-secrets set "PostHog:PersonalApiKey" "phx_..."
    ```

    You can find your project token and instance address in the [project settings](https://app.posthog.com/project/settings) page in PostHog.

    ## Working with .NET Feature Management

    `PostHog.AspNetCore` supports [.NET Feature Management](https://learn.microsoft.com/en-us/azure/azure-app-configuration/feature-management-dotnet-reference). This enables you to use the <feature /\> tag helper and the `FeatureGateAttribute` in your ASP.NET Core applications to gate access to certain features using PostHog feature flags.

    To use feature flags with the .NET Feature Management library, you'll need to implement the `IPostHogFeatureFlagContextProvider` interface. The quickest way to do that is to inherit from the `PostHogFeatureFlagContextProvider` class and override the `GetDistinctId` and `GetFeatureFlagOptionsAsync` methods.

    C#

    PostHog AI

    ```csharp
    public class MyFeatureFlagContextProvider(IHttpContextAccessor httpContextAccessor)
        : PostHogFeatureFlagContextProvider
    {
        protected override string? GetDistinctId()
            => httpContextAccessor.HttpContext?.User.Identity?.Name;
        protected override ValueTask<FeatureFlagOptions> GetFeatureFlagOptionsAsync()
        {
            // In a real app, you might get this information from a
            // database or other source for the current user.
            return ValueTask.FromResult(
                new FeatureFlagOptions
                {
                    PersonProperties = new Dictionary<string, object?>
                    {
                        ["email"] = "some-test@example.com"
                    },
                    OnlyEvaluateLocally = true
                });
        }
    }
    ```

    Then, register your implementation in `Program.cs` (or `Startup.cs`):

    C#

    PostHog AI

    ```csharp
    var builder = WebApplication.CreateBuilder(args);
    builder.AddPostHog(options => {
        options.UseFeatureManagement<MyFeatureFlagContextProvider>();
    });
    ```

    With this in place, you can now use `feature` tag helpers in your Razor views:

    HTML

    PostHog AI

    ```html
    <feature name="awesome-new-feature">
        <p>This is the new feature!</p>
    </feature>
    <feature name="awesome-new-feature" negate="true">
        <p>Sorry, no awesome new feature for you.</p>
    </feature>
    ```

    Multivariate feature flags are also supported:

    HTML

    PostHog AI

    ```html
    <feature name="awesome-new-feature" value="variant-a">
        <p>This is the new feature variant A!</p>
    </feature>
    <feature name="awesome-new-feature" value="variant-b">
        <p>This is the new feature variant B!</p>
    </feature>
    ```

    You can also use the `FeatureGateAttribute` to gate access to controllers or actions:

    C#

    PostHog AI

    ```csharp
    [FeatureGate("awesome-new-feature")]
    public class NewFeatureController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }
    }
    ```

    ## Using the core package without ASP.NET Core

    If you're not using ASP.NET Core (for example, in a console application, MAUI app, or Blazor WebAssembly), install the `PostHog` package instead of `PostHog.AspNetCore`. This package has no ASP.NET Core dependencies and can be used in any .NET project targeting .NET Standard 2.1 or .NET 8+.

    Terminal

    PostHog AI

    ```bash
    dotnet add package PostHog
    ```

    The `PostHogClient` class must be implemented as a singleton in your project. For `PostHog.AspNetCore`, this is handled by the `builder.AddPostHog();` method. For the `PostHog` package, you can do the following if you're using dependency injection:

    C#

    PostHog AI

    ```csharp
    builder.Services.AddPostHog();
    ```

    If you're not using a `builder` (such as in a console application), you can do the following:

    C#

    PostHog AI

    ```csharp
    using PostHog;
    var services = new ServiceCollection();
    services.AddPostHog();
    var serviceProvider = services.BuildServiceProvider();
    var posthog = serviceProvider.GetRequiredService<IPostHogClient>();
    ```

    The `AddPostHog` methods accept an optional `Action<PostHogOptions>` parameter that you can use to configure the client.

    If you're not using dependency injection, you can create a static instance of the `PostHogClient` class and use that everywhere in your project:

    C#

    PostHog AI

    ```csharp
    using PostHog;
    public static readonly PostHogClient PostHog = new(new PostHogOptions {
        ProjectApiKey = "<ph_project_token>",
        HostUrl = new Uri("https://us.i.posthog.com"),
        PersonalApiKey = Environment.GetEnvironmentVariable(
          "PostHog__PersonalApiKey")
    });
    ```

    ## Debug mode

    If you're not seeing the expected events being captured, the feature flags being evaluated, or the surveys being shown, you can enable debug mode to see what's happening.

    To see detailed logging, set the log level to `Debug` or `Trace` in `appsettings.json`:

    JSON

    PostHog AI

    ```json
    {
      "DetailedErrors": true,
      "Logging": {
        "LogLevel": {
          "Default": "Information",
          "Microsoft.AspNetCore": "Warning",
          "PostHog": "Trace"
        }
      },
      ...
    }
    ```

2.  2

    ## Capture conversion event

    Required

    Once PostHog is initialized, you should be able to capture events. For your experiment to be meaningful, we need to capture an event that we want to measure, such as a conversion event.

    For this tutorial, let's report a conversion event when a clicks a CTA. In server SDKs like Node, this can be called when a specific route is visited or reported from your client side app.

    C#

    PostHog AI

    ```csharp
    posthog.Capture("user_distinct_id", "cta clicked");
    ```

3.  ## Validate PostHog events

    Checkpoint

    *Confirm events are being sent to PostHog*

    Before proceeding, let's make sure events are being captured and sent to PostHog. You should see `cta clicked` events appear in the **Activity** feed.

    [Check for events in PostHog](https://app.posthog.com/activity/explore)

4.  3

    ## Create an experiment

    Required

    Go to the [**Experiments** tab](https://app.posthog.com/experiments) in the PostHog app and click on the **New experiment** button in the top right.

    ![Create experiment](https://res.cloudinary.com/dmukukwp6/image/upload/create_experiment_ae83e877d6.png)![Create experiment](https://res.cloudinary.com/dmukukwp6/image/upload/create_experiment_dark_5c6a4acbd0.png)

    For this tutorial, let's create a new experiment using simplified test values:

    -   **Name**: "Test experiment"
    -   **Description**: "This is a test experiment"
    -   **Feature flag key**: "test-experiment-ff-key"
    -   **Experiment type**: "Feature flag"
    -   **Variants**: "control" and "test"
    -   **Participant type**: "Users"

    Then click **Save as draft**.

5.  4

    ## Add primary metric and launch

    Required

    Scroll down to the **Primary metrics** section and click **\+ Add primary metric**.

    Choose **Single-use** and select **Type** > **Mean**.

    Then search for the event `cta clicked` under **Metric** and click **Save**.

    ![Add primary metric](https://res.cloudinary.com/dmukukwp6/image/upload/primary_metric_b8d831b522.png)![Add primary metric](https://res.cloudinary.com/dmukukwp6/image/upload/primary_metric_dark_a24636046b.png)

    By default, experiments are exposed to 100% of users. You can customize [release conditions](/docs/experiments/creating-an-experiment.md#release-conditions) to expose the experiment to a subset of users.

    For this tutorial, we'll ship the experiment to all users and click **Launch** in the top right.

6.  5

    ## Call feature flag

    Required

    Use the PostHog SDK to call the experiment flag and update how your page renders based on the assigned variant.

    C#

    PostHog AI

    ```csharp
    if (await posthog.GetFeatureFlagAsync(
            "your-experiment-key",
            "user_distinct_id")
        is { VariantKey: "test" })
    {
        // Show test variant UI
    } else {
        // Show control variant UI
    }
    ```

    Now when a user triggers a `cta clicked` event, PostHog automatically assigns the user to a variant and records an experiment exposure.

    By default, users are split equally between variants. If you want to assign specific users to a specific variant, see more about [distribution and release conditions](/docs/experiments/creating-an-experiment.md#distribution-and-release-conditions).

7.  ## Validate feature flag calls

    Checkpoint

    Make sure exposures and feature flag calls are being sent to PostHog. You should see `$feature_flag_called` events appear in the **Activity** feed.

    [Check for events in PostHog](https://app.posthog.com/activity/explore)

8.  6

    ## Evaluate experiment results

    Recommended

    As you capture more `cta clicked` events, more exposures will populate the primary metrics in your experiment.

    ![Evaluate experiment metrics](https://res.cloudinary.com/dmukukwp6/image/upload/experiment_metrics_ecea40f310.png)![Evaluate experiment metrics](https://res.cloudinary.com/dmukukwp6/image/upload/experiment_metrics_dark_6fed5063b9.png)

    With enough data, you can analyze the experiment and its variants by:

    -   Conversion rates
    -   Statistical significance
    -   Credible intervals
    -   Chance to win %
    -   Minimum detectable effect
    -   And more

### Community questions

Ask a question

### Was this page useful?

HelpfulCould be better