Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

adhering to new segmentio init api

  • Loading branch information...
commit 709d11cf8f4b501f3d9b1ded88e5605f5a5357c4 1 parent c9aa197
@ivolo authored
View
3  controllers/animals.js
@@ -7,8 +7,7 @@ var segmentio = require('segmentio');
var animals = require('../lib/animals');
var ip = require('../lib/ip');
-var env = process.env.NODE_ENV || 'production';
-segmentio.initialize('t5inzlxs', env);
+segmentio.init('t5inzlxs');
var getNumber = function (req, key) {
View
10 node_modules/segmentio/.makefile
@@ -1,10 +0,0 @@
-
-MOCHA_OPTS=
-REPORTER = dot
-
-test:
- @NODE_ENV=test ./node_modules/.bin/mocha \
- --reporter $(REPORTER) \
- $(MOCHA_OPTS)
-
-.PHONY: test
View
8 node_modules/segmentio/Makefile
@@ -0,0 +1,8 @@
+
+REPORTER = dot
+
+test:
+ @./node_modules/.bin/mocha \
+ --reporter $(REPORTER)
+
+.PHONY: test
View
96 node_modules/segmentio/README.md
@@ -1,4 +1,4 @@
-# Segment.io Node Client
+Segment.io Node Client
==============
[Segment.io](https://segment.io) is a segmentation-focused analytics platform. If you haven't yet,
@@ -23,37 +23,54 @@ You can control the batching behavior as described below.
```javascript
npm install segmentio
```
-#### Create a Client
+#### Initialize the client
+
+The default and easiest method for most apps is to just use the API client as a module. To get started, just use the following:
```javascript
-var Segmentio = require('segmentio');
-var seg = new Segmentio('YOUR_API_KEY', 'production');
+var segmentio = require('segmentio');
+segmentio.init('YOUR_API_KEY');
```
+Then whenever you `require('segmentio')` from your app, you'll have access to the same client.
+
+You can also create your own client if you'd like a little more customization. The API is exactly the same.
+```javascript
+var segmentio = new require('segmentio').Client();
+segmentio.init('YOUR_API_KEY');
+```
+
#### Identify a Visitor
Identifying a visitor ties all of their actions to an ID you recognize and records visitor traits you can segment by.
-```
-seg.identify(sessionId, visitorId, traits);
+```javascript
+segmentio.identify({
+ sessionId : String
+ visitorId : String
+ traits : Object
+});
```
-sessionId (string) is a unique id associated with an anonymous visitor before they are logged in. If the user
+**sessionId** (string) is a unique id associated with an anonymous visitor before they are logged in. If the user
is logged in, you can use null here.
-visitor_id (string) is usually an email, but any unique ID will work. This is how you recognize a signed-in visitor
+**visitorId** (string) is usually an email, but any unique ID will work. This is how you recognize a signed-in visitor
in your system. Note: it can be null if the visitor is not logged in.By explicitly identifying a visitor, you tie all of
their actions to their identity. This makes it possible for you to run things like segment-based email campaigns.
-traits (object) is a dictionary with keys like “Subscription Plan” or “Favorite Genre”. You can segment your visitors by any trait you record. Once you record a trait, no need to send it again, so the traits argument is optional.
+**traits** (object) is a dictionary with keys like “Subscription Plan” or “Favorite Genre”. You can segment your visitors by any trait you record. Once you record a trait, no need to send it again, so the traits argument is optional.
```javascript
-
-seg.identify('DKGXt384hFDT82D', 'ilya@segment.io', {
- 'First Name': 'Ilya',
- 'Last Name': 'Volodarsky',
- 'Subscription Plan': 'Premium',
- 'On Mailing List': true
+segmentio.identify({
+ sessionId : 'DKGXt384hFDT82D',
+ userId : 'ilya@segment.io',
+ traits : {
+ 'First Name': 'Ilya',
+ 'Last Name': 'Volodarsky',
+ 'Subscription Plan': 'Premium',
+ 'On Mailing List': true
+ }
});
```
@@ -63,28 +80,37 @@ seg.identify('DKGXt384hFDT82D', 'ilya@segment.io', {
Whenever a visitor triggers an event on your site, you’ll want to track it so that you can analyze and segment by those events later.
```
-seg.track(sessionId, visitorId, event, properties);
+seg.track({
+ sessionId : String,
+ userId : String,
+ event : String,
+ properties : Object
+});
```
-sessionId (string) is a unique id associated with an anonymous visitor before they are logged in. If the user
-is logged in, you can use null here.
+**sessionId** (string) is a unique id associated with an anonymous visitor before they are logged in. If the user
+is logged in, you can use null here. Either this or the userId must be supplied.
-visitor_id (string) is usually an email, but any unique ID will work. This is how you recognize a signed-in visitor
-in your system. Note: it can be null if the visitor is not logged in.By explicitly identifying a visitor, you tie all of
-their actions to their identity. This makes it possible for you to run things like segment-based email campaigns.
+**userId** (string) is usually an email, but any unique ID will work. This is how you recognize a signed-in visitor
+in your system. Note: it can be null if the visitor is not logged in. By explicitly identifying a visitor, you tie all of
+their actions to their identity. This makes it possible for you to run things like segment-based email campaigns. Either this or the sessionId must be supplied.
-event (string) is a human readable description like "Played a Song", "Printed a Report" or "Updated Status". You’ll be able to segment by when and how many times each event was triggered.
+**event** (string) is a human readable description like "Played a Song", "Printed a Report" or "Updated Status". You’ll be able to segment by when and how many times each event was triggered.
-properties (object) is a dictionary with items that describe the event in more detail. This argument is optional, but highly recommended—you’ll find these properties extremely useful later.
+**properties** (object) is a dictionary with items that describe the event in more detail. This argument is optional, but highly recommended—you’ll find these properties extremely useful later.
```javascript
-seg.track('DKGXt384hFDT82D', ilya@segment.io', 'Listened to a song', {
- 'Title': 'Eleanor Rigby',
- 'Artist': 'Beatles',
- 'Playlist': 'Popular'
+seg.track({
+ sessionId : 'DKGXt384hFDT82D',
+ userId : 'ilya@segment.io',
+ event : 'Listened to a song',
+ properties : {
+ 'Title': 'Eleanor Rigby',
+ 'Artist': 'Beatles',
+ 'Playlist': 'Popular'
+ }
});
-
```
#### Adjusting Batching
@@ -95,4 +121,16 @@ You can adjust the flush triggers in the client. Take a look into the source.
```javascript
npm test
-```
+```
+
+#### License
+
+(The MIT License)
+
+Copyright (c) 2012-2012 Segment.io Inc <friends@segment.io>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
View
205 node_modules/segmentio/lib/client.js
@@ -1,32 +1,26 @@
var _ = require('underscore'),
events = require('events'),
- http = require('http'),
- urlParser = require('url'),
- util = require('util');
+ util = require('util'),
+ request = require('./request'),
+ triggers = require('./triggers');
var MAX_BATCH = 1000;
-var sizeTrigger = function () {
- return this.queue.length >= this.options.flushSize;
-};
-var timeTrigger = function () {
- // flush if its been 10 seconds since the last one
- return Date.now() - this.lastFlush > 1000 * 10;
-};
+var defaults = {
+ host : 'http://api.segment.io',
+ flushSize : 50,
+ maxQueueSize : 10000,
-var defaults = {
- host: 'http://api.segment.io',
- flushSize: 50,
- maxQueueSize: 10000,
- endpoints: {
- identify: '/v2/i',
- track: '/v2/t',
- batch: '/v2/import'
+ endpoints : {
+ identify : '/v2/i',
+ track : '/v2/t',
+ batch : '/v2/import'
},
- triggers: [sizeTrigger, timeTrigger]
+
+ triggers: [triggers.size, triggers.time]
};
@@ -34,17 +28,15 @@ var defaults = {
* Batching Segment.io node client driver
*
* @param {String} apiKey - Segment.io api key
- * @param {String} environment - environment to log for (optional)
* @param {Object} options (optional)
* @option {String} host - api base hostname
* @option {Number} flushSize - size of queue before flush
* @option {Number} maxQueueSize - max size of queue to grow
* @option {Object} endpoints - endpoints to make calls to
* @option {Array} triggers - series of functions to test saving
- * [function (queueLength, lastFlush) {
- * returns {Boolean}; }]
+ * [function () { returns {Boolean}; }]
*/
-var Client = module.exports = function (apiKey, environment, options) {
+var Client = module.exports = function (apiKey, options) {
this.initialized = false;
@@ -52,8 +44,8 @@ var Client = module.exports = function (apiKey, environment, options) {
this.queue = [];
- if (apiKey || environment || options) {
- this.initialize(apiKey, environment, options);
+ if (apiKey || options) {
+ this.init(apiKey, options);
}
};
@@ -64,7 +56,6 @@ util.inherits(Client, events.EventEmitter);
* Batching Segment.io node client driver
*
* @param {String} apiKey - Segment.io api key
- * @param {String} environment - environment to log for (optional)
* @param {Object} options (optional)
* @option {String} host - api base hostname
* @option {Number} flushSize - size of queue before flush
@@ -74,18 +65,12 @@ util.inherits(Client, events.EventEmitter);
* [function (queueLength, lastFlush) {
* returns {Boolean}; }]
*/
-Client.prototype.initialize = function (apiKey, environment, options) {
-
- if (_.isObject(environment)) {
- options = environment;
- environment = null;
- }
-
- if (!_.isString(apiKey))
- throw new Error('Segment.io client must be initialized with a apiKey.');
+Client.prototype.init = function (apiKey, options) {
+ if (!_.isString(apiKey) || apiKey.length === 0)
+ throw new Error('Segment.io client must be initialized with a '+
+ 'non-empty apiKey.');
- this.environment = environment || "production";
this.apiKey = apiKey;
this.options = _.defaults(options || {}, defaults);
@@ -98,23 +83,29 @@ Client.prototype.initialize = function (apiKey, environment, options) {
};
+/**
+ * Internal method to check whether the client has been initialized.
+ * @return {[type]} [description]
+ * @private
+ */
Client.prototype._checkInitialized = function () {
if (!this.initialized)
- throw new Error('Segmentio client is not initialized. Please call client.init (apiKey, environment, options).');
+ throw new Error('Segmentio client is not initialized. Please call ' +
+ 'client.init(apiKey, options).');
};
/**
* Identifying a visitor ties all of their actions to an ID you recognize and
- * records visitor traits you can segment by.
+ * can record visitor traits to segment by.
*
* You must pass in at least one of the userId or sessionId, so that the
* visitor can be properly identified.
*
* @param {Object} identify
- * @param {String} session - anonymous visitor's session id (optional)
- * @param {String} visitor - id for logged in visitor (needs sessionId if not provided)
- * @param {Object} traits - key/value object of tags for the visitor (optional)
+ * @param {String} sessionId - anonymous visitor's session id (optional)
+ * @param {String} visitorId - id for logged in visitor (needs sessionId if not provided)
+ * @param {Object} traits - key/value object of tags for the visitor (optional)
*
* @param {Object} context - app provided context about the visitor (optional)
* @option {String} ip
@@ -127,11 +118,9 @@ Client.prototype.identify = function (identify, context) {
this._checkInitialized();
if (!_.isObject(identify)) {
-
throw new Error('[segmentio]#identify: identify must be an object');
}
-
var sessionId = identify.sessionId,
userId = identify.userId,
traits = identify.traits || {};
@@ -143,7 +132,8 @@ Client.prototype.identify = function (identify, context) {
throw new Error('[segmentio]#identify: identify.userId must be a string.');
if (!_.isString(sessionId) && !_.isString(userId))
- throw new Error('[segmentio]#identify: either sessionId or userId must be provided as a non-empty string.');
+ throw new Error('[segmentio]#identify: either sessionId or userId ' +
+ 'must be provided as a non-empty string.');
var message = {
@@ -157,13 +147,14 @@ Client.prototype.identify = function (identify, context) {
this._enqueue(message);
};
+
/**
* Whenever a user triggers an event on your site, you’ll want to track it
* so that you can analyze and segment by those events later.
*
* @param {Object} track
- * @param {String} session - id for the visitor's session (must supply either this or visitor id)
- * @param {String} visitor - id for the actual visitor (must supply either this or session)
+ * @param {String} sessionId - id for the user's session (must supply either this or userId)
+ * @param {String} userId - id for the actual visitor (must supply either this or sessionId)
* @param {String} event - name of the event by the user i.e. "Booked a listing"
* @param {Object} properties - key/value tags for the event. (optional)
*
@@ -212,21 +203,20 @@ Client.prototype.track = function (track) {
this._enqueue(message);
};
+
+
Client.prototype._enqueue = function (message) {
var self = this;
- var callback = message.callback;
-
if (this.queue.length >= this.options.maxQueueSize) {
// dropping this packet because the queue is full
// to conserve memory
- if (callback)
- return callback(
- new Error('Segment.io client failed to enqueue message because queue is full. Consider increasing queue size.'));
-
+ this.emit('error',
+ new Error('Segment.io client failed to enqueue message ' +
+ 'because queue is full. Consider increasing queue ' +
+ 'size.'));
} else {
-
this.queue.push(message);
}
@@ -237,15 +227,14 @@ Client.prototype._enqueue = function (message) {
if (_.isFunction(trigger)) {
shouldFlush = shouldFlush || trigger.apply(self);
}
-
});
if (shouldFlush) {
this.flush();
}
-
};
+
/**
* Flushes the current queue
*/
@@ -255,7 +244,6 @@ Client.prototype.flush = function() {
var self = this;
-
if (this.queue.length > 0) {
this.emit('flushing');
@@ -263,125 +251,30 @@ Client.prototype.flush = function() {
var batch = this.queue.splice(0, this.options.flushSize);
this.queue = this.queue.splice(batch.length, this.queue.length -
batch.length);
-
var callbacks = [];
-
- _.each(batch, function (message) {
-
- // save the callbacks
- if (message.callback) callbacks.push(message.callback);
- delete message.callback;
-
- });
-
-
var payload = {
- project: {
- apiKey : this.apiKey,
- environment : this.environment
- },
- batch: batch
+ apiKey : this.apiKey,
+ batch : batch
};
var url = this.options.host + this.options.endpoints.batch;
- _request(url, {
+ request(url, {
method: 'POST',
params: payload
}, function (err, response, body) {
- if (err) {
-
+ if (err)
self.emit('error', err);
-
- } else {
-
- _.each(callbacks, function (callback) {
-
- callback(err);
-
- });
-
+ else
self.emit('flushed');
- }
-
});
this.lastFlush = new Date();
}
-
};
- /**
- FROM: https://gist.github.com/1393666
-
- * UrlReq - Wraps the http.request function making it nice for unit testing APIs.
- *
- * @param {string} url The required url in any form
- * @param {object} options An options object (this is optional)
- * @param {Function} callback This is passed the 'res' object from your request
- *
- */
-var _request = function(url, options, callback){
-
- if(_.isFunction(options)) {
- callback = options;
- options = {};
- }
-
- url = urlParser.parse(url);
-
- var settings = {
- host: url.hostname,
- port: url.port || 80,
- path: url.pathname,
- headers: options.headers || {},
- method: options.method
- };
-
- // if there are params:
- if(options.params){
- options.params = JSON.stringify(options.params);
- settings.headers['Content-Type'] = 'application/json';
- settings.headers['Content-Length'] = options.params.length;
- }
-
- // MAKE THE REQUEST
- var req = http.request(settings);
-
- // if there are params: write them to the request
- if(options.params) {
- req.write(options.params);
- }
-
- req.on('error', function (err) {
- callback(err);
- });
-
- // when the response comes back
- req.on('response', function(res){
-
- res.body = '';
- res.setEncoding('utf-8');
-
- // concat chunks
- res.on('data', function(chunk) {
- res.body += chunk;
- });
-
- // when the response has finished
- res.on('end', function(){
-
- // fire callback
- callback(null, res.body, res);
- });
-
- });
-
- // end the request
- req.end();
-};
View
33 node_modules/segmentio/lib/segmentio.js
@@ -1,13 +1,34 @@
-var Client = require('./client');
-// create the default client
+var Client = exports.Client = require('./client');
+
+
+/**
+ * Keep a default client for use directly via its api methods.
+ */
var defaultClient = new Client();
+
+/**
+ * Initialize a default segmentio client with your application's API Key.
+ * See client docs for detailed signature.
+ */
+exports.init = function () {
+ defaultClient.init.apply(defaultClient, arguments);
+};
+
+
/**
- * Exposes the Client constructor so new clients can be made
- * @type {[Segmentio.Client]}
+ * Module level track. See client docs for detailed signature.
*/
-defaultClient.Client = Client;
+exports.track = function () {
+ defaultClient.track.apply(defaultClient, arguments);
+};
-module.exports = defaultClient;
+
+/**
+ * Module level identify. See client docs for detailed signature.
+ */
+exports.identify = function () {
+ defaultClient.identify.apply(defaultClient, arguments);
+};
View
4 node_modules/segmentio/package.json
@@ -4,8 +4,8 @@
, "description": "An official Segment.io client driver for node"
, "repository": "git://github.com/segmentio/segmentio"
, "keywords": ["segment.io", "node", "client", "driver", "analytics"]
- , "author": "Ilya Volodarsky <ilya@segment.io>"
- , "engines": { "node": ">= 0.6.x" }
+ , "authors": "Ilya Volodarsky <ilya@segment.io>, Calvin French-Owen <calvin@segment.io>"
+ , "engines": { "node": ">= 0.8.x" }
, "main": "./lib/segmentio"
, "dependencies":{
"underscore": "*"
View
40 node_modules/segmentio/test/client.js
@@ -11,9 +11,27 @@ var options = {
};
+/**
+ * Sets up the listeners for seg, to call 'done' on a flush and error on error.
+ * @param {Function} done - completion callback
+ */
+var setListeners = function (seg, done) {
+
+ var listenerId = seg.once('error', function (err) {
+ should.not.exist(err);
+ });
+
+ seg.once('flushed', function () {
+ seg.removeAllListeners();
+ done();
+ });
+};
+
+
+
describe('Batch', function () {
- var visitorId = 'test@segment.io',
+ var userId = 'test@segment.io',
sessionId = '123456789',
apiKey = 'fakeid';
@@ -22,25 +40,19 @@ describe('Batch', function () {
it('should properly identify', function (done) {
- seg.identify({ visitor : visitorId,
- session : sessionId,
- traits : { baller : true }}, function (err, result) {
+ setListeners(seg, done);
- should.not.exist(err);
-
- done();
- });
+ seg.identify({ userId : userId,
+ sessionId : sessionId,
+ traits : { baller : true }});
});
it('should properly track', function (done) {
- seg.track({ visitor : visitorId,
- event : 'Ate a cookie' }, function (err, result) {
-
- should.not.exist(err);
+ setListeners(seg, done);
- done();
- });
+ seg.track({ userId : userId,
+ event : 'Ate a cookie' });
});
Please sign in to comment.
Something went wrong with that request. Please try again.