I'm working on implementing the Segment analytics hub on an existing .NET e-commerce application for use with Mixpanel, among a few other services. I understand the API docs in general for both Analytics.js and the Segment .NET API, but I am confused how to connect anonymous events to the same user.
For example, say I am tracking that an item is added to the cart. I am doing this server-side, as there are multiple pages that items can be added to the cart but only one controller. A user can do this without logging in, and we are assigning them a customer ID already, so my code looks something like this:
Analytics.Client.Track(cartItem.CustomerId, "Added Product", new Properties() {
{ "sku", cartItem.Sku },
{ "quantity", quantity }
});
Then, say the user views a product category page. Since this is a relatively trivial action, I am currently doing it client-side, so my code looks something like this:
analytics.track('Viewed Product Category', {
category: '@Model.CategoryName',
subCategory: '@Model.SubCategoryName'
});
I see in the Analytics.js spec:
You won’t need to call identify for anonymous visitors to your site. We’ll automatically assign them an anonymousId, so just calling page and track will still work just fine without identify.
My main question is, how do I tell Segment that it was the same (currently anonymous) user that performed both of these actions? As a secondary question, do I need to call Identify before the server-side call, even though the Track call includes a user id?
I work at Segment. Tying anonymous activity across client and server-side calls with Segment is tricky, for a few reasons:
Segment's server-side libraries are totally stateless and naive to the request context, so it's up to you to grab the relevant information and pass it through in the call to Segment.
Moreover, on the client, the bundled 3rd party tools you've integrated with will be managing their respective anonymous/session identifiers themselves.
Some server side integrations have a special context
field for their anonymous identifier, (like GA), but most don't, so you'll need to write a wrapper that abstracts over the example case below (sending multiple calls with different anonymousId
s while dictating which should be sent to which service).
Note: The customerId
approach will work if that will remain their unique identifier even after purchase, so that you can always use that as the userId
. But it's worth bearing in mind if you intend to use it as an intermediary pseudo-anonymous identifier that not all tools have the ability to alias multiple IDs, so you might not be able to keep cohesive user profiles in all your tools if you take that approach.
But accomplishing this effectively in the case when you don't have a de-facto userId
(which I imagine will be the case for other folks who arrive @ this question) is really a question of which tools you're using; for each of them, you'll need to grab their respective anonymous identifier off the request (they're typically available in cookies) and attach it to its respective field in the server side call to Segment.
Here's how that might look if you're using KISSmetrics, Mixpanel and Google Analytics:
str gaClientId, kmAnonId, mpAnonId;
HttpCookieCollection cookies = Request.Cookies;
//GA clientId is stored as part of the _ga cookie
if (cookies["_ga"] != null)
{
string gaCookie = Request.Cookies["_ga"];
string[] parts = gaCookie.Split('.')
gaClientId = Strint.Format("{0}.{1}", parts[2], parts[3])
}
// KM anonId
if (cookies["km_ai"] != null)
{
kmAnonId = Request.Cookies["km_ai"];
}
// for brevity, I'll omit retrieving mixpanel distinctId
// from their cookie. You will need to serialize the value of
// "mp_<acesstoken>_mixpanel" to JSON and take the `distinct_id` value
// see here: http://marcmezzacca.com/integrating-mixpanel-with-asp-net-mvc-server-side-and-javascript-client-side/
Analytics.Model.Options kmCallOptions = new Options()
.SetIntegration("all", false)
.SetIntegration("Kissmetrics", true)
.SetIntegration("Google Analytics", true)
.SetContext (new Context () {
{ "ip", GetUserIP() },
{ "Google Analytics", new Dict() {
{ "clientId", gaClientId }
}
},
{ "AnonymousId", kmAnonId }
}
});
Analytics.Model.Options mpCallOptions = new Options()
.SetIntegration("all", false)
.SetIntegration("Mixpanel", true)
.SetContext (new Context () {
{ "ip", GetUserIP() },
},
{ "AnonymousId", mpAnonId }
}
});
// Send to KM and GA
Analytics.Client.Track(null, "Added Product", new Properties() {
{ "sku", cartItem.Sku },
{ "quantity", quantity }
}, kmCallOptions);
// Send to Mixpanel
Analytics.Client.Track(null, "Added Product", new Properties() {
{ "sku", cartItem.Sku },
{ "quantity", quantity }
}, mpCallOptions);
One quick note: Segment definitely intends to pave over this headache and make life easier in accomplishing this, but rather than complicating the API to accommodate multiple anonymous identifiers per tool we intend to solve the problem in a manner that obviates the need for that entirely. In the interim, to avoid the complexity, we really recommend keeping all your anonymous tracking in one place, either server-side (using a sessionId or the like for the anonymousId) or (preferably) client side. If you want to mix and match, server side tracking is best reserved for logged in users with a userId.
Also, don't ever hesitate to contact support directly @ friends@segment.com!