Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
## Unreleased

* Add ability to clear all user properties.

## 2.8.0 (December 15, 2015)

* Add getSessionId helper method to fetch the current sessionId.
Expand Down
24 changes: 16 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ Amplitude-Javascript

```
<script type="text/javascript">
(function(t,e){var n=t.amplitude||{};var r=e.createElement("script");r.type="text/javascript";
(function(e,t){var n=e.amplitude||{};var r=t.createElement("script");r.type="text/javascript";
r.async=true;r.src="https://d24n15hnbwhuhn.cloudfront.net/libs/amplitude-2.8.0-min.gz.js";
r.onload=function(){t.amplitude.runQueuedFunctions()};var s=e.getElementsByTagName("script")[0];
s.parentNode.insertBefore(r,s);var i=function(){this._q=[];return this};function o(t){
i.prototype[t]=function(){this._q.push([t].concat(Array.prototype.slice.call(arguments,0)));
return this}}var a=["add","append","set","setOnce","unset"];for(var u=0;u<a.length;u++){o(a[u]);
}n.Identify=i;n._q=[];function c(t){n[t]=function(){n._q.push([t].concat(Array.prototype.slice.call(arguments,0)));
}}var l=["init","logEvent","logRevenue","setUserId","setUserProperties","setOptOut","setVersionName","setDomain","setDeviceId","setGlobalUserProperties","identify"];
for(var p=0;p<l.length;p++){c(l[p])}t.amplitude=n})(window,document);
r.onload=function(){e.amplitude.runQueuedFunctions()};var s=t.getElementsByTagName("script")[0];
s.parentNode.insertBefore(r,s);var i=function(){this._q=[];return this};function a(e){
i.prototype[e]=function(){this._q.push([e].concat(Array.prototype.slice.call(arguments,0)));
return this}}var o=["add","append","clearAll","set","setOnce","unset"];for(var c=0;c<o.length;c++){
a(o[c])}n.Identify=i;n._q=[];function u(e){n[e]=function(){n._q.push([e].concat(Array.prototype.slice.call(arguments,0)));
}}var l=["init","logEvent","logRevenue","setUserId","setUserProperties","setOptOut","setVersionName","setDomain","setDeviceId","setGlobalUserProperties","identify","clearUserProperties"];
for(var p=0;p<l.length;p++){u(l[p])}e.amplitude=n})(window,document);

amplitude.init("YOUR_API_KEY_HERE");
</script>
Expand Down Expand Up @@ -142,6 +142,14 @@ var userProperties = {
amplitude.setUserProperties(userProperties);
```

### Clearing User Properties ###

You may use `clearUserProperties` to clear all user properties at once. Note: the result is irreversible!

```javascript
amplitude.clearUserProperties();
```

# Tracking Revenue #

To track revenue from a user, call
Expand Down
12 changes: 6 additions & 6 deletions amplitude-segment-snippet.min.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
(function(t,e){var n=t.amplitude||{};var r=function(){this._q=[];return this};function s(t){
r.prototype[t]=function(){this._q.push([t].concat(Array.prototype.slice.call(arguments,0)));
return this}}var i=["add","append","set","setOnce","unset"];for(var o=0;o<i.length;o++){
s(i[o])}n.Identify=r;n._q=[];function a(t){n[t]=function(){n._q.push([t].concat(Array.prototype.slice.call(arguments,0)));
}}var u=["init","logEvent","logRevenue","setUserId","setUserProperties","setOptOut","setVersionName","setDomain","setDeviceId","setGlobalUserProperties","identify"];
for(var c=0;c<u.length;c++){a(u[c])}t.amplitude=n})(window,document);
(function(e,t){var r=e.amplitude||{};var n=function(){this._q=[];return this};function s(e){
n.prototype[e]=function(){this._q.push([e].concat(Array.prototype.slice.call(arguments,0)));
return this}}var i=["add","append","clearAll","set","setOnce","unset"];for(var o=0;o<i.length;o++){
s(i[o])}r.Identify=n;r._q=[];function a(e){r[e]=function(){r._q.push([e].concat(Array.prototype.slice.call(arguments,0)));
}}var c=["init","logEvent","logRevenue","setUserId","setUserProperties","setOptOut","setVersionName","setDomain","setDeviceId","setGlobalUserProperties","identify","clearUserProperties"];
for(var l=0;l<c.length;l++){a(c[l])}e.amplitude=r})(window,document);
16 changes: 8 additions & 8 deletions amplitude-snippet.min.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
(function(t,e){var n=t.amplitude||{};var r=e.createElement("script");r.type="text/javascript";
(function(e,t){var n=e.amplitude||{};var r=t.createElement("script");r.type="text/javascript";
r.async=true;r.src="https://d24n15hnbwhuhn.cloudfront.net/libs/amplitude-2.8.0-min.gz.js";
r.onload=function(){t.amplitude.runQueuedFunctions()};var s=e.getElementsByTagName("script")[0];
s.parentNode.insertBefore(r,s);var i=function(){this._q=[];return this};function a(t){
i.prototype[t]=function(){this._q.push([t].concat(Array.prototype.slice.call(arguments,0)));
return this}}var o=["add","append","set","setOnce","unset"];for(var u=0;u<o.length;u++){
a(o[u])}n.Identify=i;n._q=[];function c(t){n[t]=function(){n._q.push([t].concat(Array.prototype.slice.call(arguments,0)));
}}var p=["init","logEvent","logRevenue","setUserId","setUserProperties","setOptOut","setVersionName","setDomain","setDeviceId","setGlobalUserProperties","identify"];
for(var l=0;l<p.length;l++){c(p[l])}t.amplitude=n})(window,document);
r.onload=function(){e.amplitude.runQueuedFunctions()};var s=t.getElementsByTagName("script")[0];
s.parentNode.insertBefore(r,s);var i=function(){this._q=[];return this};function a(e){
i.prototype[e]=function(){this._q.push([e].concat(Array.prototype.slice.call(arguments,0)));
return this}}var o=["add","append","clearAll","set","setOnce","unset"];for(var c=0;c<o.length;c++){
a(o[c])}n.Identify=i;n._q=[];function u(e){n[e]=function(){n._q.push([e].concat(Array.prototype.slice.call(arguments,0)));
}}var l=["init","logEvent","logRevenue","setUserId","setUserProperties","setOptOut","setVersionName","setDomain","setDeviceId","setGlobalUserProperties","identify","clearUserProperties"];
for(var p=0;p<l.length;p++){u(l[p])}e.amplitude=n})(window,document);
28 changes: 28 additions & 0 deletions amplitude.js
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,13 @@ Amplitude.prototype.setUserProperties = function(userProperties) {
this.identify(identify);
};

// Clearing user properties is irreversible!
Amplitude.prototype.clearUserProperties = function(){
var identify = new Identify();
identify.clearAll();
this.identify(identify);
};

Amplitude.prototype.identify = function(identify) {

if (type(identify) === 'object' && '_q' in identify) {
Expand Down Expand Up @@ -3522,6 +3529,7 @@ var type = require('./type');

var AMP_OP_ADD = '$add';
var AMP_OP_APPEND = '$append';
var AMP_OP_CLEAR_ALL = '$clearAll';
var AMP_OP_SET = '$set';
var AMP_OP_SET_ONCE = '$setOnce';
var AMP_OP_UNSET = '$unset';
Expand Down Expand Up @@ -3549,6 +3557,20 @@ Identify.prototype.append = function(property, value) {
return this;
};

// clearAll should be sent on its own Identify object
// If there are already other operations, then don't add clearAll
// If clearAll already in Identify, don't add other operations
Identify.prototype.clearAll = function() {
if (Object.keys(this.userPropertiesOperations).length > 0) {
if (!(AMP_OP_CLEAR_ALL in this.userPropertiesOperations)) {
log('Need to send $clearAll on its own Identify object without any other operations, skipping $clearAll');
}
return this;
}
this.userPropertiesOperations[AMP_OP_CLEAR_ALL] = '-';
return this;
};

Identify.prototype.set = function(property, value) {
this._addOperation(AMP_OP_SET, property, value);
return this;
Expand All @@ -3565,6 +3587,12 @@ Identify.prototype.unset = function(property) {
};

Identify.prototype._addOperation = function(operation, property, value) {
// check that the identify doesn't already contain a clearAll
if (AMP_OP_CLEAR_ALL in this.userPropertiesOperations) {
log('This identify already contains a $clearAll operation, skipping operation ' + operation);
return;
}

// check that property wasn't already used in this Identify
if (this.properties.indexOf(property) !== -1) {
log('User property "' + property + '" already used in this identify, skipping operation ' + operation);
Expand Down
4 changes: 2 additions & 2 deletions amplitude.min.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/amplitude-snippet.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
this._q.push([fn].concat(Array.prototype.slice.call(arguments, 0))); return this;
};
}
var identifyFuncs = ['add', 'append', 'set', 'setOnce', 'unset'];
var identifyFuncs = ['add', 'append', 'clearAll', 'set', 'setOnce', 'unset'];
for (var i = 0; i < identifyFuncs.length; i++) {
proxyIdentify(identifyFuncs[i]);
}
Expand All @@ -26,7 +26,7 @@
}
var funcs = ['init', 'logEvent', 'logRevenue', 'setUserId', 'setUserProperties',
'setOptOut', 'setVersionName', 'setDomain', 'setDeviceId',
'setGlobalUserProperties', 'identify'];
'setGlobalUserProperties', 'identify', 'clearUserProperties'];
for (var j = 0; j < funcs.length; j++) {
proxy(funcs[j]);
}
Expand Down
7 changes: 7 additions & 0 deletions src/amplitude.js
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,13 @@ Amplitude.prototype.setUserProperties = function(userProperties) {
this.identify(identify);
};

// Clearing user properties is irreversible!
Amplitude.prototype.clearUserProperties = function(){
var identify = new Identify();
identify.clearAll();
this.identify(identify);
};

Amplitude.prototype.identify = function(identify) {

if (type(identify) === 'object' && '_q' in identify) {
Expand Down
21 changes: 21 additions & 0 deletions src/identify.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ var type = require('./type');

var AMP_OP_ADD = '$add';
var AMP_OP_APPEND = '$append';
var AMP_OP_CLEAR_ALL = '$clearAll';
var AMP_OP_SET = '$set';
var AMP_OP_SET_ONCE = '$setOnce';
var AMP_OP_UNSET = '$unset';
Expand Down Expand Up @@ -35,6 +36,20 @@ Identify.prototype.append = function(property, value) {
return this;
};

// clearAll should be sent on its own Identify object
// If there are already other operations, then don't add clearAll
// If clearAll already in Identify, don't add other operations
Identify.prototype.clearAll = function() {
if (Object.keys(this.userPropertiesOperations).length > 0) {
if (!(AMP_OP_CLEAR_ALL in this.userPropertiesOperations)) {
log('Need to send $clearAll on its own Identify object without any other operations, skipping $clearAll');
}
return this;
}
this.userPropertiesOperations[AMP_OP_CLEAR_ALL] = '-';
return this;
};

Identify.prototype.set = function(property, value) {
this._addOperation(AMP_OP_SET, property, value);
return this;
Expand All @@ -51,6 +66,12 @@ Identify.prototype.unset = function(property) {
};

Identify.prototype._addOperation = function(operation, property, value) {
// check that the identify doesn't already contain a clearAll
if (AMP_OP_CLEAR_ALL in this.userPropertiesOperations) {
log('This identify already contains a $clearAll operation, skipping operation ' + operation);
return;
}

// check that property wasn't already used in this Identify
if (this.properties.indexOf(property) !== -1) {
log('User property "' + property + '" already used in this identify, skipping operation ' + operation);
Expand Down
29 changes: 29 additions & 0 deletions test/amplitude.js
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,35 @@ describe('Amplitude', function() {
});
});

describe('clearUserProperties', function() {
beforeEach(function() {
amplitude.init(apiKey);
});

afterEach(function() {
reset();
});

it('should log identify call from clear user properties', function() {
assert.equal(amplitude._unsentCount(), 0);
amplitude.clearUserProperties();

assert.lengthOf(amplitude._unsentEvents, 0);
assert.lengthOf(amplitude._unsentIdentifys, 1);
assert.equal(amplitude._unsentCount(), 1);
assert.lengthOf(server.requests, 1);
var events = JSON.parse(querystring.parse(server.requests[0].requestBody).e);
assert.lengthOf(events, 1);
assert.equal(events[0].event_type, '$identify');
assert.deepEqual(events[0].event_properties, {});

var expected = {
'$clearAll': '-'
};
assert.deepEqual(events[0].user_properties, expected);
});
});

describe('setDeviceId', function() {

afterEach(function() {
Expand Down
12 changes: 6 additions & 6 deletions test/browser/amplitudejs.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
this._q.push([fn].concat(Array.prototype.slice.call(arguments, 0))); return this;
};
}
var identifyFuncs = ['add', 'append', 'set', 'setOnce', 'unset'];
var identifyFuncs = ['add', 'append', 'clearAll', 'set', 'setOnce', 'unset'];
for (var i = 0; i < identifyFuncs.length; i++) {
proxyIdentify(identifyFuncs[i]);
}
Expand All @@ -29,14 +29,13 @@
}
var funcs = ['init', 'logEvent', 'logRevenue', 'setUserId', 'setUserProperties',
'setOptOut', 'setVersionName', 'setDomain', 'setDeviceId',
'setGlobalUserProperties', 'identify'];
'setGlobalUserProperties', 'identify', 'clearUserProperties'];
for (var j = 0; j < funcs.length; j++) {
proxy(funcs[j]);
}
window.amplitude = amplitude;
})(window, document);


var setUserId = function() {
var userId = prompt('Input userId', 'user01');
amplitude.setUserId(userId);
Expand All @@ -56,18 +55,18 @@
var addToPhotoCount = function() {
var photoCount = parseInt(prompt('Input amount to increment photo count by', '2'), 10);
amplitude.identify(new amplitude.Identify().add('photoCount', photoCount));
}
};
var clickOnLinkA = function() {
amplitude.logEvent('Clicked on link A', null, function() { window.location='https://www.google.com'; });
};
var setPhotoCount = function() {
var photoCount = parseInt(prompt('Input photo count to set', '2'), 10);
amplitude.identify(new amplitude.Identify().set('photoCount', photoCount));
}
};
var setOncePhotoCount = function() {
var photoCount = parseInt(prompt('Input photo count to setOnce', '2'), 10);
amplitude.identify(new amplitude.Identify().setOnce('photoCount', photoCount));
}
};
</script>
<script>
amplitude.init('a2dbce0e18dfe5f8e74493843ff5c053', null, {includeReferrer: true}, function() {
Expand Down Expand Up @@ -96,6 +95,7 @@ <h3>Amplitude JS Test</h3>
<li><a href="javascript:setPhotoCount();">Set photo count</a></li>
<li><a href="javascript:setOncePhotoCount();">Set photo count once</a></li>
<li><a href="javascript:setCity();">Set city via setUserProperties</a></li>
<li><a href="javascript:amplitude.clearUserProperties();">Clear all user properties</a></li>
<br><br>
<li><a href="/test/browser/amplitudejs2.html">Go to second page</a></li>
</body>
Expand Down
6 changes: 3 additions & 3 deletions test/browser/amplitudejs2.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
this._q.push([fn].concat(Array.prototype.slice.call(arguments, 0))); return this;
};
}
var identifyFuncs = ['add', 'append', 'set', 'setOnce', 'unset'];
var identifyFuncs = ['add', 'append', 'clearAll', 'set', 'setOnce', 'unset'];
for (var i = 0; i < identifyFuncs.length; i++) {
proxyIdentify(identifyFuncs[i]);
}
Expand All @@ -29,14 +29,13 @@
}
var funcs = ['init', 'logEvent', 'logRevenue', 'setUserId', 'setUserProperties',
'setOptOut', 'setVersionName', 'setDomain', 'setDeviceId',
'setGlobalUserProperties', 'identify'];
'setGlobalUserProperties', 'identify', 'clearUserProperties'];
for (var j = 0; j < funcs.length; j++) {
proxy(funcs[j]);
}
window.amplitude = amplitude;
})(window, document);


var setUserId = function() {
var userId = prompt('Input userId', 'user01');
amplitude.setUserId(userId);
Expand Down Expand Up @@ -96,6 +95,7 @@ <h3>Amplitude JS Test</h3>
<li><a href="javascript:setPhotoCount();">Set photo count</a></li>
<li><a href="javascript:setOncePhotoCount();">Set photo count once</a></li>
<li><a href="javascript:setCity();">Set city via setUserProperties</a></li>
<li><a href="javascript:amplitude.clearUserProperties();">Clear all user properties</a></li>
<br><br>
<li><a href="/test/browser/amplitudejs.html">Go to first page</a></li>
</body>
Expand Down
41 changes: 41 additions & 0 deletions test/identify.js
Original file line number Diff line number Diff line change
Expand Up @@ -197,4 +197,45 @@ describe('Identify', function() {
assert.deepEqual(expected, identify.userPropertiesOperations);
assert.deepEqual([property], identify.properties);
});

it ('should disallow other operations on a clearAll identify', function() {
var property = "testProperty";
var value1 = "testValue";
var value2 = 0.123;
var value3 = true;
var value4 = {};

var identify = new Identify().clearAll();
identify.setOnce(property, value1).add(property, value2).set(property, value3).unset(property);

var expected = {
'$clearAll': '-'
};

assert.deepEqual(expected, identify.userPropertiesOperations);
assert.deepEqual([], identify.properties);
});

it ('should disallow clearAll on an identify with other operations', function() {
var property = "testProperty";
var value1 = "testValue";
var value2 = 0.123;
var value3 = true;
var value4 = {};

var identify = new Identify().setOnce(property, value1).add(property, value2);
identify.set(property, value3).unset(property).clearAll();

var expected = {
'$setOnce': {}
};
expected['$setOnce'][property] = value1

assert.deepEqual(expected, identify.userPropertiesOperations);
assert.deepEqual([property], identify.properties);
});

it ('should not log any warnings for calling clearAll multiple times on a single identify', function() {
var identify = new Identify().clearAll().clearAll().clearAll();
});
});