mirror of
https://github.com/BillyOutlast/posthog.com.git
synced 2026-02-04 03:11:21 +01:00
Write up documentation on posthog-dotnet (#10589)
Co-authored-by: Ian Vanagas <34755028+ivanagas@users.noreply.github.com>
This commit is contained in:
@@ -149,6 +149,14 @@ if feature_flag.enabled == "variant-name" do
|
||||
end
|
||||
```
|
||||
|
||||
```dotnet
|
||||
var featureFlag = await posthog.GetFeatureFlagAsync("experiment-feature-flag-key", "user_distinct_id");
|
||||
|
||||
if (featureFlag is { VariantKey: "variant-name" })
|
||||
{
|
||||
// Do something
|
||||
}
|
||||
```
|
||||
</MultiLanguage>
|
||||
|
||||
> Since feature flags are not supported yet in our Java and Rust SDKs, to run an experiment using these SDKs see our docs on [how to run experiments without feature flags](/docs/experiments/running-experiments-without-feature-flags). This also applies to running experiments using our API.
|
||||
@@ -230,6 +238,13 @@ posthog.capture(
|
||||
);
|
||||
```
|
||||
|
||||
```dotnet
|
||||
posthog.Capture(
|
||||
"distinct_id",
|
||||
"event_name_of_your_goal_metric",
|
||||
properties: new() { ["$feature/experiment-feature-flag-key"] = "variant-name" }
|
||||
);
|
||||
```
|
||||
</MultiLanguage>
|
||||
|
||||
import Tab from "components/Tab"
|
||||
@@ -238,6 +253,7 @@ import NodeMethod2 from "../integrate/feature-flags-code/_snippets/feature-flags
|
||||
import GoMethod2 from "../integrate/feature-flags-code/_snippets/feature-flags-code-go-set-send-feature-flags-to-true.mdx"
|
||||
import PythonMethod2 from "../integrate/feature-flags-code/_snippets/feature-flags-code-python-set-send-feature-flags-to-true.mdx"
|
||||
import PHPMethod2 from "../integrate/feature-flags-code/_snippets/feature-flags-code-php-set-send-feature-flags-to-true.mdx"
|
||||
import DotNetMethod2 from "../integrate/feature-flags-code/_snippets/feature-flags-code-dotnet-set-send-feature-flags-to-true.mdx"
|
||||
|
||||
### Method 2: Set `send_feature_flags` to `true`
|
||||
|
||||
@@ -265,5 +281,8 @@ import PHPMethod2 from "../integrate/feature-flags-code/_snippets/feature-flags-
|
||||
<Tab.Panel>
|
||||
<GoMethod2 />
|
||||
</Tab.Panel>
|
||||
<Tab.Panel>
|
||||
<DotNetMethod2 />
|
||||
</Tab.Panel>
|
||||
</Tab.Panels>
|
||||
</Tab.Group>
|
||||
|
||||
@@ -30,9 +30,10 @@ import ReactNativeInstall from '../integrate/_snippets/install-react-native.mdx'
|
||||
import AndroidInstall from '../integrate/_snippets/install-android.mdx'
|
||||
import IOSInstall from '../integrate/_snippets/install-ios.mdx'
|
||||
import ElixirInstall from '../integrate/_snippets/install-elixir.mdx'
|
||||
import DotNetInstall from '../integrate/_snippets/install-dotnet.mdx'
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
<Tab.Group tabs={['Web', 'React', 'Node.js', 'Python', 'PHP', 'Ruby', 'Go', 'React Native', 'Android', 'iOS', 'Java', 'Rust', 'Elixir', 'api']}>
|
||||
<Tab.Group tabs={['Web', 'React', 'Node.js', 'Python', 'PHP', 'Ruby', 'Go', 'React Native', 'Android', 'iOS', 'Java', 'Rust', 'Elixir', '.NET', 'api']}>
|
||||
<Tab.List>
|
||||
<Tab>Web</Tab>
|
||||
<Tab>React</Tab>
|
||||
@@ -47,6 +48,7 @@ import ElixirInstall from '../integrate/_snippets/install-elixir.mdx'
|
||||
<Tab>Java</Tab>
|
||||
<Tab>Rust</Tab>
|
||||
<Tab>Elixir</Tab>
|
||||
<Tab>.NET</Tab>
|
||||
<Tab>API</Tab>
|
||||
</Tab.List>
|
||||
<Tab.Panels>
|
||||
@@ -93,6 +95,9 @@ import ElixirInstall from '../integrate/_snippets/install-elixir.mdx'
|
||||
<Tab.Panel>
|
||||
<ElixirInstall />
|
||||
</Tab.Panel>
|
||||
<Tab.Panel>
|
||||
<DotNetInstall />
|
||||
</Tab.Panel>
|
||||
<Tab.Panel>
|
||||
<blockquote class='warning-note'>
|
||||
To run an experiment using the <a href="/docs/api">PostHog API</a>, see our docs on <a href="/docs/experiments/running-experiments-without-feature-flags">how to run experiments without feature flags</a>.
|
||||
|
||||
@@ -123,6 +123,16 @@ posthog.capture(
|
||||
);
|
||||
```
|
||||
|
||||
```csharp
|
||||
posthog.Capture(
|
||||
"distinct_id",
|
||||
"event_name_of_your_goal_metric",
|
||||
properties: new() {
|
||||
["$feature/experiment-feature-flag-key"] = "variant-name"
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
</MultiLanguage>
|
||||
|
||||
## Step 4 (optional): Send the `$feature_flag_called` event
|
||||
@@ -245,4 +255,15 @@ posthog.capture(
|
||||
);
|
||||
```
|
||||
|
||||
```csharp
|
||||
posthog.Capture(
|
||||
"distinct_id",
|
||||
"$feature_flag_called",
|
||||
properties: new() {
|
||||
["$feature_flag_response"] = "variant-name",
|
||||
["feature_flag"] = "feature-flag-key"
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
</MultiLanguage>
|
||||
@@ -25,9 +25,10 @@ import AndroidFeatureFlagsCode from '../integrate/feature-flags-code/_snippets/f
|
||||
import IOSFeatureFlagsCode from '../integrate/feature-flags-code/_snippets/feature-flags-code-ios.mdx'
|
||||
import FlutterFeatureFlagsCode from '../integrate/feature-flags-code/_snippets/feature-flags-code-flutter.mdx'
|
||||
import ElixirFeatureFlagsCode from '../integrate/feature-flags-code/_snippets/feature-flags-code-elixir.mdx'
|
||||
import DotNetFeatureFlagsCode from '../integrate/feature-flags-code/_snippets/feature-flags-code-dotnet.mdx'
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
<Tab.Group tabs={['Web', 'React', 'Node.js', 'Python', 'PHP', 'Ruby', 'Go', 'React Native', 'Android', 'iOS', 'Flutter', 'Java', 'Rust', 'Elixir', 'api']}>
|
||||
<Tab.Group tabs={['Web', 'React', 'Node.js', 'Python', 'PHP', 'Ruby', 'Go', 'React Native', 'Android', 'iOS', 'Flutter', 'Java', 'Rust', 'Elixir', '.NET', 'api']}>
|
||||
<Tab.List>
|
||||
<Tab>Web</Tab>
|
||||
<Tab>React</Tab>
|
||||
@@ -43,6 +44,7 @@ import ElixirFeatureFlagsCode from '../integrate/feature-flags-code/_snippets/fe
|
||||
<Tab>Java</Tab>
|
||||
<Tab>Rust</Tab>
|
||||
<Tab>Elixir</Tab>
|
||||
<Tab>.NET</Tab>
|
||||
<Tab>API</Tab>
|
||||
</Tab.List>
|
||||
<Tab.Panels>
|
||||
@@ -92,6 +94,9 @@ import ElixirFeatureFlagsCode from '../integrate/feature-flags-code/_snippets/fe
|
||||
<Tab.Panel>
|
||||
<ElixirFeatureFlagsCode />
|
||||
</Tab.Panel>
|
||||
<Tab.Panel>
|
||||
<DotNetFeatureFlagsCode />
|
||||
</Tab.Panel>
|
||||
<Tab.Panel>
|
||||
<APIFeatureFlagsCode />
|
||||
</Tab.Panel>
|
||||
|
||||
@@ -31,9 +31,10 @@ import JavaInstall from '../integrate/_snippets/install-java.mdx'
|
||||
import RustInstall from '../integrate/_snippets/install-rust.mdx'
|
||||
import FlutterInstall from '../integrate/_snippets/install-flutter.mdx'
|
||||
import ElixirInstall from '../integrate/_snippets/install-elixir.mdx'
|
||||
import DotNetInstall from '../integrate/_snippets/install-dotnet.mdx'
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
<Tab.Group tabs={['Web', 'React', 'Node.js', 'Python', 'PHP', 'Ruby', 'Go', 'React Native', 'Android', 'iOS', 'Java', 'Rust', 'Flutter', 'Elixir', 'api']}>
|
||||
<Tab.Group tabs={['Web', 'React', 'Node.js', 'Python', 'PHP', 'Ruby', 'Go', 'React Native', 'Android', 'iOS', 'Java', 'Rust', 'Flutter', 'Elixir', '.NET', 'api']}>
|
||||
<Tab.List>
|
||||
<Tab>Web</Tab>
|
||||
<Tab>React</Tab>
|
||||
@@ -49,6 +50,7 @@ import ElixirInstall from '../integrate/_snippets/install-elixir.mdx'
|
||||
<Tab>Rust</Tab>
|
||||
<Tab>Flutter</Tab>
|
||||
<Tab>Elixir</Tab>
|
||||
<Tab>.NET</Tab>
|
||||
<Tab>API</Tab>
|
||||
</Tab.List>
|
||||
<Tab.Panels>
|
||||
@@ -98,6 +100,9 @@ import ElixirInstall from '../integrate/_snippets/install-elixir.mdx'
|
||||
<Tab.Panel>
|
||||
<ElixirInstall />
|
||||
</Tab.Panel>
|
||||
<Tab.Panel>
|
||||
<DotNetInstall />
|
||||
</Tab.Panel>
|
||||
<Tab.Panel>
|
||||
<APIInstall />
|
||||
<blockquote>
|
||||
|
||||
55
contents/docs/integrate/_snippets/install-dotnet.mdx
Normal file
55
contents/docs/integrate/_snippets/install-dotnet.mdx
Normal file
@@ -0,0 +1,55 @@
|
||||
<DotNetInstall />
|
||||
|
||||
At the moment, ASP.NET Core is the only supported platform for the PostHog .NET SDK.
|
||||
|
||||
```bash
|
||||
dotnet add package PostHog.AspNetCore
|
||||
```
|
||||
|
||||
In your `Program.cs` file, add the following code:
|
||||
|
||||
```csharp
|
||||
using PostHog.AspNetCore;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
builder.AddPostHog();
|
||||
```
|
||||
|
||||
Make sure to configure PostHog with your project API key, instance address, and optional personal API key. For example, in appsettings.json:
|
||||
|
||||
```json
|
||||
{
|
||||
"PostHog": {
|
||||
"ProjectApiKey": "phc_...",
|
||||
"Host": "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:
|
||||
|
||||
```bash
|
||||
dotnet user-secrets init
|
||||
dotnet user-secrets set "PostHog:PersonalApiKey" "phc_..."
|
||||
```
|
||||
|
||||
You can find your project API key and instance address in the [project settings](https://app.posthog.com/project/settings) page in PostHog.
|
||||
|
||||
To see detailed logging, set the log level to `Debug` or `Trace` in `appsettings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"DetailedErrors": true,
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning",
|
||||
"PostHog": "Trace"
|
||||
}
|
||||
},
|
||||
...
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,13 @@
|
||||
The `Capture()` method has an optional argument `sendFeatureFlags`, which is set to `false` by default. By setting this to `true`, feature flag information will automatically be sent with the event.
|
||||
|
||||
Note that by doing this, PostHog will make an additional request to fetch feature flag information before capturing the event. So this method is only recommended if you don't mind the extra API call and delay.
|
||||
|
||||
```csharp
|
||||
posthog.Capture(
|
||||
"distinct_id_of_your_user",
|
||||
"event_name",
|
||||
properties: null,
|
||||
groups: null,
|
||||
sendFeatureFlags: true
|
||||
);
|
||||
```
|
||||
@@ -0,0 +1,119 @@
|
||||
There are 2 steps to implement feature flags in .NET:
|
||||
|
||||
### Step 1: Evaluate the feature flag value
|
||||
|
||||
#### Boolean feature flags
|
||||
|
||||
```csharp
|
||||
var isMyFlagEnabled = await posthog.IsFeatureEnabledAsync(
|
||||
"flag-key",
|
||||
"distinct_id_of_your_user"
|
||||
);
|
||||
if (isMyFlagEnabled.GetValueOrDefault())
|
||||
{
|
||||
// Feature is enabled
|
||||
}
|
||||
else
|
||||
{
|
||||
// Feature is disabled
|
||||
}
|
||||
```
|
||||
|
||||
> **Note:** The `IsFeatureEnabledAsync` method returns a nullable boolean. If the flag is not found or evaluating it is inconclusive, it returns `null`.
|
||||
|
||||
#### Multivariate feature flags
|
||||
|
||||
```csharp
|
||||
var flag = await posthog.GetFeatureFlagAsync(
|
||||
"flag-key",
|
||||
"distinct_id_of_your_user"
|
||||
);
|
||||
|
||||
// replace "variant-key" with the key of your variant
|
||||
if (flag is { VariantKey: "variant-key"} ) {
|
||||
// Do something differently for this user
|
||||
// Optional: fetch the payload
|
||||
var matchedPayload = flag.Payload;
|
||||
}
|
||||
```
|
||||
|
||||
The `GetFeatureFlagAsync` method returns a nullable `FeatureFlag` object. If the flag is not found or evaluating it is inconclusive, it returns `null`. However, there is an implicit conversion to bool to make comparisons easier.
|
||||
|
||||
```csharp
|
||||
if (await posthog.GetFeatureFlagAsync(
|
||||
"flag-key",
|
||||
"distinct_id_of_your_user")
|
||||
)
|
||||
{
|
||||
// Do something differently for this user
|
||||
}
|
||||
```
|
||||
|
||||
import IncludePropertyInEvents from "./include-feature-flag-property-in-backend-events.mdx"
|
||||
|
||||
<IncludePropertyInEvents />
|
||||
|
||||
There are two methods you can use to include feature flag information in your events:
|
||||
|
||||
#### Method 1: Include the `$feature/feature_flag_name` property
|
||||
|
||||
In the event properties, include `$feature/feature_flag_name: variant_key`:
|
||||
|
||||
```csharp
|
||||
posthog.Capture(
|
||||
"distinct_id_of_your_user",
|
||||
"event_name",
|
||||
properties: new() {
|
||||
// replace feature-flag-key with your flag key.
|
||||
// Replace 'variant-key' with the key of your variant
|
||||
["$feature/feature-flag-key"] = "variant-key"
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
#### Method 2: Set `send_feature_flags` to `true`
|
||||
|
||||
import DotNetSetSendFeatureFlagsTrue from "./feature-flags-code-dotnet-set-send-feature-flags-to-true.mdx"
|
||||
|
||||
<DotNetSetSendFeatureFlagsTrue />
|
||||
|
||||
### Fetching all flags for a user
|
||||
|
||||
You can fetch all flag values for a single user by calling `GetAllFeatureFlagsAsync()`.
|
||||
|
||||
This is useful when you need to fetch multiple flag values and don't want to make multiple requests.
|
||||
|
||||
```csharp
|
||||
var flags = await posthog.GetAllFeatureFlagsAsync(
|
||||
"distinct_id_of_your_user"
|
||||
);
|
||||
```
|
||||
|
||||
### Sending `$feature_flag_called` events
|
||||
|
||||
Capturing `$feature_flag_called` events enable PostHog to know when a flag was accessed by a user and thus provide [analytics and insights](/docs/product-analytics/insights) on the flag. By default, we send a these event when:
|
||||
|
||||
1. You call `posthog.GetFeatureFlagAsync()` or `posthog.IsFeatureEnabledAsync()`, AND
|
||||
2. It's a new user, or the value of the flag has changed.
|
||||
|
||||
> *Note:* Tracking whether it's a new user or if a flag value has changed happens in a local cache. This means that if you reinitialize the PostHog client, the cache resets as well – causing `$feature_flag_called` events to be sent again when calling `GetFeatureFlagAsync` or `IsFeatureEnabledAsync`. PostHog is built to handle this, and so duplicate `$feature_flag_called` events won't affect your analytics.
|
||||
|
||||
You can disable automatically the additional request to capture `$feature_flag_called` events. For example, when you don't need the analytics, or it's being called at such a high volume that sending events slows things down.
|
||||
|
||||
To disable it, set the `sendFeatureFlagsEvent` option in your function call, like so:
|
||||
|
||||
```csharp
|
||||
var isMyFlagEnabled = await posthog.IsFeatureEnabledAsync(
|
||||
"flag-key",
|
||||
"distinct_id_of_your_user",
|
||||
options: new FeatureFlagOptions
|
||||
{
|
||||
SendFeatureFlagEvents = true
|
||||
}
|
||||
);
|
||||
// will not send `$feature_flag_called` events
|
||||
```
|
||||
|
||||
import DotNetOverrideServerProperties from './override-server-properties/dotnet.mdx'
|
||||
|
||||
<DotNetOverrideServerProperties />
|
||||
@@ -0,0 +1,31 @@
|
||||
import OverrideServerPropertiesIntro from './override-server-properties-intro.mdx'
|
||||
|
||||
<OverrideServerPropertiesIntro />
|
||||
|
||||
```csharp
|
||||
var flag = await posthog.GetFeatureFlagAsync(
|
||||
"flag-key",
|
||||
"distinct_id_of_the_user",
|
||||
options: new FeatureFlagOptions
|
||||
{
|
||||
PersonProperties = new() { ["property_name"] = "value" },
|
||||
Groups = [
|
||||
new Group("your_group_type", "your_group_id")
|
||||
{
|
||||
["group_property_name"] = "your group value"
|
||||
},
|
||||
new Group(
|
||||
"another_group_type",
|
||||
"another_group_id",
|
||||
new Dictionary<string, object?>
|
||||
{
|
||||
["group_property_name"] = "another group value"
|
||||
}
|
||||
)
|
||||
]
|
||||
});
|
||||
```
|
||||
|
||||
import OverrideGeoIPPropertiesSDK from './override-geoip-properties-SDKs.mdx'
|
||||
|
||||
<OverrideGeoIPPropertiesSDK />
|
||||
@@ -0,0 +1,37 @@
|
||||
import SettingProperties from "./setting-properties-text.mdx"
|
||||
import NamingTip from "./naming-tip.mdx"
|
||||
import Intro from "./intro.mdx"
|
||||
|
||||
<Intro />
|
||||
|
||||
```csharp
|
||||
posthog.Capture("distinct_id_of_the_user", "user_signed_up");
|
||||
```
|
||||
|
||||
<NamingTip />
|
||||
|
||||
<SettingProperties />
|
||||
|
||||
```csharp
|
||||
posthog.Capture(
|
||||
"distinct_id_of_the_user",
|
||||
"user_signed_up",
|
||||
properties: new() {
|
||||
["login_type"] = "email",
|
||||
["is_free_trial"] = "true"
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
### Sending page views
|
||||
|
||||
If you're aiming for a backend-only implementation of PostHog and won't be capturing events from your frontend, you can send `$pageview` events from your backend like so:
|
||||
|
||||
```csharp
|
||||
using PostHog;
|
||||
using Microsoft.AspNetCore.Http.Extensions;
|
||||
|
||||
posthog.CapturePageView(
|
||||
"distinct_id_of_the_user",
|
||||
context.HttpContext.Request.GetDisplayUrl());
|
||||
```
|
||||
10
contents/docs/libraries/dotnet/_snippets/capture.mdx
Normal file
10
contents/docs/libraries/dotnet/_snippets/capture.mdx
Normal file
@@ -0,0 +1,10 @@
|
||||
```csharp
|
||||
posthog.Capture(
|
||||
distinctId: "distinct_id",
|
||||
eventName: "movie_played",
|
||||
properties: new()
|
||||
{
|
||||
["movie_id"] = 123,
|
||||
["category"] = "romcom",
|
||||
});
|
||||
```
|
||||
7
contents/docs/libraries/dotnet/_snippets/identify.mdx
Normal file
7
contents/docs/libraries/dotnet/_snippets/identify.mdx
Normal file
@@ -0,0 +1,7 @@
|
||||
```csharp
|
||||
await posthog.IdentifyAsync(
|
||||
"distinct_id_of_the_user",
|
||||
email: "john@doe.com",
|
||||
name: "John Doe"
|
||||
);
|
||||
```
|
||||
150
contents/docs/libraries/dotnet/index.mdx
Normal file
150
contents/docs/libraries/dotnet/index.mdx
Normal file
@@ -0,0 +1,150 @@
|
||||
---
|
||||
title: .NET
|
||||
sidebarTitle: .NET
|
||||
sidebar: Docs
|
||||
showTitle: true
|
||||
github: 'https://github.com/PostHog/posthog-dotnet'
|
||||
icon: >-
|
||||
https://res.cloudinary.com/dmukukwp6/image/upload/dotnet_logo_7e446176f2.svg
|
||||
features:
|
||||
eventCapture: true
|
||||
userIdentification: true
|
||||
featureFlags: true
|
||||
groupAnalytics: true
|
||||
surveys: false
|
||||
llmObservability: false
|
||||
errorTracking: false
|
||||
---
|
||||
|
||||
> ⚠️ **Warning:** This is in beta and may break.
|
||||
|
||||
This is an optional library you can install if you're working with .NET Core. It uses an internal queue to make calls fast and non-blocking. It also batches requests and flushes asynchronously, making it perfect to use in any part of your web app or other server side application that needs performance.
|
||||
|
||||
## Installation
|
||||
|
||||
import DotNetInstall from '../../integrate/_snippets/install-dotnet.mdx'
|
||||
|
||||
<DotNetInstall />
|
||||
|
||||
## Capturing events
|
||||
|
||||
import DotNetSendEvents from '../../integrate/send-events/_snippets/send-events-dotnet.mdx'
|
||||
|
||||
<DotNetSendEvents />
|
||||
|
||||
## Person profiles and properties
|
||||
|
||||
The .NET SDK captures identified events by default. These create [person profiles](/docs/data/persons). To set [person properties](/docs/data/user-properties) in these profiles, include them when capturing an event:
|
||||
|
||||
```csharp
|
||||
posthog.Capture(
|
||||
"distinct_id",
|
||||
"event_name",
|
||||
personPropertiesToSet: new() { ["name"] = "Max Hedgehog" },
|
||||
personPropertiesToSetOnce: new() { ["initial_url"] = "/blog" }
|
||||
);
|
||||
```
|
||||
|
||||
For more details on the difference between `$set` and `$set_once`, see our [person properties docs](/docs/data/user-properties#what-is-the-difference-between-set-and-set_once).
|
||||
|
||||
To capture [anonymous events](/docs/data/anonymous-vs-identified-events) without person profiles, set the event's `$process_person_profile` property to `false`:
|
||||
|
||||
```csharp
|
||||
posthog.Capture(
|
||||
"distinct_id",
|
||||
"event_name",
|
||||
properties: new() {
|
||||
["$process_person_profile"] = false
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
## Alias
|
||||
|
||||
Sometimes, you want to assign multiple distinct IDs to a single user. This is helpful when your primary distinct ID is inaccessible. For example, if a distinct ID used on the frontend is not available in your backend.
|
||||
|
||||
In this case, you can use `alias` to assign another distinct ID to the same user.
|
||||
|
||||
```csharp
|
||||
await posthog.AliasAsync('current_distinct_id', 'new_distinct_id');
|
||||
```
|
||||
|
||||
We strongly recommend reading our docs on [alias](/docs/product-analytics/identify#alias-assigning-multiple-distinct-ids-to-the-same-user) to best understand how to correctly use this method.
|
||||
|
||||
## Group analytics
|
||||
|
||||
Group analytics allows you to associate an event with a group (e.g. teams, organizations, etc.). Read the [group analytics](/docs/product-analytics/group-analytics) guide for more information.
|
||||
|
||||
> **Note:** This is a paid feature and is not available on the open-source or free cloud plan. Learn more on our [pricing page](/pricing).
|
||||
|
||||
To capture an event and associate it with a group, add the `groups` argument to your `Capture` call:
|
||||
|
||||
```csharp
|
||||
postHogClient.Capture(
|
||||
"user_distinct_id",
|
||||
"some_event",
|
||||
groups: [new Group("company", "company_id_in_your_db")]);
|
||||
```
|
||||
|
||||
Update properties on a group, use the `GroupIdentifyAsync` method:
|
||||
|
||||
```csharp
|
||||
await postHogClient.GroupIdentifyAsync(
|
||||
type: "company",
|
||||
key: "company_id_in_your_db",
|
||||
name: "Awesome Inc.",
|
||||
properties: new()
|
||||
{
|
||||
["employees"] = 11
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
The `name` is a special property which is used in the PostHog UI for the name of the group. If you don't specify a `name` property, the group ID will be used instead.
|
||||
|
||||
## Feature flags
|
||||
|
||||
import FeatureFlagsLibsIntro from "../_snippets/feature-flags-libs-intro.mdx"
|
||||
|
||||
<FeatureFlagsLibsIntro />
|
||||
|
||||
import DotNetFeatureFlagsCode from '../../integrate/feature-flags-code/_snippets/feature-flags-code-dotnet.mdx'
|
||||
|
||||
<DotNetFeatureFlagsCode />
|
||||
|
||||
### Local evaluation
|
||||
|
||||
import LocalEvaluationIntro from "../../feature-flags/snippets/local-evaluation-intro.mdx"
|
||||
|
||||
<LocalEvaluationIntro />
|
||||
|
||||
For details on how to implement local evaluation, see our [local evaluation guide](/docs/feature-flags/local-evaluation).
|
||||
|
||||
## Experiments (A/B tests)
|
||||
|
||||
Since [experiments](/docs/experiments/manual) use feature flags, the code for running an experiment is very similar to the feature flags code:
|
||||
|
||||
```csharp
|
||||
if (await posthog.GetFeatureFlagAsync(
|
||||
"experiment-feature-flag-key",
|
||||
"user_distinct_id")
|
||||
is { VariantKey: "variant-name" })
|
||||
{
|
||||
// Do something
|
||||
}
|
||||
```
|
||||
|
||||
It's also possible to [run experiments without using feature flags](/docs/experiments/running-experiments-without-feature-flags).
|
||||
|
||||
|
||||
## GeoIP properties
|
||||
|
||||
The posthog-dotnet library disregards the server IP, does not add the GeoIP properties, and does not use the values for feature flag evaluations.
|
||||
|
||||
## Serverless environments (Azure Functions/Render/Lambda/...)
|
||||
|
||||
By default, the library buffers events before sending them to the `/batch` endpoint, for better performance. This can
|
||||
lead to lost events in serverless environments, if the .NET process is terminated by the platform before the buffer
|
||||
is fully flushed. To avoid this, you can:
|
||||
|
||||
- ensure that `await posthog.FlushAsync()` is called after processing every request, by adding a middleware to your server: this allows `posthog.Capture()` to remain asynchronous for better performance.
|
||||
@@ -24,6 +24,7 @@ import JavaSendEvent from '../integrate/send-events/_snippets/send-events-java.m
|
||||
import RustSendEvent from '../integrate/send-events/_snippets/send-events-rust.mdx'
|
||||
import FlutterSendEvent from '../integrate/send-events/_snippets/send-events-flutter.mdx'
|
||||
import ElixirSendEvent from '../integrate/send-events/_snippets/send-events-elixir.mdx'
|
||||
import DotNetSendEvent from '../integrate/send-events/_snippets/send-events-dotnet.mdx'
|
||||
|
||||
Once your PostHog instance is up and running, the next step is to start sending events.
|
||||
|
||||
@@ -43,6 +44,7 @@ Once your PostHog instance is up and running, the next step is to start sending
|
||||
'Rust',
|
||||
'Elixir',
|
||||
'Flutter',
|
||||
'.NET',
|
||||
'api']}>
|
||||
<Tab.List>
|
||||
<Tab>Web</Tab>
|
||||
@@ -59,6 +61,7 @@ Once your PostHog instance is up and running, the next step is to start sending
|
||||
<Tab>Rust</Tab>
|
||||
<Tab>Elixir</Tab>
|
||||
<Tab>Flutter</Tab>
|
||||
<Tab>.NET</Tab>
|
||||
<Tab>API</Tab>
|
||||
</Tab.List>
|
||||
<Tab.Panels>
|
||||
@@ -104,6 +107,9 @@ Once your PostHog instance is up and running, the next step is to start sending
|
||||
<Tab.Panel>
|
||||
<FlutterSendEvent />
|
||||
</Tab.Panel>
|
||||
<Tab.Panel>
|
||||
<DotNetSendEvent />
|
||||
</Tab.Panel>
|
||||
<Tab.Panel>
|
||||
<APISendEvent />
|
||||
</Tab.Panel>
|
||||
|
||||
@@ -24,6 +24,7 @@ import JavaInstall from '../integrate/_snippets/install-java.mdx'
|
||||
import RustInstall from '../integrate/_snippets/install-rust.mdx'
|
||||
import FlutterInstall from '../integrate/_snippets/install-flutter.mdx'
|
||||
import ElixirInstall from '../integrate/_snippets/install-elixir.mdx'
|
||||
import DotNetInstall from '../integrate/_snippets/install-dotnet.mdx'
|
||||
|
||||
Product analytics enable you to gather and analyze data about how users interact with your product.
|
||||
|
||||
@@ -32,7 +33,7 @@ To start, install PostHog in the app you want to collect data in.
|
||||
> **Tip**: Even if you have multiple customer-facing products (e.g., a marketing website + iOS app + web app), it's best to have them share the same project. This enables you to track the user across their journey across different platforms. See [organizations & projects docs](/manual/organizations-and-projects) for more.
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
<Tab.Group tabs={['Web', 'React', 'Node.js', 'Python', 'PHP', 'Ruby', 'Go', 'React Native', 'Android', 'iOS', 'Java', 'Rust', 'Elixir', 'Flutter', 'guides', 'api']}>
|
||||
<Tab.Group tabs={['Web', 'React', 'Node.js', 'Python', 'PHP', 'Ruby', 'Go', 'React Native', 'Android', 'iOS', 'Java', 'Rust', 'Elixir', 'Flutter', '.NET', 'guides', 'api']}>
|
||||
<Tab.List>
|
||||
<Tab>Web</Tab>
|
||||
<Tab>React</Tab>
|
||||
@@ -48,6 +49,7 @@ To start, install PostHog in the app you want to collect data in.
|
||||
<Tab>Rust</Tab>
|
||||
<Tab>Elixir</Tab>
|
||||
<Tab>Flutter</Tab>
|
||||
<Tab>.NET</Tab>
|
||||
<Tab count="11">Framework guides</Tab>
|
||||
<Tab>API</Tab>
|
||||
</Tab.List>
|
||||
@@ -94,6 +96,9 @@ To start, install PostHog in the app you want to collect data in.
|
||||
<Tab.Panel>
|
||||
<FlutterInstall />
|
||||
</Tab.Panel>
|
||||
<Tab.Panel>
|
||||
<DotNetInstall />
|
||||
</Tab.Panel>
|
||||
<Tab.Panel>
|
||||
<Frameworks />
|
||||
</Tab.Panel>
|
||||
|
||||
@@ -84,6 +84,7 @@ Your primary responsibility is simply to make sure SDK questions get some love.
|
||||
- [posthog-java](https://github.com/PostHog/posthog-java)
|
||||
- [posthog-rs (Rust)](https://posthog.com/docs/libraries/rust)
|
||||
- [posthog-go](https://posthog.com/docs/libraries/go)
|
||||
- [posthog-dotnet](https://github.com/PostHog/posthog-dotnet)
|
||||
- Others, see https://posthog.com/docs/libraries
|
||||
|
||||
You don't have to be an expert in all of the SDKs, but it can be a great opportunity to dive into parts unknown.
|
||||
|
||||
@@ -12,6 +12,7 @@ require('prismjs/components/prism-elixir')
|
||||
require('prismjs/components/prism-rust')
|
||||
require('prismjs/components/prism-kotlin')
|
||||
require('prismjs/components/prism-groovy')
|
||||
require('prismjs/components/prism-csharp')
|
||||
|
||||
type LanguageMap = {
|
||||
[key: string]: {
|
||||
@@ -32,6 +33,7 @@ type LanguageMap = {
|
||||
| 'vue'
|
||||
| 'svelte'
|
||||
| 'astro'
|
||||
| 'csharp'
|
||||
label: React.ReactNode
|
||||
}
|
||||
}
|
||||
@@ -235,6 +237,10 @@ const languageMap: LanguageMap = {
|
||||
language: 'rust',
|
||||
label: 'Hog',
|
||||
},
|
||||
csharp: {
|
||||
language: 'csharp',
|
||||
label: 'C#',
|
||||
},
|
||||
}
|
||||
|
||||
export default languageMap
|
||||
|
||||
@@ -113,6 +113,16 @@ const librariesData = {
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
name: '.NET',
|
||||
url: '/docs/libraries/dotnet',
|
||||
icon: (
|
||||
<CloudinaryImage
|
||||
src="https://res.cloudinary.com/dmukukwp6/image/upload/dotnet_logo_7e446176f2.svg"
|
||||
alt=".NET"
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
name: 'More',
|
||||
url: '/docs/libraries',
|
||||
|
||||
@@ -1360,6 +1360,10 @@ export const docsMenu = {
|
||||
name: 'Rust',
|
||||
url: '/docs/libraries/rust',
|
||||
},
|
||||
{
|
||||
name: '.NET',
|
||||
url: '/docs/libraries/dotnet',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user