segmentio/analytics.js — pull request #148 by ianstormtaylor (2013-05-03 20:02:32+00:00)
Title: added an analytics.group method for associating groups of users

Okay, we're starting to see APIs that offer the ability to group multiple numbers of users into single "accounts" or "companies" or "projects", so this is a stab at an API that lets that happen.

I think it's a pretty necessary thing for our API to handle, because groups of users are a core "objects" in lots of the providers we integrate with. And the more important part, they are core "objects" in almost every SaaS app, and lots of others. From the Totango docs:

> Users and Accounts are core objects in the Totango data model.

I think other players who currently don't do this, like Mixpanel or KISSmetrics will want to do it in the future if they want to get enterprise-style customers.

So with that in mind, I'll walk through the rest of the decisions' justification...

### Why `group`?
First the name. I decided to go with `group` for a couple reasons. The very first of which, which is less important but still nice is it's nice to have methods be verbs, which is why you have things like `identify` and `track` instead of `user` and `event`. In this case, `group` is a verb and noun so that's a plus. But that's a horrible reason by itself, so moving on...

The big reason is that this feature is for associating multiple users in general, and I want it to be abstract enough to cover the cases we will need it to cover. The only other alternative that was presented was `account`. Account has a strong argument, because a lot of people use that terminology for creating their associations between users. Salesforce does, Totango does, I'm not sure but I assume Marketo and lots of the other enterprise integrations do.

So going with `account` seems natural, but it forces us into a place I don't think we want to be because it is a specific term. For example on Segment.io, we call them "Projects" not "Accounts", and Github calls them "Organizations". Other analytics APIs use different terms too, for example Intercom calls them "Companies". So everyone can potentially call them different things, and my argument is that `group` is a nice word that can take on any of those meanings in the future.

The other problem with the word "account" is that it is already overloaded in B2C companies. They freely interchange "user" and "account". For example, Facebook might ask you to "setup your free account today", when they aren't talking about multiple users at all. There's proof of this confusion in the Totango docs already:

> If your web-application is a “B2C app”, you probably do not have a distinction between a user and an account. They are one of the same. In this case, you should use the user’s email address as the account:id as shown in the example below: ...

I think "account" introduces unnecessary confusion when talking about the API. Whereas you will never get confused that `group` might refer to a single user.

### The API.
I've made the API for `group` almost identical to `identify`. It takes a `groupId` and `properties`, just like `identify` takes a `userId` and `traits`. We only user `traits` to describe things on individual users.

The only difference is that `groupId` is required, whereas `userId` is not. That's because I don't really think it's a valide use case to not know the group's ID, whereas having an anonymous user is much more valid. Making it required means we reduce scope by not having to implementing sessioning/cookieing for groups as well. And we can always make it optional in the future anyways.

Another thing to remember: users can belong to multiple groups. That is a mental requirement for our API, that doesn't mean that every provider will support this. But realistically in the use cases in businesses, they will want this functionality, so we should build with this in mind. If a provider can't support it, we'd implement a provider-level workaround to only call it the first time. Otherwise, assume that we can call `group` multiple times (for each Segment.io project for instance).

### Must come after identify.
This is another restriction that I came up with only after starting to implement it. I realized that most of the time you are directly reliant on the user to be able to place them inside a group. (Because no one really wants to build the ability for anonymous merging of users inside groups.) So in the docs and everything, we will tell people that you `identify` first, then `group`. Technically, they could do `group`, `identify`, but some providers might break for that. For example, Totango needs the `userId` to make add the user to a group. I think that makes sense. It's also future-compatible with removing the requirement.

### Providers that don't support it natively.
The other thing that we can do that will be very nice for people is to add a bit of "grouping" functionality for providers that don't support it. The way we'd do this is to add a nested `group` trait to the user with the properties of the group. So the direct translation would be like this:

```js
analytics.group('group', {
name : 'Segment.io',
teammates : 5
});

analytics.identify({
group : {
id : 'group',
name : 'Segment.io',
teammates : 5
}
});
```

That way, in Mixpanel you can see `group.name` and `group.id` and other properties as traits of the user. And we'd only do this for providers that it makes sense for, where you'd actually want to see group information in traits.

---

Okay that's it. Let me know if you guys have objections or if you see any bugs.