segmentio / analytics.net Goto Github PK
View Code? Open in Web Editor NEWThe hassle-free way to integrate analytics into any C# / .NET application.
Home Page: https://segment.io/libraries/.net
License: MIT License
The hassle-free way to integrate analytics into any C# / .NET application.
Home Page: https://segment.io/libraries/.net
License: MIT License
https://github.com/segmentio/spec
anonymousId
from sessionId
for clarity.integrations
(was providers
) object from context
, for cleaner logs.requestId
for easily tracing calls through to the raw logs.library
to be a object with name
and version
for consistency.When using 'track' or 'identify', write key is also displayed in the segment event data.
Is there a specific reason for this?
I understand that write key is required to make an authentication token while posting to Segment API endpoint. But it only needs to be in the http-client headers. Or is there something I am missing here?
Is it possible to publish a non-alpha version of the Nuget package? We're getting build warnings because were dependant on an alpha version of your package. Unfortunately 3.0 (the last non alpha version) is not suitable for us because we need the newer .net standard support.
If it helps we've been using the package along with over 12,000 other people without issue: https://www.nuget.org/packages/Analytics/
Thanks
Hello,
Is it possible to use Analytics.NET with ASP.NET MVC as an ActionFilter?
Thank You,
Miguel
In order to get the fix for #156, I used version 3.7.0 of Analytics.Net
. Unfortunately, I still get some errors that tell me that messages are lost.
First, here's what my Failed
callback looks like:
private void Initialize()
{
// ...
client = new SegmentSdk.Client(...);
client.Failed += LogFailure;
// ...
}
private void LogFailure(SegmentSdk.Model.BaseAction action, Exception e)
{
string details = null;
if (e != null)
{
details = e.Message;
}
_logger.LogError(LoggingEvents.SegmentFailure, e, $"Failed to send analytic event {action.Type} for user {action.UserId} and message {action.MessageId} to segment.io server. Details: {details}");
}
With this, I got these error logs after a few hours:
Failed to send analytic event track for user 831ba960-a73c-49b7-be6b-771d2233ce2d and message 5c72ec76-0044-407b-8c69-9a8c3edb9aef to segment.io server. Details: Status Code: 0, Message: Has Backoff reached max: True with number of Attempts:8,
Status Code: 0
, response message:
Segment.Exception.APIException: Status Code: 0, Message: Has Backoff reached max: True with number of Attempts:8,
Status Code: 0
, response message:
Failed to send analytic event identify for user 831ba960-a73c-49b7-be6b-771d2233ce2d and message 2a2d3b52-2b01-4b21-9178-4876f1e725e8 to segment.io server. Details: Status Code: 0, Message: Has Backoff reached max: True with number of Attempts:8,
Status Code: 0
, response message:
Segment.Exception.APIException: Status Code: 0, Message: Has Backoff reached max: True with number of Attempts:8,
Status Code: 0
, response message:
Is there anything that I could do to help you troubleshoot this?
In order to get the fix for #156, I used version 3.6.0 of Analytics.Net
. Unfortunately, I still get some errors that tell me that messages are lost.
First, here's what my Failed
callback looks like:
private void Initialize()
{
// ...
client = new SegmentSdk.Client(...);
client.Failed += LogFailure;
// ...
}
private void LogFailure(SegmentSdk.Model.BaseAction action, Exception e)
{
string details = null;
if (e != null)
{
details = e.Message;
if (e is SegmentSdk.Exception.APIException apiException)
{
details = $"Code={apiException.Code}, message={apiException.message}, Message={apiException.Message}";
}
}
_logger.LogError(LoggingEvents.SegmentFailure, e, $"Failed to send analytic event {action.Type} for user {action.UserId} and message {action.MessageId} to segment.io server. Details: {details}");
}
With this, I got these error logs:
timestamp | "json.message"
-- | --
2021-03-12 02:02:53.419 -05:00 | Failed to send analytic event track for user e0f68aac-7b92-4703-85d3-d967354a5f0a and message 7559433d-46fb-435a-9c50-3bc550cf1e9b to segment.io server. Details: Code=Unexpected Status Code, message=, Message= Segment.Exception.APIException
2021-03-12 02:02:53.338 -05:00 | Failed to send analytic event identify for user e0f68aac-7b92-4703-85d3-d967354a5f0a and message 25935a15-91e1-4fc9-8e0c-ccadaac0fe30 to segment.io server. Details: Code=Unexpected Status Code, message=, Message= Segment.Exception.APIException
2021-03-12 02:02:53.256 -05:00 | Failed to send analytic event track for user e0f68aac-7b92-4703-85d3-d967354a5f0a and message a1ab9ca6-a4fc-4231-b635-7df0ca46a9a7 to segment.io server. Details: Code=Unexpected Status Code, message=, Message= Segment.Exception.APIException
2021-03-12 02:02:53.172 -05:00 | Failed to send analytic event identify for user e0f68aac-7b92-4703-85d3-d967354a5f0a and message 4c28eca2-5f10-4918-bec3-713b40db1160 to segment.io server. Details: Code=Unexpected Status Code, message=, Message= Segment.Exception.APIException
2021-03-12 00:22:59.675 -05:00 | Failed to send analytic event track for user 9ef95e43-c067-46f0-be51-d1587824095a and message 8417e505-4dad-4f58-af94-deda74882d30 to segment.io server. Details: Code=Unexpected Status Code, message=, Message= Segment.Exception.APIException
2021-03-12 00:22:59.672 -05:00 | Failed to send analytic event identify for user 9ef95e43-c067-46f0-be51-d1587824095a and message 097f39e5-dd64-4b9f-8ed9-daec648471be to segment.io server. Details: Code=Unexpected Status Code, message=, Message= Segment.Exception.APIException
2021-03-11 22:24:33.093 -05:00 | Failed to send analytic event track for user eb845629-2532-4a27-8786-8c37b8413c7a and message bf41100a-72b0-4769-adc0-db659de47522 to segment.io server. Details: Code=Unexpected Status Code, message=, Message= Segment.Exception.APIException
2021-03-11 22:24:33.091 -05:00 | Failed to send analytic event identify for user eb845629-2532-4a27-8786-8c37b8413c7a and message f0052abf-1627-41fd-824b-df59ef6a674c to segment.io server. Details: Code=Unexpected Status Code, message=, Message= Segment.Exception.APIException
These errors come from this code:
On top of fixing the issue, I highly suggest a few code improvements:
message
property in APIException
. It is a duplicate of the Message
property in the base class.APIException
class so that the value of Code
ends up diplayed by ToString()
. Here's an example of how to do it:public class APIException : System.Exception
{
public string Code { get; set; }
public APIException(string code, string message) : base($"{code}: {message}")
{
this.Code = code;
}
}
APIException
to include more details. For examples, here's the critical piece of code that should be enhanced:if (_backo.HasReachedMax || statusCode != (int)HttpStatusCode.OK)
{
var message = $"has reached max = {_backo.HasReachedMax}, statusCode = {statusCode}, response={responseStr}";
Fail(batch, new APIException("Failed to send message", message), watch.ElapsedMilliseconds);
if (_backo.HasReachedMax)
{
_backo.Reset();
}
}
responseStr
is initialized in all error scenarios (including the missing else
):Logger.Handlers
whenever there is a retry in that loop.Without these changes, we are in the dark and I can't help you with proper logs.
How do I track events retroactively?
eg. I want to send now an event that happened last week
When using Analytics.NET
version 3.4.2-beta, I found out thta a few analytics events per hour are not successfully sent to the segment servers. To troubleshoot this, I configured the Segment.Client.Failed
callback:
private void LogFailure(SegmentSdk.Model.BaseAction action, Exception e)
{
_logger.LogError(e, $"Failed to send analytic event {action.Type} for user {action.UserId} to segment.io server");
}
myClient.Failed += LogFailure;
With this in-place, I now see this error log pop-up a few times per hour. Here's what the error looks like this (The response ended prematurely
):
Failed to send analytic event track for user c08cb1fb-f963-4238-b075-570f08a88892 to segment.io server
System.Net.Http.HttpRequestException: An error occurred while sending the request.
---> System.IO.IOException: The response ended prematurely.
at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.SendWithNtConnectionAuthAsync(HttpConnection connection, HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.DiagnosticsHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
at Segment.Request.BlockingRequestHandler.MakeRequest(Batch batch)
From what I can see, the events are then completely lost. The consequence of this are pretty bad for us:
Identify
to set a few traits on the user.Chameleon is also used to create some on-boarding flows. Since the traits are not always sent correctly, it means that some users see the wrong on-boarding flows.
After looking at the Analytics.NET code, I can see that all unexpected exceptions are not retried:
So my question is:
This would clearly help in having more accurate analytics.
Regards,
Maxime
Since a picture is worth a thousand words:
I believe I'm doing this by the book, so pretty sure it's not a problem with my code...
The result is that these events (which are only supposed to go to Google Analytics) are ending up in the dashboards for other analytics providers.
Am I doing something stupid here?
It looks like the versions that support .NET Core have been in alpha for more than a year.
Is there any plan to release them as stable versions?
The pull request #96 proposes a change to account for Network related exceptions when attempting to send the batches. The current code does not account for the exceptions thrown by the PostAsync method and could result on some batches not being sent in those cases. The pull request proposes a retry if failed approach in order to solve the issue.
.NET documentation on PostAsync : https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient.postasync?view=net-5.0
The #96 is a 2 year old pull request which merging it to our current version of the code will lead to conflicts that will need to be resolved. It's not recommended to do so, since it's logic as well has not evolved as our current versions.
Alias
alias combines two previously unassociated user identities. This comes in handy if the same user visits from two different devices and you want to combine their history.
Source https://segment.io/libraries/analytics.js/
Can we have this in .net too please!
Analytics.Client.Flush(Async=false)
After many years of using Segment, I just realized that we sometimes call the "Identify" or "Track" method and events are lost because of this code (note that we are using version 3.3.1-alpha):
So no exceptions are raised. There is only a warning being triggered. Pretty annoying. For me, it's like doing an SQL INSERT where the database answered "success" when in fact it did "well you know, I was too busy. I just dropped your request... without letting you know. Oh yeah, I sent you a letter about it. If you're lucky you will receive it. But note that the letter will not let you know what I dropped exactly. It will just let you know that I was too busy."
What is your suggestion to make sure that no events are lost?
class Client
has a number of methods which accept userId
and a second parameter which varies from one method to another. Validation code uses line like this to throw:
throw new InvalidOperationException("Please supply a valid userId or anonymousId to SOMETHING.");
and
throw new InvalidOperationException("Please supply a valid PARAMNAME to SOMETHING");
Although only method names should differ the actual wording for SOMETHING is inconsistent.
Group()
says to call #Group
for both checks.Track()
says to Track
- no "call" and no #
.Page()
says to #Page
- no "call"Screen()
says to #Screen
- no "call"Ticket Ref:
https://segment.zendesk.com/agent/tickets/33879
You have mismatch in your nuget package dependencies declaration and what the real dependency your dll uses
Here you from source
<Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net35\Newtonsoft.Json.dll</HintPath>
</Reference
Here is you package dependency
<dependencies>
<group targetFramework=".NETFramework3.5">
<dependency id="Newtonsoft.Json" version="4.5.11" />
</group>
</dependencies>
Using the 19 August head (9912dc4). (But this didn't work with the 1.1. version released on nuget either.)
Given:
Segmentio.Analytics.Client.Identify("100", new Traits() { {"firstName", "Vincent"}, {"lastName", "Vangogh"}, {"email", "[email protected]"} }, new Context().SetIp("71.198.218.39"));
Then in BlockingRequestHandler.cs, line 30:
string json = JsonConvert.SerializeObject(batch, settings);
json lack the contents of the context we just set:
{
"secret": "--------",
"batch": [{
"action": "identify",
"userId": "100",
"traits": {
"firstName": "Vincent",
"lastName": "Vangogh",
"email": "[email protected]"
},
"timestamp": null,
"context": {} <----------------
}],
"context": {
"library": "analytics-.NET"
}
}
At this point in the code, the "batch" has 2 Context objects: The one that is a direct property of "batch" has this library property, and makes it out to the json. However the other one, the one inside which has the Identify has the IP, Language, and Providers, does not make it out into the json, and is not transmitted to segmentio.
The cause is a well-known (disputed) bug in json.net: http://json.codeplex.com/workitem/23769.
In testing Segment Analytics on mobile devices under Xamarin, I've noticed any events that occur while the device is offline are discarded. It appears the event queue is being flushed even if the events fail to send to segment.io.
[Analytics] [DEBUG] Dequeued action in async loop. message id: d0fe64a7-7715-465a-bf4a-08f8189dba3d, queue size: 0,
[Analytics] [DEBUG] Created flush batch. batch size: 1,
[Analytics] [INFO] Sending analytics request to Segment.io .. batch id: f552873c-7656-485c-83e9-f79c22c15809, json size: 513, batch size: 1,
[Analytics] [DEBUG] Enqueued action in queue. queue size: 0,
[Analytics] [INFO] Segment.io request failed. batch id: f552873c-7656-485c-83e9-f79c22c15809, reason: Error: ConnectFailure (Network is unreachable), duration (ms): 0,
[Analytics] [DEBUG] Queue is empty, flushing is finished.
In a server environment this might not be a big deal but on mobile devices which frequently lose connection it seems a more robust queuing strategy is needed. Other analytics libraries I've used such as Xamarin Insights and Google Analytics have this capability.
We experienced some events created on Thursday Sep. 3'rd that they where timestamped as March 9'th.
The error is due to bad formatted datetime sent by BaseAction.cs
If Timestamp is set it will send the data as Timestamp.ToString() instead of .ToString("o") as when it has not been set.
if (options.Timestamp.HasValue)
this.Timestamp = options.Timestamp.ToString ();
else
this.Timestamp = DateTime.Now.ToString("o");
https://github.com/segmentio/Analytics.NET/blob/master/Analytics/Model/BaseAction.cs#L39
Two suggestion for improving the nuget metadata in Analytics.csproj
.
Replace PackageLicenseFile
with <PackageLicenseExpression>MIT</PackageLicenseExpression>
This makes it more visible that the packages is released under the MIT license.
Add
<RepositoryUrl>https://github.com/segmentio/Analytics.NET.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
This adds a link from nuget.org directly to the github repository.
Hey, thanks for posting a new version on nuget!
I have been trying to use this package for a netcore1.0 library and the only way I currently can do it is to clone this repo and pull the Analytics project directly into my solution. For build to production sake, I'd like to pull in the nuget package instead.
When I try to reference the 3.0.0 nuget package, it throws this error:
Restoring packages for xxx.csproj...
GET http://nuget/nuget/FindPackagesById()?id='Analytics'
GET https://api.nuget.org/v3-flatcontainer/analytics/index.json
OK http://nuget/nuget/FindPackagesById()?id='Analytics' 6ms
OK https://api.nuget.org/v3-flatcontainer/analytics/index.json 284ms
GET https://api.nuget.org/v3-flatcontainer/analytics/3.0.0/analytics.3.0.0.nupkg
OK https://api.nuget.org/v3-flatcontainer/analytics/3.0.0/analytics.3.0.0.nupkg 193ms
Installing Analytics 3.0.0.
Package Analytics 3.0.0 is not compatible with netcoreapp1.0 (.NETCoreApp,Version=v1.0). Package Analytics 3.0.0 supports: net (.NETFramework,Version=v0.0)
Package restore failed. Rolling back package changes for 'xxx'.
Time Elapsed: 00:00:01.0880009
It appears the project config/csproj file is correct at targeting the netstandard1.3, but the nuspec file needs to be updated to allow for the newer frameworks to be targeted.
Here's the definition of Statistics
:
public class Statistics
{
public int Submitted { get; set; }
public int Succeeded { get; set; }
public int Failed { get; set; }
}
All members are signed. The typical line of code dealing with them looks like this:
_client.Statistics.Failed += 1;
If code runs long enough then counters may reach Int32.MaxValue
. Depending on whether code runs in checked or unchecked context subsequent behavior varies. If code happens to run in unchecked context then counters overflow and become negative which makes no sense. If code happens to run in checked context then subsequent increments fail with OverflowException
.
Counters should be unsigned. Code manipulating them should be explicitly wrapped in unchecked {}
.
Hi,
We have an ASP.NET Core server running on Azure with analytics.NET 3.3.0-alpha, and it's configured to send user events to Segment using Analytics.Client.Track(). It's initialized using this line:
Analytics.Initialize(
apiKey,
new Config().setAsync(true).SetTimeout(100).SetMaxQueueSize(10000));
After a while (around 1h or so) segment stops confirming the reception of the tracked events. There are no new entries in the debug panel, meaning they don't arrive to Segment. It all starts working when we republish the app, probably because the program restarts.
For instance, this is the last event that was successfully sent a couple of days ago:
2018-07-03 07:53:42,915 36 INFO Analytics - Segment.io request successful.
batch id: c5a1b751-c683-430b-b31d-5c30bb0eacf0
duration (ms): 87
2018-07-03 07:53:42,916 5 DEBUG Analytics - Queue is empty, flushing is finished.
2018-07-03 07:53:43,738 59 DEBUG Analytics - Blocking flush waiting until the queue if fully empty ..
2018-07-03 07:53:43,739 59 DEBUG Analytics - Blocking flush completed.
2018-07-03 07:53:55,741 59 DEBUG Analytics - Enqueued action in queue.
queue size: 1
2018-07-03 07:53:55,741 5 DEBUG Analytics - Dequeued action in async loop.
message id: 4766d95e-d101-4215-a935-ca942e955559
queue size: 0
2018-07-03 07:53:55,742 5 DEBUG Analytics - Created flush batch.
batch size: 1
2018-07-03 07:53:55,743 59 DEBUG Analytics - Enqueued action in queue.
queue size: 1
After that, no matter what we do, segment says "sending request" but never says "request successful" again:
2018-07-03 07:53:55,743 5 INFO Analytics - Sending analytics request to Segment.io ..
batch id: cd65ad4c-6ea3-43c9-b030-22205ac7a7a2
json size: 448
batch size: 1
Could this be related to #83 ? We also contacted Segment support, so I'll update this issue when we have more details.
Thanks!
Miguel
We use some integrations that take advantage of identify calls without user id's (Drip, Salesforce). These work fine in Analytics.js, but this .NET client throws an InvalidOperationException if you attempt to call Identify without the userId parameter. Is there some way to mimic the behavior in Analytics.JS so we can call this before we have a User Id in our system?
See here: https://www.nuget.org/packages/Analytics/
Look at version history.
For people using .NET Core (pretty much all new greenfield development) they're going to get warnings like this:
[NU1701] Package 'Analytics 3.0.0' was restored using '.NETFramework,Version=v4.6.1' instead of the project target framework '.NETCoreApp,Version=v2.1'. This package may not be fully compatible with your project.
It's been two years, might as well take the alpha off.
Developing a Windows 10 Phone App, using the Universal Windows Platform and installing with NuGet results in this error:
"Install-Package : Analytics 2.0.2 is not compatible with UAP,Version=v10.0."
a customer was asking about it earlier, would make the interface for adding traits a bit nicer.
would solve this kind of thing:
Analytics.Client.Track("hj2kf92ds212", "ate a bagel",
new Context() {
{ "traits", new Props() {
{ "email", "[email protected]" }
}
}
}
});
Hi,
My company is using your library in a console that we run as a nightly job. Today I noticed that the background job no longer shuts down properly. After running NewRelic's thread profiler in production I noticed that thread that was still running:
System.Threading.ThreadHelper:ThreadStart
System.Threading.ExecutionContext:Run
System.Threading.ExecutionContext:Run
System.Threading.ExecutionContext:RunInternal
System.Threading.ThreadHelper:ThreadStart_Context
Segmentio.Flush.AsyncFlushHandler:Loop
Segmentio.Flush.BlockingQueue`1:Dequeue
System.Threading.Monitor:Wait
System.Threading.Monitor:Wait
I'm guessing that this thread is not running with IsBackground set to true? http://msdn.microsoft.com/en-us/library/system.threading.thread.isbackground(v=vs.110).aspx
I'd very much appreciate if you would change that. Thanks!
Get JavascriptSerializer to work
Why is the assembly (Analytics.dll) not signed?
I really like to control which providers the events are sent to, I found this in the docs:(https://segment.io/docs/methods/identify)
You can control which providers the identify goes to using the context.providers variable.
But it seems the Model.context in the .net library only SetIP / SetLanguage. Any workaround?
the spec developed and deployed with the iOS SDK: https://gist.github.com/reinpk/7bd33d29694578b06cce (ignore the requestTimestamp on batch flushing since we don't want to correct timestamps coming from a server)
Hello,
It would be greate to support .NETStandard,Version=v1.4 :)
Thank you,
Lapinou.
Currently, consumers of this library have to either use or extend the Dict
/Properties
/Traits
classes in order to call Segment client methods. This adds unnecessary complexity and an explicit dependency on Segment, not to mention violating the I in SOLID. ๐
I'd like to see this changed to only require the dictionary interface (IDictionary<string, object>
) for Segment methods instead of the concrete classes. This way, we can pass in custom dictionary objects or just a regular Dictionary
without having to derive from a class provided by Segment.
See also:
"Why not inherit from List?"
http://stackoverflow.com/a/21694054/102351
"Is it correct to use inheritance instead of name aliasing in c#?"
http://stackoverflow.com/q/147049/102351
"C#: How to create 'aliases' for classes"
http://stackoverflow.com/q/7082238/102351
An example of Segment.NET library being used on an F# project should be developed in order to understand it can be called perfectly well with its different functions
On nuget.org, I see that the latest version of the library is 3.4.1-alpha. Unfortunately, there is no tag in github for this version. It is therefore impossible to look at the code at this exact version:
> git tag --list
2.0.0
2.0.1
2.0.2
2.0.3
3.0.0
3.1.0-alpha
3.2.0-alpha
3.3.0-alpha
3.3.1-alpha
3.4.0-alpha
Its been a couple of months-ish since clfetchers original question so I thought I'd ask again. Those of us that really need .net standard support would really like to see a non-alpha library for Segment up on Nuget, is this something you could see happening in the near future?
I can see some quite sensible PRs from daletskyi that are waiting for approval still. Perhaps we could at least have a 3.4.0 alpha library on nuget with those fixes in?
@f2prateek @Dmitry-Me I think there are some problems with PR #41. Adding the unchecked
blocks is unnecessary, but harmless, since the default behavior is to silently overflow:
For non-constant expressions (expressions that are evaluated at run-time) that are not enclosed by any checked or unchecked operators or statements, the default overflow checking context is unchecked unless external factors (such as compiler switches and execution environment configuration) call for checked evaluation.
checked
However, changing the properties from int
to uint
will break CLS compliance (MSDN), which is a huge deal for a library project. As of this change, any code written in a .NET language that doesn't support uint
s will break on reference once this goes out.
I'm trying to see how I could update my .NET server-to-server code to send the Segment Identify and Track requests through a proxy.
We're moving to a more secure environment that requires outbound calls from the API server to pass through a proxy. Thank you for the info; we love Segment!
Ryan
What's the current state of this library with respect to Xamarin support? Can we test it to see what can be done to make this work? Or does it already support Xamarin after the last few updates?
In order to get the fix for #163, I used version 3.7.1 of Analytics.Net. Unfortunately, I still get some errors that tell me that messages are lost.
I attached about 2000 logs coming from the Analytics.net library. I hope this can help you to isolate the problem.
Hi,
The client library is very well made, but it's currently impossible to add destinations specific option.
In my particular case, I want to be able to add or remove a Tag when using the Identify call and Vero destination. In the documentation it says to pass an object called tags
in the Vero integration object for example:
analytics.identify('324LKJF', {
email: '[email protected]'
}, {
integrations: {
Vero: {
tags: {
id: '235FAG', // This is optional! If not defined, we default to the event's userId (ie: 324LKJF)
action: 'add',
values: ['warriors', 'giants', 'niners']
}
}
}
})
But the .NET library only support setting an individual integration to true
or false
via the SetIntegration("Vero", true)
method.
It would be nice to not have to call the HTTP API endpoint in order to succesfully pass the tags.
Thanks
class Client
has a number of public methods and they all verify userId
. Most of them use this line to signal the userId is invalid:
throw new InvalidOperationException("Please supply a valid userId or anonymousId to SOMETHING.");
here anonymousId
is spelled in camelCase. But Group()
uses this string:
throw new InvalidOperationException("Please supply a valid userId or anonymousID to call #Group.");
here anonymousID
is spelled with ID
rather than with Id
as in other methods. This serves no good purpose, this is simply a typo.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.