Analytics-CSharp (C#) Migration Guide
If you’re currently using Analytics.NET or Analytics.Xamarin to send data to Segment, please follow the steps below to migrate to the Analytics-CSharp library.
Analytics-C# does not include v1
as part of the url
address. If you are using the Segment EU endpoint, you will have to pass it manually. For instance, events.eu1.segmentapis.com/v1
You can update to Analytics-CSharp in 3 steps:
- Bundle Analytics-CSharp into your app and remove your previous SDK.
- Change the namespaces.
- (Optional) Use
Reset
to stay anonymous.
Migration steps
-
Add the Analytics-CSharp dependency to your project.
Before:dotnet add package Analytics --version <VERSION>
Before (for Xamarin users only):git clone https://github.com/segmentio/Analytics.Xamarin.git
After:dotnet add package Segment.Analytics.CSharp --version <VERSION>
-
Replace namespaces.
Before:using Segment; using Segment.Flush; using Segment.Model; using Segment.Request;
After:using Segment.Analytics; using Segment.Analytics.Compat;
-
(Required for .NET users) Add
UserIdPlugin
to Analytics.Analytics-CSharp, by default, attaches an internal state
userId
to each event. TheUserIdPlugin
, instead, attaches theuserId
provided in analytics calls directly to the event.
After:analytics.Add(new UserIdPlugin());
-
(Optional) Update calls that resets the anonymous ID.
The old SDK requires you to provide the anonymous ID. The new SDK generates an Anonymous ID for you if you never call
analytics.Identify
. If you callIdentify
and want to go back to anonymous, the new SDK provides aReset
function to achieve that.
Before:Analytics.Client.Page(null, "Login", new Properties(), new Options() .SetAnonymousId("some-id"));
After:analytics.Reset();
Optional changes for unit tests
Change your development settings if you would like to make analytics run synchronously for testing purposes.
Before:
Analytics.Initialize("YOUR_WRITE_KEY", new Config().SetAsync(false));
After:
var configuration = new Configuration("YOUR WRITE KEY",
useSynchronizeDispatcher: true,
// provide a defaultSettings in case the SDK failed to fetch settings in test environment
defaultSettings: new Settings
{
Integrations = new JsonObject
{
["Segment.io"] = new JsonObject
{
["apiKey"] = "YOUR WRITE KEY"
}
}
}
);
var analytics = new Analytics(configuration);
FAQs
Should I make Analytics a singleton or scoped in .NET?
The SDK supports both, but be aware of the implications of choosing one over the other:
Feature | Singleton | Scoped |
---|---|---|
Fetch Settings | Settings are fetched only once at application startup. | Settings are fetched on every request. |
Flush | Supports both async and sync flush. | Requires sync flush. Should flush per event or on page redirect/close to avoid data loss. |
Internal State | The internal state (userId , anonId , etc.) is shared across sessions and cannot be used. (This is an overhead we are working to minimize.) |
The internal state is safe to use since a new instance is created per request. |
UserId for Events | Requires adding UserIdPlugin and calling analytics APIs with userId to associate the correct userId with events. |
No need for UserIdPlugin or passing userId in API calls. Instead, call analytics.Identify() to update the internal state with the userId . Successive events are auto-stamped with that userId . |
Storage | Supports both local storage and in-memory storage. | Requires in-memory storage. (Support for local storage is in progress.) |
In a nutshell, to register Analytics as singleton:
var configuration = new Configuration(
writeKey: "YOUR_WRITE_KEY",
// Use in-memory storage to keep the SDK stateless.
// The default storage also works if you want to persist events.
storageProvider: new InMemoryStorageProvider(),
// Use a synchronous pipeline to make manual flush operations synchronized.
eventPipelineProvider: new SyncEventPipelineProvider()
);
var analytics = new Analytics(configuration);
// Add UserIdPlugin to associate events with the provided userId.
analytics.Add(new UserIdPlugin());
// Call analytics APIs with a userId. The UserIdPlugin will update the event with the provided userId.
analytics.Track("user123", "foo", properties);
// This is a blocking call due to SyncEventPipelineProvider.
// Use the default EventPipelineProvider for asynchronous flush.
analytics.Flush();
// Register Analytics as a singleton.
To register Analytics as scoped:
var configuration = new Configuration(
writeKey: "YOUR_WRITE_KEY",
// Requires in-memory storage.
storageProvider: new InMemoryStorageProvider(),
// Flush per event to prevent data loss in case of a page close.
// Alternatively, manually flush on page close.
flushAt: 1,
// Requires a synchronous flush.
eventPipelineProvider: new SyncEventPipelineProvider()
);
var analytics = new Analytics(configuration);
// Update the internal state with a userId.
analytics.Identify("user123");
// Subsequent events are auto-stamped with the userId from the internal state.
analytics.Track("foo", properties);
// This is a blocking call due to SyncEventPipelineProvider.
analytics.Flush();
// Register Analytics as scoped.
Which JSON library does this SDK use?
The SDK supports .netstandard 1.3
and .netstandard 2.0
and automatically selects the internal JSON library based on the target framework:
- In
.netstandard 1.3
, the SDK usesNewtonsoft Json.NET
- In
.netstandard 2.0
, the SDK usesSystem.Text.Json
Be ware that both Analytics.NET and Analytics.Xamarin use Newtonsoft Json.NET
. If you encounter issues where JSON dictionary values are turned into empty arrays, it is likely that:
- You are targeting
.netstandard 2.0
. - Your properties use
Newtonsoft Json.NET
objects or arrays.
To resolve this, you can:
- Option 1: Target
.netstandard 1.3
- Option 2: Upgrade your JSON library to
System.Text.Json
This page was last modified: 25 Mar 2025
Need support?
Questions? Problems? Need more info? Contact Segment Support for assistance!