Set up purchase tracking

This commit is contained in:
Blade Barringer
2015-07-06 08:11:31 -05:00
parent e6f0acba4c
commit e6ee4d303c
3 changed files with 184 additions and 54 deletions

View File

@@ -5,7 +5,7 @@
"main": "./website/src/server.js",
"dependencies": {
"amazon-payments": "0.0.4",
"amplitude": "^1.0.3",
"amplitude": "1.0.4",
"async": "~0.9.0",
"aws-sdk": "^2.0.25",
"babel": "^5.5.4",

View File

@@ -6,73 +6,151 @@ var rewire = require('rewire');
describe('analytics', function() {
var amplitudeMock = sinon.stub();
var googleAnalyticsMock = sinon.stub();
describe('init', function() {
var analytics = rewire('../../website/src/analytics');
afterEach(function(){
amplitudeMock.reset();
googleAnalyticsMock.reset();
});
it('throws an error if no options are passed in', function() {
expect(analytics).to.throw('No options provided');
});
it('registers amplitude with token', function() {
analytics.__set__('Amplitude', amplitudeMock);
var options = {
amplitudeToken: 'token'
};
analytics(options);
expect(amplitudeMock).to.be.calledOnce;
expect(amplitudeMock).to.be.calledWith('token');
});
it('registers google analytics with token', function() {
analytics.__set__('googleAnalytics', googleAnalyticsMock);
var options = {
googleAnalytics: 'token'
};
analytics(options);
expect(googleAnalyticsMock).to.be.calledOnce;
expect(googleAnalyticsMock).to.be.calledWith('token');
});
});
describe('trackPurchase', function() {
var purchaseData = {
uuid: 'user-id',
sku: 'paypal-checkout',
paymentMethod: 'PayPal',
itemPurchased: 'Gems',
purchaseValue: 8,
purchaseType: 'checkout',
gift: false,
quantity: 1
}
var analytics = rewire('../../website/src/analytics');
var amplitudeTrack = sinon.stub();
var googleEvent = sinon.stub().returns({
send: function() { return true }
});
var googleItem = sinon.stub().returns({
send: function() {}
});
var googleTransaction = sinon.stub().returns({
item: googleItem
});
var initializedAnalytics;
beforeEach(function() {
analytics.__set__('Amplitude', amplitudeMock);
initializedAnalytics = analytics({amplitudeToken: 'token', googleAnalytics: 'token'});
analytics.__set__('amplitude.track', amplitudeTrack);
analytics.__set__('ga.event', googleEvent);
analytics.__set__('ga.transaction', googleTransaction);
});
afterEach(function(){
amplitudeMock.reset();
googleEvent.reset();
googleTransaction.reset();
googleItem.reset();
});
it('throws an error if no options are passed in', function() {
expect(analytics.init).to.throw('No options provided');
});
it('calls amplitude.track', function() {
it('registers amplitude with token', function() {
var options = {
amplitudeToken: 'token',
uuid: 'user-id'
};
analytics.init(options);
initializedAnalytics.trackPurchase(purchaseData);
expect(amplitudeMock).to.be.calledOnce;
expect(amplitudeMock).to.be.calledWith('token', 'user-id');
});
it('does not register amplitude without token', function() {
var options = { uuid: 'user-id' };
analytics.init(options);
expect(amplitudeMock).to.not.be.called;
});
});
describe('track', function() {
var analytics = rewire('../../website/src/analytics');
context('amplitude not initialized', function() {
it('throws error', function() {
expect(analytics.track).to.throw('Amplitude not initialized');
expect(amplitudeTrack).to.be.calledOnce;
expect(amplitudeTrack).to.be.calledWith({
event_type: 'purchase',
user_id: 'user-id',
event_properties: {
paymentMethod: 'PayPal',
sku: 'paypal-checkout',
gift: false,
itemPurchased: 'Gems',
purchaseType: 'checkout',
quantity: 1
},
revenue: 8
});
});
context('amplitude initialized', function() {
var amplitudeTrack = sinon.stub();
it('calls ga.event', function() {
beforeEach(function() {
analytics.__set__('Amplitude', amplitudeMock);
analytics.init({amplitudeToken: 'token', uuid: 'user-id'});
analytics.__set__('amplitude.track', amplitudeTrack);
});
initializedAnalytics.trackPurchase(purchaseData);
afterEach(function(){
amplitudeMock.reset();
});
expect(googleEvent).to.be.calledOnce;
expect(googleEvent).to.be.calledWith(
'commerce',
'checkout',
'PayPal',
8
);
});
it('tracks event in amplitude', function() {
var data = {
foo: 'bar'
};
it('calls ga.transaction', function() {
analytics.track(data);
initializedAnalytics.trackPurchase(purchaseData);
expect(amplitudeTrack).to.be.calledOnce;
expect(amplitudeTrack).to.be.calledWith(data);
});
expect(googleTransaction).to.be.calledOnce;
expect(googleTransaction).to.be.calledWith(
'user-id',
8
);
expect(googleItem).to.be.calledOnce;
expect(googleItem).to.be.calledWith(
8,
1,
'paypal-checkout',
'Gems',
'checkout'
);
});
it('appends gift to variation of ga.transaction.item if gift is true', function() {
var purchaseDataWithGift = _.clone(purchaseData);
purchaseDataWithGift.gift = true;
initializedAnalytics.trackPurchase(purchaseDataWithGift);
expect(googleItem).to.be.calledOnce;
expect(googleItem).to.be.calledWith(
8,
1,
'paypal-checkout',
'Gems',
'checkout - Gift'
);
});
});
});

View File

@@ -1,22 +1,74 @@
var _ = require('lodash');
var Amplitude = require('amplitude');
var googleAnalytics = require('universal-analytics');
var ga;
var amplitude;
var analytics = {
init: init,
track: track
trackPurchase: trackPurchase
}
function init(options) {
if(!options) { throw 'No options provided' }
if(options.amplitudeToken) {
amplitude = new Amplitude(options.amplitudeToken, options.uuid);
amplitude = new Amplitude(options.amplitudeToken);
ga = googleAnalytics(options.googleAnalytics);
return analytics;
}
function trackPurchase(data) {
_sendPurchaseDataToAmplitude(data);
_sendPurchaseDataToGoogle(data);
}
function _sendPurchaseDataToAmplitude(data) {
var amplitudeData = _formatDataForAmplitude(data);
amplitudeData.event_type = 'purchase';
amplitudeData.revenue = data.purchaseValue;
amplitude.track(amplitudeData)
}
function _formatDataForAmplitude(data) {
var PROPERTIES_TO_SCRUB = ['uuid', 'user', 'purchaseValue'];
var event_properties = _.omit(data, PROPERTIES_TO_SCRUB);
var ampData = {
user_id: data.uuid,
event_properties: event_properties
}
if(data.user) {
ampData.user_properties = _formatUserData(data.user);
}
return ampData;
}
function track(data) {
if(!amplitude) throw 'Amplitude not initialized';
amplitude.track(data);
function _formatUserData(user) {
var data = {};
return data;
}
module.exports = analytics;
function _sendPurchaseDataToGoogle(data) {
var label = data.paymentMethod;
var type = data.purchaseType;
var price = data.purchaseValue;
var qty = data.quantity;
var sku = data.sku;
var itemName = data.itemPurchased;
var variation = type;
if(data.gift) variation += ' - Gift';
ga.event('commerce', type, label, price)
.send();
ga.transaction(data.uuid, price)
.item(price, qty, sku, itemName, variation)
.send();
}
module.exports = init;