Skip to content

Commit c700ea3

Browse files
committed
Revert "Revert "Set group""
1 parent 83b6d66 commit c700ea3

File tree

6 files changed

+157
-12
lines changed

6 files changed

+157
-12
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Add support for passing callback function to identify.
44
* Add support for prepend user property operation.
55
* Keep sessions and event metadata in sync across multiple windows/tabs.
6+
* Add support for setting groups for users and events.
67

78
### 2.9.1 (March 6, 2016)
89

README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,29 @@ amplitude.init('YOUR_API_KEY_HERE', null, {
240240
# Advanced #
241241
This SDK automatically grabs useful data about the browser, including browser type and operating system version.
242242

243+
### Setting Groups ###
244+
245+
Amplitude supports assigning users to groups, and performing queries such as count by distinct on those groups. An example would be if you want to group your users based on what organization they are in (based on something like an orgId). For example you can designate user Joe to be in orgId 10, while Sue is in orgId 15. When performing an event segmentation query, you can then select Count By: orgId, to query the number of different orgIds that have performed a specific event. As long as at least one member of that group has performed the specific event, that group will be included in the count. See our help article on [Count By Distinct]() for more information.
246+
247+
In the above example, 'orgId' is a `groupType`, and the value 10 or 15 is the `groupName`. Another example of a `groupType` could a sport that the user participates in, and possible `groupNames` within that type would be tennis, baseball, etc.
248+
249+
You can use `setGroup(groupType, groupName)` to designate which groups a user belongs to. Few things to note: this will also set the `groupType: groupName` as a user property. **This will overwrite any existing groupName value set for that user's groupType, as well as the corresponding user property value.** For example if Joe was in orgId 10, and you call `setGroup('orgId', 20)`, 20 would replace 10. You can also call `setGroup` multiple times with different groupTypes to add a user to different groups. For example Sue is in orgId: 15, and she also plays sport: soccer. Now when querying, you can Count By both orgId and sport. **You are allowed to set up to 5 different groupTypes per user.** Any more than that will be ignored from the query UI, although they will still appear as user properties.
250+
251+
```javascript
252+
amplitude.setGroup('orgId', 15);
253+
amplitude.setGroup('sport', 'tennis');
254+
```
255+
256+
You can also use `logEventWithGroups` to set event-level groups, meaning the group designation only applies for the specific event being logged and does not persist on the user unless you explicitly set it with `setGroup`.
257+
258+
```javascript
259+
var eventProperties = {
260+
'key': 'value'
261+
}
262+
263+
amplitude.logEventWithGroups('initialize_game', eventProperties, {'sport': 'soccer'});
264+
```
265+
243266
### Setting Version Name ###
244267
By default, no version name is set. You can specify a version name to distinguish between different versions of your site by calling `setVersionName`:
245268

amplitude.js

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,18 @@ Amplitude.prototype.setUserId = function(userId) {
545545
}
546546
};
547547

548+
Amplitude.prototype.setGroup = function(groupType, groupName) {
549+
if (!this._apiKeySet('setGroup()')) {
550+
return;
551+
}
552+
553+
var groups = {};
554+
groups[groupType] = groupName;
555+
556+
var identify = new Identify().set(groupType, groupName);
557+
this._logEvent(IDENTIFY_EVENT, null, null, identify.userPropertiesOperations, groups, null);
558+
};
559+
548560
Amplitude.prototype.setOptOut = function(enable) {
549561
if (!this._apiKeySet('setOptOut()')) {
550562
return;
@@ -620,7 +632,7 @@ Amplitude.prototype.identify = function(identify, callback) {
620632
}
621633

622634
if (identify instanceof Identify && Object.keys(identify.userPropertiesOperations).length > 0) {
623-
this._logEvent(IDENTIFY_EVENT, null, null, identify.userPropertiesOperations, callback);
635+
this._logEvent(IDENTIFY_EVENT, null, null, identify.userPropertiesOperations, null, callback);
624636
} else if (callback && type(callback) === 'function') {
625637
callback(0, 'No request sent');
626638
}
@@ -664,7 +676,7 @@ var _truncateValue = function(value) {
664676
/**
665677
* Private logEvent method. Keeps apiProperties from being publicly exposed.
666678
*/
667-
Amplitude.prototype._logEvent = function(eventType, eventProperties, apiProperties, userProperties, callback) {
679+
Amplitude.prototype._logEvent = function(eventType, eventProperties, apiProperties, userProperties, groups, callback) {
668680
if (type(callback) !== 'function') {
669681
callback = null;
670682
}
@@ -700,6 +712,7 @@ Amplitude.prototype._logEvent = function(eventType, eventProperties, apiProperti
700712

701713
apiProperties = apiProperties || {};
702714
eventProperties = eventProperties || {};
715+
groups = groups || {};
703716
var event = {
704717
device_id: this.options.deviceId,
705718
user_id: this.options.userId || this.options.deviceId,
@@ -721,7 +734,8 @@ Amplitude.prototype._logEvent = function(eventType, eventProperties, apiProperti
721734
name: 'amplitude-js',
722735
version: version
723736
},
724-
sequence_number: sequenceNumber // for ordering events and identifys
737+
sequence_number: sequenceNumber, // for ordering events and identifys
738+
groups: this._truncate(utils.validateProperties(groups))
725739
// country: null
726740
};
727741

@@ -762,7 +776,17 @@ Amplitude.prototype.logEvent = function(eventType, eventProperties, callback) {
762776
}
763777
return -1;
764778
}
765-
return this._logEvent(eventType, eventProperties, null, null, callback);
779+
return this._logEvent(eventType, eventProperties, null, null, null, callback);
780+
};
781+
782+
Amplitude.prototype.logEventWithGroups = function(eventType, eventProperties, groups, callback) {
783+
if (!this._apiKeySet('logEventWithGroup()')) {
784+
if (callback && type(callback) === 'function') {
785+
callback(0, 'No request sent');
786+
}
787+
return -1;
788+
}
789+
return this._logEvent(eventType, eventProperties, null, null, groups, callback);
766790
};
767791

768792
// Test that n is a number or a numeric value.
@@ -782,7 +806,7 @@ Amplitude.prototype.logRevenue = function(price, quantity, product) {
782806
special: 'revenue_amount',
783807
quantity: quantity || 1,
784808
price: price
785-
});
809+
}, null, null, null);
786810
};
787811

788812
/**

amplitude.min.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/amplitude.js

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,18 @@ Amplitude.prototype.setUserId = function(userId) {
439439
}
440440
};
441441

442+
Amplitude.prototype.setGroup = function(groupType, groupName) {
443+
if (!this._apiKeySet('setGroup()')) {
444+
return;
445+
}
446+
447+
var groups = {};
448+
groups[groupType] = groupName;
449+
450+
var identify = new Identify().set(groupType, groupName);
451+
this._logEvent(IDENTIFY_EVENT, null, null, identify.userPropertiesOperations, groups, null);
452+
};
453+
442454
Amplitude.prototype.setOptOut = function(enable) {
443455
if (!this._apiKeySet('setOptOut()')) {
444456
return;
@@ -514,7 +526,7 @@ Amplitude.prototype.identify = function(identify, callback) {
514526
}
515527

516528
if (identify instanceof Identify && Object.keys(identify.userPropertiesOperations).length > 0) {
517-
this._logEvent(IDENTIFY_EVENT, null, null, identify.userPropertiesOperations, callback);
529+
this._logEvent(IDENTIFY_EVENT, null, null, identify.userPropertiesOperations, null, callback);
518530
} else if (callback && type(callback) === 'function') {
519531
callback(0, 'No request sent');
520532
}
@@ -558,7 +570,7 @@ var _truncateValue = function(value) {
558570
/**
559571
* Private logEvent method. Keeps apiProperties from being publicly exposed.
560572
*/
561-
Amplitude.prototype._logEvent = function(eventType, eventProperties, apiProperties, userProperties, callback) {
573+
Amplitude.prototype._logEvent = function(eventType, eventProperties, apiProperties, userProperties, groups, callback) {
562574
if (type(callback) !== 'function') {
563575
callback = null;
564576
}
@@ -594,6 +606,7 @@ Amplitude.prototype._logEvent = function(eventType, eventProperties, apiProperti
594606

595607
apiProperties = apiProperties || {};
596608
eventProperties = eventProperties || {};
609+
groups = groups || {};
597610
var event = {
598611
device_id: this.options.deviceId,
599612
user_id: this.options.userId || this.options.deviceId,
@@ -615,7 +628,8 @@ Amplitude.prototype._logEvent = function(eventType, eventProperties, apiProperti
615628
name: 'amplitude-js',
616629
version: version
617630
},
618-
sequence_number: sequenceNumber // for ordering events and identifys
631+
sequence_number: sequenceNumber, // for ordering events and identifys
632+
groups: this._truncate(utils.validateProperties(groups))
619633
// country: null
620634
};
621635

@@ -656,7 +670,17 @@ Amplitude.prototype.logEvent = function(eventType, eventProperties, callback) {
656670
}
657671
return -1;
658672
}
659-
return this._logEvent(eventType, eventProperties, null, null, callback);
673+
return this._logEvent(eventType, eventProperties, null, null, null, callback);
674+
};
675+
676+
Amplitude.prototype.logEventWithGroups = function(eventType, eventProperties, groups, callback) {
677+
if (!this._apiKeySet('logEventWithGroup()')) {
678+
if (callback && type(callback) === 'function') {
679+
callback(0, 'No request sent');
680+
}
681+
return -1;
682+
}
683+
return this._logEvent(eventType, eventProperties, null, null, groups, callback);
660684
};
661685

662686
// Test that n is a number or a numeric value.
@@ -676,7 +700,7 @@ Amplitude.prototype.logRevenue = function(price, quantity, product) {
676700
special: 'revenue_amount',
677701
quantity: quantity || 1,
678702
price: price
679-
});
703+
}, null, null, null);
680704
};
681705

682706
/**

test/amplitude.js

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,36 @@ describe('Amplitude', function() {
534534
});
535535
});
536536

537+
describe('setGroup', function() {
538+
539+
beforeEach(function() {
540+
reset();
541+
amplitude.init(apiKey);
542+
});
543+
544+
afterEach(function() {
545+
reset();
546+
});
547+
548+
it('should generate an identify event with groups set', function() {
549+
amplitude.setGroup('orgId', 15);
550+
assert.lengthOf(server.requests, 1);
551+
var events = JSON.parse(querystring.parse(server.requests[0].requestBody).e);
552+
assert.lengthOf(events, 1);
553+
554+
// verify identify event
555+
var identify = events[0];
556+
assert.equal(identify.event_type, '$identify');
557+
assert.deepEqual(identify.user_properties, {
558+
'$set': {'orgId': 15},
559+
});
560+
assert.deepEqual(identify.event_properties, {});
561+
assert.deepEqual(identify.groups, {
562+
'orgId': 15,
563+
});
564+
});
565+
});
566+
537567
describe('setDeviceId', function() {
538568

539569
beforeEach(function() {
@@ -1646,6 +1676,49 @@ describe('Amplitude', function() {
16461676
assert.equal(amplitude2._unsentIdentifys[0]['sequence_number'], sequenceNumber + 4);
16471677
assert.equal(amplitude1._unsentEvents[2]['sequence_number'], sequenceNumber + 5);
16481678
});
1679+
1680+
it('should handle groups input', function() {
1681+
var counter = 0;
1682+
var value = -1;
1683+
var message = '';
1684+
var callback = function (status, response) {
1685+
counter++;
1686+
value = status;
1687+
message = response;
1688+
};
1689+
1690+
var eventProperties = {
1691+
'key': 'value'
1692+
};
1693+
1694+
var groups = {
1695+
'group1': 'value1',
1696+
'group2': 'value2',
1697+
}
1698+
1699+
amplitude.logEventWithGroups('Test', eventProperties, groups, callback);
1700+
assert.lengthOf(server.requests, 1);
1701+
var events = JSON.parse(querystring.parse(server.requests[0].requestBody).e);
1702+
assert.lengthOf(events, 1);
1703+
1704+
// verify event is correctly formatted
1705+
var event = events[0];
1706+
assert.equal(event.event_type, 'Test');
1707+
assert.equal(event.event_id, 1);
1708+
assert.deepEqual(event.user_properties, {});
1709+
assert.deepEqual(event.event_properties, eventProperties);
1710+
assert.deepEqual(event.groups, groups);
1711+
1712+
// verify callback behavior
1713+
assert.equal(counter, 0);
1714+
assert.equal(value, -1);
1715+
assert.equal(message, '');
1716+
server.respondWith('success');
1717+
server.respond();
1718+
assert.equal(counter, 1);
1719+
assert.equal(value, 200);
1720+
assert.equal(message, 'success');
1721+
});
16491722
});
16501723

16511724
describe('optOut', function() {

0 commit comments

Comments
 (0)