Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

gosquared

Package Overview
Dependencies
Maintainers
4
Versions
23
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

gosquared - npm Package Compare versions

Comparing version 1.0.1 to 2.0.0

lib/api/Account.js

69

config.js

@@ -1,13 +0,7 @@

var URL = require('url');
var h = require('./lib/helpers');
var url = require('url');
var utils = require('./lib/utils');
var endpoints = {
data: {
url: 'https://data.gosquared.com',
method: 'POST'
},
api: {
url: 'https://api.gosquared.com',
method: 'GET'
href: 'https://api.gosquared.com'
}

@@ -17,7 +11,7 @@ };

Object.keys(endpoints).forEach(function(l){
var url;
if((url = process.env[l+'Endpoint'])){
var pUrl = URL.parse(url);
var href;
if((href = process.env[l+'Endpoint'])){
var pUrl = url.parse(href);
if(!pUrl) return;
h.extend(endpoints[l], pUrl);
utils.extend(endpoints[l], pUrl);
}

@@ -27,50 +21,3 @@ });

module.exports = {
endpoints: endpoints,
gsEvent: {
route: '/event'
},
api: {
'account': {
'def': 'v1',
'v1': [
"alertPreferences",
"ignoredVisitors",
"reportPreferences",
"sites"
]
},
'now': {
'def': 'v3',
'v3': [
"aggregateStats",
"campaigns",
"concurrents",
"engagement",
"geo",
"overview",
"pages",
"sources",
"timeSeries",
"visitors"
]
},
'trends': {
'def': 'v2',
'v2': [
"aggregate",
"browser",
"country",
"event",
"language",
"organisation",
"os",
"page",
"path1",
"screenDimensions",
"sources"
]
}
}
endpoint: endpoints.api.href
};

@@ -0,245 +1,67 @@

var Account = require('./api/Account');
var Now = require('./api/Now');
var Trends = require('./api/Trends');
var Ecommerce = require('./api/Ecommerce');
var Tracking = require('./api/Tracking');
var request = require('request');
var config = require('../config');
var h = require('./helpers');
var queryString = require('querystring');
var util = require('util');
var format = util.format;
var Transaction = require('./Transaction');
var Person = require('./Person');
var utils = require('./utils');
var debugLevels = {
NONE: 0,
TRACE: 1,
NOTICE: 1<<1,
WARNING: 1<<2,
FATAL: 1<<3
};
debugLevels.ALL = Math.pow(2, Object.keys(debugLevels).length) -1;
var GoSquared = module.exports = function(opts) {
this.opts = utils.extend({
log: function() {},
requestTimeout: 10000
}, opts);
var messages = {
requestFailed: 'requestFailed',
responseEmpty: 'responseEmpty',
responseParseError: 'responseParseError',
responseInvalid: 'responseInvalid',
missingEventName: 'The event must have a name. No name was given.',
missingSiteToken: 'A site token must be given.',
paramsTooLarge: 'The event parameters were too large. Send fewer / smaller parameters.',
non200Code: 'The HTTP request completed with a non-200 status code.',
errorEncountered: 'The GoSquared server didn\'t like something, so it gave us an error.'
};
this.apiParams = {
site_token: this.opts.site_token || this.opts.siteToken,
api_key: this.opts.api_key || this.opts.apiKey
};
var errors = {
0: '',
1: messages.requestFailed,
2: messages.responseEmpty,
3: messages.responseParseError,
4: messages.responseInvalid,
5: messages.missingEventName,
6: messages.missingSiteToken,
7: messages.requestFailed,
8: messages.paramsTooLarge,
9: messages.non200Code,
10: messages.errorEncountered,
this.log = this.opts.log;
100: "Transaction items must have a name",
101: "Transactions must have an ID"
this.account = new Account(this);
this.now = new Now(this);
this.trends = new Trends(this);
this.ecommerce = new Ecommerce(this);
this.tracking = new Tracking(this);
};
var GoSquared = module.exports = function(opts){
this.opts = h.extend({
requestTimeout: 10000,
debugLevel: 'NONE'
}, opts);
if(!this.opts.site_token){
this._debug(6);
GoSquared.prototype._exec = function(endpoint, path, method, params, data, cb){
if (!cb && typeof data === 'function') {
cb = data;
data = {};
}
this.config = config;
if (!cb) cb = function() {};
this.setupMethods();
};
params = utils.extend({}, params, this.apiParams);
GoSquared.prototype._exec = function(endpoint, path, params, body, cb){
var self = this;
if (!cb && typeof body === 'function') {
cb = body;
body = {};
}
var req = {
url: endpoint.url + path,
url: endpoint + path,
qs: params,
method: endpoint.method,
method: method,
json: true,
body: body,
body: data,
timeout: this.opts.requestTimeout
};
this._debug(0, 'TRACE', req);
this.log(req);
request(req, function(err, res, data) {
if (err) self._debug(1, 'WARNING', { error: err, req: req });
cb(err, data);
});
};
request(req, function(err, res, body) {
if (err) return cb(err);
GoSquared.prototype._validateResponse = function(responseData){
var err;
if(!responseData){
err = 2;
this._debug(err, 'WARNING');
return err;
}
if (!responseData.success && responseData.error) {
var errObj = responseData.error;
switch(errObj.code){
case 1011:
err = 8;
this._debug(err, 'WARNING', errObj);
return err;
default:
err = 10;
this._debug(err, 'WARNING', errObj);
return err;
if (!body) {
err = new Error('Empty response');
err.httpStatus = res.statusCode;
return cb(err, { success: false });
}
}
return responseData;
};
GoSquared.prototype._debug = function(code, level, extra){
var dLevel = this.opts.debugLevel || 'ALL';
if(!(debugLevels[dLevel] & debugLevels[level])) return false;
var stream = console.log;
if(level > debugLevels['NOTICE']) stream = console.error;
// Errors are machine-parseable
stream(
format(
'[GoSquared][%s]:%s', level, JSON.stringify({message: errors[code], code: code, extra: extra})
)
);
};
GoSquared.prototype._makeError = function(code){
var err = new Error(errors[code]);
err.code = code;
return err;
};
GoSquared.prototype.event = function(name, data, cb) {
if(typeof data === 'function'){
cb = data;
data = {};
}
if(!name){
this._debug(5, 'WARNING');
return cb && cb(this._makeError(5));
}
this._exec(this.config.endpoints.data, '/' + this.opts.site_token + '/v1/event', { name: name }, data, this._responseCompleted.bind(this, cb));
};
GoSquared.prototype.createTransaction = GoSquared.prototype.Transaction = function(transactionID, opts){
return new Transaction(this, transactionID, opts);
};
GoSquared.prototype.createPerson = GoSquared.prototype.Person = function(id, opts){
return new Person(this, id);
};
GoSquared.prototype._responseCompleted = function(cb, err, responseData){
if (!cb) cb = function(){};
if(err){
this._debug(7, 'WARNING');
return cb(err);
}
var validated = this._validateResponse(responseData);
if (typeof validated !== "object") {
if (typeof validated === "number") {
err = this._makeError(validated);
if (!body.success && res.statusCode !== 200) {
err = new Error(body.message || 'HTTP ' + res.statusCode);
err.code = body.code;
err.httpStatus = res.statusCode;
}
return cb(err);
}
cb(null, validated);
cb(err, body);
});
};
var createMethod = function(namespace, version, func) {
var self = this;
return function(opts, cb){
if (typeof opts == 'function'){
cb = opts;
opts = {};
}
if (typeof opts != 'object') opts = {};
if (typeof cb != 'function') cb = function(){};
var endpoint = self.config.endpoints.api;
opts.site_token = opts.site_token || self.opts.site_token;
opts.api_key = opts.api_key || self.opts.api_key;
self._exec(endpoint, '/' + namespace + '/'+ version + '/' + func, opts, self._responseCompleted.bind(self, cb));
};
};
/**
* Create API methods nested in properties that reflect the API structure
*
* GoSquared[namespace][version][function]
*
* Also, for default versions:
*
* GoSquared[namespace][function]
*
*/
GoSquared.prototype.setupMethods = function() {
var self = this;
// set up the methods for each version and namespace
var functions = config.api;
for (var namespace in functions) {
var n = self[namespace];
// ensure object exists
if (!n) n = self[namespace] = {};
for (var version in functions[namespace]) {
if (version === 'def') continue;
var v = n[version];
// ensure version object exists
if (!v) v = n[version] = {};
var fncs = functions[namespace][version];
for (var i = 0; i < fncs.length; i++) {
var f = v[fncs[i]] = createMethod.call(self, namespace, version, fncs[i]);
// is this the default version?
if (version === functions[namespace]['def']) {
// set it on the namespace (e.g. $.GoSquared.now.concurrents)
n[fncs[i]] = f;
}
}
}
}
};
var crypto = require('crypto');
var h = require('./helpers');
var utils = require('./utils');
var Transaction = require('./Transaction');
var Event = require('./Event');
var config = require('../config');

@@ -13,5 +16,3 @@ var Person = module.exports = function(GS, id) {

v = v.toString();
this._id = v;
this.baseURL = '/' + GS.opts.site_token + '/v1/people/' + encodeURIComponent(v);
this.auth();
this._id = ''+v;
},

@@ -24,32 +25,23 @@ enumerable: true

Person.prototype.auth = function() {
var key = this.GS.opts.tracking_key;
if (!key) return this.authParams = {};
return this.authParams = { auth: crypto.createHmac('sha256', key).update(this.id).digest('hex') };
};
Person.prototype._exec = function(url, params, data, cb) {
var GS = this.GS;
params = h.extend({}, params, this.authParams);
GS._exec(GS.config.endpoints.data, this.baseURL + url, params, data, GS._responseCompleted.bind(GS, cb));
GS._exec(config.endpoint + '/tracking/v1', url, 'POST', params, data, cb);
};
// identify is a quick way to both alias and set properties on a person
Person.prototype.identify = function(newID, data, cb) {
Person.prototype.identify = function(newID, props, cb) {
// if we don't have an anonymous ID, just go straight to adding the data as properties
if (!this.id) {
this.id = newID;
return this.setProperties(data, cb);
return this.setProperties(props, cb);
}
if (!cb && typeof data === 'function') {
cb = data;
data = {};
if (!cb && typeof props === 'function') {
cb = props;
props = {};
}
if (typeof newID === 'object') {
data = newID;
newID = data.id;
props = newID;
newID = props.id;
}

@@ -59,19 +51,23 @@

if (!newID) {
return this.setProperties(data, cb);
return this.setProperties(props, cb);
}
this._exec('/identify/' + encodeURIComponent(newID), {}, data, cb);
var data = { visitor_id: this.id, person_id: ''+newID };
if (props) data.properties = props;
this._exec('/identify', {}, data, cb);
};
Person.prototype.alias = function(newID, cb) {
this._exec('/alias/' + encodeURIComponent(newID), {}, {}, cb);
var data = { visitor_id: this.id, person_id: ''+newID };
this.id = newID;
this._exec('/alias', {}, data, cb);
};
Person.prototype.setProperties = function(data, cb) {
Person.prototype.setProperties = function(props, cb) {
var data = { person_id: this.id, properties: props };
this._exec('/properties', {}, data, cb);
};
Person.prototype.event = function(name, data, cb) {
if(!cb && typeof data == 'function'){
Person.prototype.trackEvent = function(name, data, cb) {
if (typeof data === 'function') {
cb = data;

@@ -81,17 +77,11 @@ data = {};

if(!name){
this.GS._debug(5, 'WARNING');
return cb && cb(this.GS._makeError(5));
}
this._exec('/event', { name: name }, data, cb);
var event = new Event(this.GS, name, data);
event.personID = this.id;
event.track(cb);
};
Person.prototype.createTransaction = function(transactionID, opts) {
var t = this.GS.createTransaction(transactionID, opts);
t.params = {
personID: this.id,
auth: this.authParams.auth
};
var t = new Transaction(this.GS, transactionID, opts);
t.personID = this.id;
return t;
};

@@ -1,2 +0,3 @@

var util = require('util');
var utils = require('./utils');
var config = require('../config');

@@ -7,2 +8,3 @@ var Transaction = module.exports = function(GS, transactionID, opts){

this.items = [];
this.params = {};

@@ -14,8 +16,2 @@ if (typeof transactionID === 'object') {

if (typeof this.id === 'undefined') {
this.GS._debug(101, 'WARNING');
} else {
this.id = '' + this.id;
}
if (typeof opts === 'object') {

@@ -32,4 +28,2 @@ this.opts = opts;

if (!itemOpts.name) return this.GS._debug(100, 'WARNING');
this.items.push(itemOpts);

@@ -46,3 +40,3 @@ };

Transaction.prototype.track = function(cb){
var GS = this.GS;
var GS = this.GS, err;

@@ -53,14 +47,28 @@ if(typeof cb !== 'function'){

if (typeof this.id === 'undefined') return cb('transactionID not given');
if (typeof this.id === 'undefined') {
err = new Error('Transaction ID not given');
err.transaction = this;
return cb(err);
}
var data = {
id: this.id,
items: this.items,
opts: this.opts
for (var i = 0; i < this.items.length; i++) {
var it = this.items[i];
if (!it.name) {
err = new Error('Item name not given');
err.item = it;
err.transaction = this;
return cb(err);
}
}
var body = {
person_id: this.personID,
transaction: {
id: this.id,
items: this.items,
opts: this.opts
}
};
// not the tidiest
var params = this.params || {};
GS._exec(GS.config.endpoints.data, '/' + GS.opts.site_token + '/v1/transaction', params, data, GS._responseCompleted.bind(GS, cb));
GS._exec(config.endpoint + '/tracking/v1', '/transaction', 'POST', this.params, body, cb);
};
{
"name": "gosquared",
"version": "1.0.1",
"version": "2.0.0",
"description": "GoSquared for your Node.JS application",

@@ -9,4 +9,10 @@ "main": "lib/GoSquared.js",

"gosquared",
"API",
"analytics"
"people",
"user",
"event",
"analytics",
"tracking",
"reporting",
"metrics",
"API"
],

@@ -32,8 +38,14 @@ "contributors": [

"dependencies": {
"request": "^2.44.0"
"request": "^2.51.0"
},
"devDependencies": {
"mocha": "~1.8.1",
"should": "~1.2.1"
"async": "^0.9.0",
"mocha": "~1.8.1"
},
"scripts": {
"test": "./node_modules/mocha/bin/mocha",
"test-tracking": "./node_modules/mocha/bin/mocha test/tracking",
"test-retrieval": "./node_modules/mocha/bin/mocha test/retrieval",
"test-account": "./node_modules/mocha/bin/mocha test/account"
}
}
# node-gosquared
This lightweight module allows you to integrate the [GoSquared API][api-docs] into your Node.JS app with ease.
The official GoSquared Node.js module for integrating the [GoSquared API](docs) into your Node.JS app with ease.
Commonly, you'll use this module to retrieve analytics data collected by GoSquared, but it can also be used to manage accounts, store events, and record transactions for GoSquared Ecommerce.
## Installation
It can also be used in a backend app to proxy requests from a frontend app to the GoSquared API so you don't publicly expose your API Key.
## Installation
```bash

@@ -16,16 +13,17 @@ npm install --save gosquared

### Tracking API
See the [Tracking API][tracking-docs] docs site for full documentation.
### Reporting API
```javascript
var GoSquared = require('gosquared');
var gosquared = new GoSquared(opts);
var gosquared = new GoSquared({
api_key: 'demo',
site_token: 'GSN-181546-E'
});
```
##### Options
* api_key: API key from your [account][casa]. Required for API functions, not required for tracking functions.
* site_token: Token for the registered site you're working with. Required.
* requestTimeout: Maximum time in ms an API request can be pending. Default 2000ms
* debugLevel: One of 'NONE', TRACE', 'NOTICE', 'WARNING', 'ALL'. Default 'WARNING'
### API
Methods mirror the structure of the GoSquared API:

@@ -37,3 +35,3 @@

Consult the [API Docs][api-docs] for available namespaces, versions, and functions.
Consult the [Reporting API Docs][reporting-docs] for available namespaces, versions, and functions.

@@ -56,122 +54,15 @@ **Example**: We want to get the total number of visitors online on the site right now. For this, we need to use the `concurrents` function under the `v3` version of the `now` namespace:

All functions listed in the [API documentation][api-docs] are methods you can call on the ```gosquared``` object. The documentation also demonstrates the response data you can expect to get back.
All functions listed in the [Reporting API][reporting-docs] documentation are methods you can call on the ```gosquared``` object. The documentation also demonstrates the response data you can expect to get back.
## Run tests
### Recording data
The module can also be used to send data to GoSquared.
#### Transactions
To track a transaction:
```javascript
var transactionID = 123456789;
var t = gosquared.createTransaction(transationID);
// Make sure each item has a name
t.addItem('Beer', {
price: 3.50,
quantity: 1,
category: 'Alcoholic Drinks'
});
// You can also add multiple items at once
t.addItems([
{
name: 'More Beer',
price: 4.99,
quantity: 2,
category: 'Alcoholic Drinks'
},
{
name: 'Limoncello',
price: 17.99,
quantity: 1,
category: 'Liquor'
}
]);
// Send off to GoSquared
t.track(function(){
// Done
});
```
GoSquared automatically calculates the total revenue and quantity for each transaction by summing these values of each item. If you would like to override the total transaction revenue and quantity, you can set them as transaction options:
```javascript
// Override revenue and quantity amounts
var opts = {
revenue: 10,
quantity: 5
};
var t = gosquared.createTransaction(transactionID, opts);
t.track();
```
##### Including additional info
One of the features of GoSquared Ecommerce is the ability to attribute revenue and quantity amounts to aspects of the customer, such as their country, language, browser or referring source. Although GoSquared is not able to automatically detect these for backend-triggered events, you can pass in the values GoSquared needs for this functionality.
To do this, include any of the following in the transaction's options object:
```javascript
var userAgent = 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36'; // The browser's user agent
var ip = '0.0.0.0'; // The cusomer's IP address. IPv4 or IPv6
var language = 'en-gb'; // The customer's ISO 639-1 language string
var referringURL = 'http://www.gosquared.com/ecommerce/'; // The referring URL of the customer's visit
var previousTransaction = {
ts: Date.now() // The UNIX timestamp in ms of the customer's previous transaction, if any
};
var opts = {
ua: userAgent,
ip: ip,
la: language,
ru: referringURL,
pt: previousTransaction
};
var t = gosquared.createTransaction(transactionID, opts);
```
#### Events
Send events to GoSquared:
```javascript
gosquared.event('Test Event', {
its: true,
'you can': 'store',
any: 'event',
properties: 'You Like'
},
function(e, res){
if(e) return console.log(e);
console.log(res);
}
);
```
## Run tests
Install test dependencies using ```npm install``` then:
```bash
make test
SITE_TOKEN=<your site token> API_KEY=<your api key> npm test-tracking
SITE_TOKEN=<your site token> API_KEY=<your api key> npm test-retrieval
```
Optionally, you can run the tests with a site token and API key of your choice:
```bash
SITE_TOKEN=<your token> API_KEY=<your api key> make test
```
[api-docs]: https://www.gosquared.com/developer/api/
[casa]: https://www.gosquared.com/home/developer
[reporting-docs]: https://gosquared.com/developer/api/
[tracking-docs]: https://beta.gosquared.com/docs/tracking/api/
[docs]: https://beta.gosquared.com/docs

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc