Skip to content

Commit d7b1e87

Browse files
committed
Merge pull request #6 from amplitude/logRevenue
Add logRevenue support
2 parents f610d1e + f7b8d54 commit d7b1e87

File tree

8 files changed

+135
-9
lines changed

8 files changed

+135
-9
lines changed

README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Amplitude-Javascript
1212
n.async=true;n.src="https://d24n15hnbwhuhn.cloudfront.net/libs/amplitude-2.0.4-min.js";
1313
var s=t.getElementsByTagName("script")[0];s.parentNode.insertBefore(n,s);r._q=[];
1414
function a(e){r[e]=function(){r._q.push([e].concat(Array.prototype.slice.call(arguments,0)))
15-
}}var i=["init","logEvent","setUserId","setUserProperties","setOptOut","setVersionName","setDomain","setDeviceId","setGlobalUserProperties"];
15+
}}var i=["init","logEvent","logRevenue","setUserId","setUserProperties","setOptOut","setVersionName","setDomain","setDeviceId","setGlobalUserProperties"];
1616
for(var o=0;o<i.length;o++){a(i[o])}e.amplitude=r})(window,document);
1717

1818
amplitude.init("YOUR_API_KEY_HERE");
@@ -57,6 +57,15 @@ To add properties that are tracked in every event, you can set properties for a
5757
userProperties.key = "value";
5858
amplitude.setUserProperties(userProperties);
5959

60+
# Tracking Revenue #
61+
62+
To track revenue from a user, call
63+
64+
amplitude.logRevenue(9.99, 1, "product");
65+
66+
The function takes a unit price, a quantity, and a product identifier. Quantity and product identifier are optional parameters.
67+
68+
This allows us to automatically display data relevant to revenue on the Amplitude website, including average revenue per daily active user (ARPDAU), 7, 30, and 90 day revenue, lifetime value (LTV) estimates, and revenue by advertising campaign cohort and daily/weekly/monthly cohorts.
6069

6170
# Opting User Out of Logging #
6271

amplitude-snippet.min.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
n.async=true;n.src="https://d24n15hnbwhuhn.cloudfront.net/libs/amplitude-2.0.4-min.js";
33
var s=t.getElementsByTagName("script")[0];s.parentNode.insertBefore(n,s);r._q=[];
44
function a(e){r[e]=function(){r._q.push([e].concat(Array.prototype.slice.call(arguments,0)))
5-
}}var i=["init","logEvent","setUserId","setUserProperties","setOptOut","setVersionName","setDomain","setDeviceId","setGlobalUserProperties"];
5+
}}var i=["init","logEvent","logRevenue","setUserId","setUserProperties","setOptOut","setVersionName","setDomain","setDeviceId","setGlobalUserProperties"];
66
for(var o=0;o<i.length;o++){a(i[o])}e.amplitude=r})(window,document);

amplitude.js

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,10 @@ Amplitude.prototype.setVersionName = function(versionName) {
384384
}
385385
};
386386

387-
Amplitude.prototype.logEvent = function(eventType, eventProperties) {
387+
/**
388+
* Private logEvent method. Keeps apiProperties from being publicly exposed.
389+
*/
390+
Amplitude.prototype._logEvent = function(eventType, eventProperties, apiProperties) {
388391
if (!eventType || this.options.optOut) {
389392
return;
390393
}
@@ -405,6 +408,7 @@ Amplitude.prototype.logEvent = function(eventType, eventProperties) {
405408
object.merge(userProperties, this.options.userProperties || {});
406409
object.merge(userProperties, this._utmProperties);
407410

411+
apiProperties = apiProperties || {};
408412
eventProperties = eventProperties || {};
409413
var event = {
410414
device_id: this.options.deviceId,
@@ -419,6 +423,7 @@ Amplitude.prototype.logEvent = function(eventType, eventProperties) {
419423
os_version: ua.browser.version,
420424
device_model: ua.os.family,
421425
language: this.options.language,
426+
api_properties: apiProperties,
422427
event_properties: eventProperties,
423428
user_properties: userProperties,
424429
uuid: UUID(),
@@ -439,6 +444,30 @@ Amplitude.prototype.logEvent = function(eventType, eventProperties) {
439444
}
440445
};
441446

447+
Amplitude.prototype.logEvent = function(eventType, eventProperties) {
448+
this._logEvent(eventType, eventProperties);
449+
};
450+
451+
// Test that n is a number or a numeric value.
452+
var _isNumber = function(n) {
453+
return !isNaN(parseFloat(n)) && isFinite(n);
454+
};
455+
456+
Amplitude.prototype.logRevenue = function(price, quantity, product) {
457+
// Test that the parameters are of the right type.
458+
if (!_isNumber(price) || quantity !== undefined && !_isNumber(quantity)) {
459+
// log('Price and quantity arguments to logRevenue must be numbers');
460+
return;
461+
}
462+
463+
this._logEvent('revenue_amount', {}, {
464+
productId: product,
465+
special: 'revenue_amount',
466+
quantity: quantity || 1,
467+
price: price
468+
});
469+
};
470+
442471
Amplitude.prototype.sendEvents = function() {
443472
if (!this._sending && !this.options.optOut) {
444473
this._sending = true;

amplitude.min.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/amplitude-snippet.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
amplitude._q.push([fn].concat(Array.prototype.slice.call(arguments, 0)));
1313
};
1414
}
15-
var funcs = ["init", "logEvent", "setUserId", "setUserProperties", "setOptOut",
16-
"setVersionName", "setDomain", "setDeviceId",
15+
var funcs = ["init", "logEvent", "logRevenue", "setUserId", "setUserProperties",
16+
"setOptOut", "setVersionName", "setDomain", "setDeviceId",
1717
"setGlobalUserProperties"];
1818
for (var i = 0; i < funcs.length; i++) {
1919
proxy(funcs[i]);

src/amplitude.js

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,10 @@ Amplitude.prototype.setVersionName = function(versionName) {
272272
}
273273
};
274274

275-
Amplitude.prototype.logEvent = function(eventType, eventProperties) {
275+
/**
276+
* Private logEvent method. Keeps apiProperties from being publicly exposed.
277+
*/
278+
Amplitude.prototype._logEvent = function(eventType, eventProperties, apiProperties) {
276279
if (!eventType || this.options.optOut) {
277280
return;
278281
}
@@ -293,6 +296,7 @@ Amplitude.prototype.logEvent = function(eventType, eventProperties) {
293296
object.merge(userProperties, this.options.userProperties || {});
294297
object.merge(userProperties, this._utmProperties);
295298

299+
apiProperties = apiProperties || {};
296300
eventProperties = eventProperties || {};
297301
var event = {
298302
device_id: this.options.deviceId,
@@ -307,6 +311,7 @@ Amplitude.prototype.logEvent = function(eventType, eventProperties) {
307311
os_version: ua.browser.version,
308312
device_model: ua.os.family,
309313
language: this.options.language,
314+
api_properties: apiProperties,
310315
event_properties: eventProperties,
311316
user_properties: userProperties,
312317
uuid: UUID(),
@@ -327,6 +332,30 @@ Amplitude.prototype.logEvent = function(eventType, eventProperties) {
327332
}
328333
};
329334

335+
Amplitude.prototype.logEvent = function(eventType, eventProperties) {
336+
this._logEvent(eventType, eventProperties);
337+
};
338+
339+
// Test that n is a number or a numeric value.
340+
var _isNumber = function(n) {
341+
return !isNaN(parseFloat(n)) && isFinite(n);
342+
};
343+
344+
Amplitude.prototype.logRevenue = function(price, quantity, product) {
345+
// Test that the parameters are of the right type.
346+
if (!_isNumber(price) || quantity !== undefined && !_isNumber(quantity)) {
347+
// log('Price and quantity arguments to logRevenue must be numbers');
348+
return;
349+
}
350+
351+
this._logEvent('revenue_amount', {}, {
352+
productId: product,
353+
special: 'revenue_amount',
354+
quantity: quantity || 1,
355+
price: price
356+
});
357+
};
358+
330359
Amplitude.prototype.sendEvents = function() {
331360
if (!this._sending && !this.options.optOut) {
332361
this._sending = true;

test/amplitude.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,65 @@ describe('Amplitude', function() {
341341
});
342342
});
343343

344+
describe('logRevenue', function() {
345+
beforeEach(function() {
346+
amplitude.init(apiKey);
347+
});
348+
349+
afterEach(function() {
350+
reset();
351+
});
352+
353+
/**
354+
* Deep compare an object against the api_properties of the
355+
* event queued for sending.
356+
*/
357+
function revenueEqual(api, event) {
358+
assert.lengthOf(server.requests, 1);
359+
var events = JSON.parse(querystring.parse(server.requests[0].requestBody).e);
360+
assert.deepEqual(events[0].api_properties, api || {});
361+
assert.deepEqual(events[0].event_properties, event || {});
362+
}
363+
364+
it('should log simple amount', function() {
365+
amplitude.logRevenue(10.10);
366+
revenueEqual({
367+
special: 'revenue_amount',
368+
price: 10.10,
369+
quantity: 1
370+
})
371+
});
372+
373+
it('should log complex amount', function() {
374+
amplitude.logRevenue(10.10, 7);
375+
revenueEqual({
376+
special: 'revenue_amount',
377+
price: 10.10,
378+
quantity: 7
379+
})
380+
});
381+
382+
it('shouldn\'t log invalid price', function() {
383+
amplitude.logRevenue('kitten', 7);
384+
assert.lengthOf(server.requests, 0);
385+
});
386+
387+
it('shouldn\'t log invalid quantity', function() {
388+
amplitude.logRevenue(10.00, 'puppy');
389+
assert.lengthOf(server.requests, 0);
390+
});
391+
392+
it('should log complex amount with product id', function() {
393+
amplitude.logRevenue(10.10, 7, 'chicken.dinner');
394+
revenueEqual({
395+
special: 'revenue_amount',
396+
price: 10.10,
397+
quantity: 7,
398+
productId: 'chicken.dinner'
399+
});
400+
});
401+
});
402+
344403
describe('sessionId', function() {
345404

346405
var clock;

test/browser/amplitudejs.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
};
1717
}
1818

19-
var funcs = ["init", "logEvent", "setUserId", "setUserProperties", "setOptOut", "setVersionName", "setDomain", "setGlobalUserProperties"];
19+
var funcs = ["init", "logEvent", "logRevenue", "setUserId", "setUserProperties", "setOptOut", "setVersionName", "setDomain", "setGlobalUserProperties"];
2020
for (var i = 0; i < funcs.length; i++) {
2121
proxy(funcs[i]);
2222
}

0 commit comments

Comments
 (0)