Analytics for .NET
Segment doesn't manage or update community libraries. These libraries are available on GitHub under the MIT License for the open-source community to fork or contribute.
Segment’s .NET library is the best way to integrate analytics into your .NET application or website. It lets you record analytics data from your ASP.NET, C#, F#, and Visual Basic code. The library issues requests that hit Segment’s servers, and then Segment routes your data to any analytics service you enable on our destinations page. This library is open-source, so you can check it out on GitHub.
All of Segment’s server-side libraries are built for high-performance, so you can use them in your web server controller code. This library uses an internal queue to make Identify and Track calls non-blocking and fast. It also batches messages and flushes asynchronously to Segment’s servers.
Analytics-CSharp (C#)
With Analytics-CSharp, you can add Segment analytics to your C# based app which includes .NET. If you’d like to migrate to use Analytics-CSharp, see the Analytics-CSharp migration guide.
Getting Started
Client-side vs Server-side
The best analytics installation combines both client-side and server-side tracking. A client-side analytics.js installation allows you to install A/B testing, heat mapping, session recording, and ad optimization tools. A server-side .NET installation allows you to accurately track events that aren’t available client-side, such as payments. For best practices, check out Segment’s guide to client-side vs. server-side.
Step 1: Add Analytics.js to your ASP.NET Master Page
- In your Segment workspace, click Catalog, and search for “Net”.
- Click the .Net tile, then click Add Source.
- Give the new source a label (which you’ll use to identify it later), and apply any labels such as
prod
ortest
.
You will then be presented with an Analytics.js snippet.
Copy the snippet directly into your ASP.NET Site.master.
That snippet will load analytics.js
onto the page asynchronously, so it won’t affect your page load speed.
As soon as that snippet is running on your site, you can start turning on any destinations on your Segment destinations page. In fact, if you reload, you can start seeing Page calls in the source debugger.
For more in depth analytics.js
information, check out Segment’s analytics.js docs.
Lots of analytics and marketing tools want to know more information about your users, and what they’re doing on your app. In the next section, Segment installs the .NET library and start sending an event every time a new user registers on your site.
Step 2: Install Segment’s .NET Library
Your website will use Segment’s .NET library to Identify and Track users. You can use NuGet to install the library.
Install-Package Analytics -Version <version>
Note: the Analytics package has a dependency on Newton.JSON.
You can also accomplish the same thing in the Visual Studio Tools
menu, select Library Package Manager
and then click Package Manager Console
.
Now the .NET library needs to know which Segment project you want to send data to. You can initialize the library with your Segment source’s writeKey
in the Global.asax file. Then you can use the Analytics
singleton in any controller you want:
<%@ Application Language="C#" %>
<%@ Import Namespace="ASP.NET_Example" %>
<%@ Import Namespace="System.Web.Optimization" %>
<%@ Import Namespace="System.Web.Routing" %>
<%@ Import Namespace="Segment" %>
<script runat="server">
void Application_Start(object sender, EventArgs e)
{
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
// this is your project's write key
Segment.Analytics.Initialize("x24b2rmtvv");
}
</script>
using Segment;
// initialize the project #{source.owner.login}/#{source.slug}...
Analytics.Initialize("YOUR_WRITE_KEY");
You only need to initialize once at the start of your program. You can then keep using the Analytics
singleton anywhere in your code.
The default initialization settings are production-ready and queue messages on another thread before sending any requests. In development you might want to use development settings.
Regional configuration
For Business plans with access to Regional Segment, you can use the host
configuration parameter to send data to the desired region:
- Oregon (Default) —
api.segment.io/
- Dublin —
events.eu1.segmentapis.com/
Identify
Good to know: For any of the different methods described on this page, you can replace the properties and traits in the code samples with variables that represent the data collected.
If you’re not familiar with the Segment Specs, take a look to understand what the Identify method does.
The Identify call has the following fields:
userId String |
The ID for this user in your database. |
Traits Traits, optional |
A dictionary of traits you know about the user. Things like: email , name or friends . |
options Options, optional |
A custom object which allows you to set a timestamp, an anonymous cookie id, or enable specific destinations. |
An example call would look like:
Analytics.Client.Identify("019mr8mf4r", new Traits() {
{ "name", "#{ user.name }" },
{ "email", "#{ user.email }" },
{ "friends", 29 }
});
Track
If you’re not familiar with the Segment Spec, take a look to understand what the Track method does.
The Track call has the following fields:
userId String |
The ID for this user in your database. |
event String |
The name of the event you’re tracking. Segment recommends human-readable names like Song Played or Status Updated. |
properties Properties, optional |
A dictionary of properties for the event. If the event was Product Added to cart, it might have properties like price or product . |
options Options, optional |
A custom object which allows you to set a timestamp, an anonymous cookie id, or enable specific destinations. |
An example call would look like:
Analytics.Client.Track("019mr8mf4r", "Item Purchased", new Properties() {
{ "revenue", 39.95 },
{ "shipping", "2-day" }
});
Page
If you’re not familiar with the Segment Specs, take a look to understand what the Page method does.
The Page call has the following fields:
userId String |
The ID for this user in your database. |
name String |
The webpage name you’re tracking. Segment recommends human-readable names like Login or Register. |
category String |
The webpage category. If you’re making a news app, the category could be Sports. |
properties Properties, optional |
A dictionary of properties for the webpage visit. If the event was Login, it might have properties like path or title . |
options Options, optional |
A custom object which allows you to set a timestamp, an anonymous cookie id, or enable specific destinations. |
Example Page call:
Analytics.Client.Page("019mr8mf4r", "Login", new Properties() {
{ "path", "/login" },
{ "title", "Initech Login" }
});
Screen
If you’re not familiar with the Segment Specs, take a look to understand what the Screen method does.
The Screen call has the following fields:
userId String |
The ID for this user in your database. |
name String |
The screen name you’re tracking. Segment recommends human-readable names like Login or Register. |
category String |
The screen category. If you’re making a news app, the category could be Sports. |
properties Properties, optional |
A dictionary of properties for the screen view. If the screen is Restaurant Reviews, it might have properties like reviewCount or restaurantName . |
options Options, optional |
A custom object which allows you to set a timestamp, an anonymous cookie id, or enable specific destinations. |
Example Screen call:
Analytics.Client.Screen("019mr8mf4r", "Register", new Properties() {
{ "type", "facebook" }
});
Group
If you’re not familiar with the Segment Specs, take a look to understand what the Group method does.
The Group call has the following fields:
userId String |
The ID for this user in your database. |
groupId String |
The ID for this group in your database. |
traits Traits, optional |
A dictionary of traits you know about the group. Things like: ma,e or website . |
options Options, optional |
A custom object which allows you to set a timestamp, an anonymous cookie id, or enable specific destinations. |
Example Group call:
Analytics.Client.Group("userId", "groupId", new Traits() {
{ "name", "Initech, Inc." },
{ "website", "http://www.example.com" }
});
Alias
If you’re not familiar with the Segment Specs, take a look to understand what the Alias method does.
The Alias call has the following fields:
previousId String |
The previousId for this user. |
userId String |
The ID for this user in your database. |
Example Alias call:
Analytics.Client.Alias("previousId", "userId")
Here’s a full example of how you might use the Alias call:
// the anonymous user does actions ...
Analytics.Client.Track("anonymous_user", "Anonymous Event");
// the anonymous user signs up and is aliased
Analytics.Client.Alias("anonymous_user", "identified@example.com");
// the identified user is identified
Analytics.Client.Identify("identified@example.com", new Traits() { plan: "Free" });
// the identified user does actions ...
Analytics.Client.Track("identified@example.com", "Identified Action");
Development Settings
You can use this initialization during development while testing the library. SetAsync(false)
will make sure the library makes a request to Segment’s servers every time it’s called.
Analytics.Initialize("YOUR_WRITE_KEY", new Config().SetAsync(false));
Don’t forget to set async back to true
for production, so that you can advantage of asynchronous flushing on a different thread.
Historical Import
You can import historical data by adding the timestamp
argument to any of your method calls. This can be helpful if you’ve just switched to Segment.
Historical imports can only be done into destinations that can accept historical timestamped data. Most analytics tools like Mixpanel, Amplitude, Kissmetrics, etc. can handle that type of data just fine. One common destination that does not accept historical data is Google Analytics since their API cannot accept historical data.
Note: If you’re tracking things that are happening right now, leave out the timestamp
and Segment’s servers will timestamp the requests for you.
Analytics.Client.Track("sadi89e2jd", "Workout Logged", new Properties() {
{ "distance", "10 miles" },
{ "city", "Boston" },
}, new Options()
.SetTimestamp(new DateTime(2010, 1, 18))
);
Selecting Destinations
The Alias, Group, Identify, Page, and Track calls can all be passed an object of options
that lets you turn certain destinations on or off. By default all destinations are enabled.
You can specify which analytics destinations you want each action to go to.
Analytics.Client.Identify("hj2kf92ds212", new Traits() {
{ "email", "tom@example.com" },
{ "name", "Tom Smykowski" },
}, new Options()
.SetIntegration("all", false)
.SetIntegration("Kissmetrics", true)
);
In this case, you’re specifying that you want this identify to only go to Kissmetrics. "all", false
says that no destination should be enabled unless otherwise specified, and { "Kissmetrics", true }
turns on Kissmetrics.
Destination flags are case sensitive and match the destination’s name in the docs (for example, “AdLearn Open Platform”, “awe.sm”, or “MailChimp”).
Note:
-
Business Tier users can filter Track calls right from the Segment UI on your source schema page. Segment recommends using the UI if possible since it’s a much simpler way of managing your filters and can be updated with no code changes on your side.
-
If you are on a grandfathered plan, events sent server-side that are filtered through the Segment dashboard still count towards your API usage.
Context
If you’re running a web server, you might want to send context variables such as userAgent
or ip
with your page
or screen
calls. You can do so by setting the Context
in the Options
object.
Analytics.Client.Page("019mr8mf4r", "Login", new Properties() {
{ "path", "/login" },
{ "title", "Initech Login" }
}, new Options()
.SetContext (new Context () {
{ "userAgent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36"},
{ "ip", "12.212.12.49" },
{ "language", "en-us" },
{ "Google Analytics", new Dict() {
{ "clientId", User.ClientId }
}
}
}));
Anonymous ID
All libraries require all messages to have either a userId
or anonymousId
. If you would like to use an anonymousId
, which you should for anonymous users, you can pass it in with options.
Analytics.Client.Page(null, "Login", new Properties(), new Options()
.SetAnonymousId("some-id"));
Nested Properties
You can provide nested properties, like so:
Analytics.Client.Identify("hj2kf92ds212", new Traits() {
{ "email", "tom@example.com" },
{ "name", "Tom Smykowski" },
{ "address", new Dict() {
{ "street", "123 Fake Street" },
{ "city", "Boston" }
}}
});
Batching
Segment’s libraries are built to support high performance environments. That means it is safe to use Analytics.NET on a web server that’s serving hundreds of requests per second.
By default (in async mode), this library starts a single separate thread on initialization, and flushes all messages on that thread. That means every method you call does not result in an HTTP request, but is queued in memory instead. Messages are flushed in batch in the background, which allows for much faster operation.
There is a maximum of 500KB
per batch request and 32KB
per call.
HTTP Tracking API limits
Segment's HTTP Tracking API accepts batch requests up to 500KB. To avoid errors in event creation, ensure that individual event payload sizes remain below 32KB.
How do I turn batching off?
Sometimes you might not want batching (for example, when debugging, or in short-lived programs). You can turn off batching by setting the async
argument to false
, and your requests will always be sent in a blocking manner.
Analytics.Initialize("YOUR_WRITE_KEY", new Config().SetAsync(false));
What happens if there are just too many messages?
If the module detects that it can’t flush faster than it’s receiving messages, it’ll simply stop accepting messages. This means your program will never crash because of a backing up analytics queue. The maximum size of the queue defaults to 10000
, and here’s how you can change it:
Analytics.Initialize("YOUR_WRITE_KEY", new Config().SetMaxQueueSize(10000));
How do I flush right now?!
You can also flush on demand. For example, at the end of your program, you’ll want to flush to make sure there’s nothing left in the queue. Just call the Flush
method:
Analytics.Client.Flush();
This method will block until all messages are flushed.
How do I dispose of the flushing thread at the end of my program?
The Analytics client implements the IDisposable
interface, and will turn off its flushing thread when you call Dispose
.
Analytics.Client.Dispose();
Configuration
If you hate defaults, than you’ll love how configurable the Analytics.NET is. Check out these gizmos:
Analytics.Initialize("YOUR_WRITE_KEY", new Config()
.SetAsync(true)
.SetTimeout(TimeSpan.FromSeconds(10))
.SetHost("https://events.eu1.segmentapis.com")
.SetMaxQueueSize(10000));));
async boolean |
true to flush on a different thread, false to flush immediately on the same thread. |
timeout TimeSpan |
The amount of time to wait before calling the HTTP request a timeout. |
host string |
The API host server address - can be set with the EU endpoint “https://events.eu1.segmentapis.com” instead of default server “https://api.segment.io” |
maxQueueSize int |
The maximum number of messages to allow into the queue before no new message are accepted. |
Multiple Clients
Different parts of your app may require different Segment. In that case, you can initialize different Analytics.Client
instances instead of using the singleton.
Client client = new Client("YOUR_WRITE_KEY", new Config()
.SetAsync(false)
.SetTimeout(TimeSpan.FromSeconds(10))
.SetMaxQueueSize(10000));
client.Track(...);
Troubleshooting
The following tips often help resolve common issues.
No events in my debugger
-
Double check that you’ve followed all the steps in the Quickstart.
-
Make sure that you’re calling a Segment API method once the library is successfully installed—
identify
,track
, etc. -
Make sure your application isn’t shutting down before the
Analytics.Client
local queue events are pushed to Segment. You can manually callAnalytics.Client.Flush()
to ensure the queue is fully processed before shutdown.
Other common errors
If you are experiencing data loss from your .NET source, you may be experiencing one or more of the following common errors:
-
Payload is too large: If you attempt to send events larger than 32KB per normal API request or batches of events larger than 500KB per request, Segment’s tracking API responds with
400 Bad Request
. Try sending smaller events (or smaller batches) to correct this error. -
Identifier is not present: Segment’s tracking API requires that each payload has a
userId
and/oranonymousId
. If you send events without either theuserId
oranonymousId
, Segment’s tracking API responds with anno_user_anon_id
error. Check the event payload and client instrumentation for more details. -
Track event is missing name: All Track events to Segment must have a name in string format.
-
Event dropped during deduplication: Segment automatically adds a
messageId
field to all payloads and uses this value to deduplicate events. If you’re manually setting amessageId
value, ensure that each event has a unique value. -
Incorrect credentials: Double check your credentials for your downstream destination(s).
-
Destination incompatibility: Make sure that the destination you are troubleshooting can accept server-side API calls. You can see compatibility information on the Destination comparison by category page and in the documentation for your specific destination.
-
Destination-specific requirements: Check out the destination’s documentation to see if there are other requirements for using the method and destination that you’re trying to get working.
Logging
Analytics.NET
has detailed logging, which you can enable by attaching your own handler, like so:
using Segment;
Logger.Handlers += LoggingHandler;
static void LoggingHandler(Logger.Level level, string message, IDictionary<string, object> args)
{
if (args != null)
{
foreach (string key in args.Keys)
{
message += String.Format(" {0}: {1},", "" + key, "" + args[key]);
}
}
Console.WriteLine(String.Format("[Analytics] [{0}] {1}", level, message));
}
Note: the logger requires a minimum version of .NET Core 2.1.
Json.NET
Analytics.NET
uses Json.NET to serialize JSON payloads. If you have an older version of Json.NET
in your build path, Analytics.NET
could create incomplete JSON payloads, which can cause strange API responses. If you’re seeing issues, try updating Json.NET
.
Mono
Analytics.NET
has been tested and works in Mono.
.NET Core
Analytics.NET
has been tested and works with .NET Core 3.1 and 3.4.2 beta.
This page was last modified: 30 May 2024
Need support?
Questions? Problems? Need more info? Contact Segment Support for assistance!