@clearbit-dcp/clearbit.js-core
Version:
The hassle-free way to integrate analytics into any web application.
177 lines (144 loc) • 3.61 kB
JavaScript
'use strict';
/*
* Module dependencies.
*/
var Entity = require('./entity');
var bindAll = require('bind-all');
var cookie = require('./cookie');
var debug = require('debug')('analytics:user');
var inherit = require('inherits');
var rawCookie = require('component-cookie');
var uuid = require('uuid');
/**
* User defaults
*/
User.defaults = {
persist: true,
cookie: {
key: 'cb_user_id',
oldKey: 'cb_user'
},
localStorage: {
key: 'cb_user_traits'
}
};
/**
* Initialize a new `User` with `options`.
*
* @param {Object} options
*/
function User(options) {
this.defaults = User.defaults;
this.debug = debug;
Entity.call(this, options);
}
/**
* Inherit `Entity`
*/
inherit(User, Entity);
/**
* Set/get the user id.
*
* When the user id changes, the method will reset his anonymousId to a new one.
*
* // FIXME: What are the mixed types?
* @param {string} id
* @return {Mixed}
* @example
* // didn't change because the user didn't have previous id.
* anonymousId = user.anonymousId();
* user.id('foo');
* assert.equal(anonymousId, user.anonymousId());
*
* // didn't change because the user id changed to null.
* anonymousId = user.anonymousId();
* user.id('foo');
* user.id(null);
* assert.equal(anonymousId, user.anonymousId());
*
* // change because the user had previous id.
* anonymousId = user.anonymousId();
* user.id('foo');
* user.id('baz'); // triggers change
* user.id('baz'); // no change
* assert.notEqual(anonymousId, user.anonymousId());
*/
User.prototype.id = function(id) {
var prev = this._getId();
var ret = Entity.prototype.id.apply(this, arguments);
if (prev == null) return ret;
// FIXME: We're relying on coercion here (1 == "1"), but our API treats these
// two values differently. Figure out what will break if we remove this and
// change to strict equality
/* eslint-disable eqeqeq */
if (prev != id && id) this.anonymousId(null);
/* eslint-enable eqeqeq */
return ret;
};
/**
* Set / get / remove anonymousId.
*
* @param {String} anonymousId
* @return {String|User}
*/
User.prototype.anonymousId = function(anonymousId) {
var store = this.storage();
// set / remove
if (arguments.length) {
store.set('cb_anonymous_id', anonymousId);
return this;
}
// new
anonymousId = store.get('cb_anonymous_id');
if (anonymousId) {
return anonymousId;
}
// old - it is not stringified so we use the raw cookie.
anonymousId = rawCookie('_cb');
if (anonymousId) {
anonymousId = anonymousId.split('----')[0];
store.set('cb_anonymous_id', anonymousId);
store.remove('_cb');
return anonymousId;
}
// empty
anonymousId = uuid.v4();
store.set('cb_anonymous_id', anonymousId);
return store.get('cb_anonymous_id');
};
/**
* Remove anonymous id on logout too.
*/
User.prototype.logout = function() {
Entity.prototype.logout.call(this);
this.anonymousId(null);
};
/**
* Load saved user `id` or `traits` from storage.
*/
User.prototype.load = function() {
if (this._loadOldCookie()) return;
Entity.prototype.load.call(this);
};
/**
* BACKWARDS COMPATIBILITY: Load the old user from the cookie.
*
* @api private
* @return {boolean}
*/
User.prototype._loadOldCookie = function() {
var user = cookie.get(this._options.cookie.oldKey);
if (!user) return false;
this.id(user.id);
this.traits(user.traits);
cookie.remove(this._options.cookie.oldKey);
return true;
};
/**
* Expose the user singleton.
*/
module.exports = bindAll(new User());
/**
* Expose the `User` constructor.
*/
module.exports.User = User;