From d1a2c3e8d33135ae1f36561356908db562306bcb Mon Sep 17 00:00:00 2001 From: Paul Scott Date: Wed, 24 Mar 2021 19:05:12 +0000 Subject: [PATCH] ravelin.track.event(name, [props]) (#40) --- README.md | 9 ++++++++ lib/track.js | 18 ++++++++++++---- test/track.test.js | 44 ++++++++++++++++++++++++++++++++++++++-- test/track/track.spec.js | 6 +++--- 4 files changed, 68 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index a2a4038..c7b95f2 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ and [source](https://github.com/unravelin/ravelinjs/tree/v0). * [`ravelin.core.id(): Promise`](#ravelincoreid-promisestring) * [`ravelin.encrypt.card(card: object): object`](#ravelinencryptcardcard-object-object) * [`ravelin.track.load()`](#ravelintrackload) + * [`ravelin.track.event(name, [props])`](#ravelintrackeventname-props) * [`ravelin.track.paste(event: ClipboardEvent)`](#ravelintrackpasteevent-clipboardevent) * [Vendored Code](#vendored-code) * [Upgrading](#upgrading) @@ -348,6 +349,14 @@ single-page app. To ensure the correct page title is collected, call after the page content has loaded - so the [Window popstate][popstate] event may be too early. +### `ravelin.track.event(name, [props])` + +Send a named event to attach to the session, with optional descriptive +properties. Most event names use "UPPER_SNAKE_CASE" but the most important thing +is to have consistency between your browser and mobile applications where they +have common events. Returns a Promise that resolves once the event has been +sent. + ### `ravelin.track.paste(event: ClipboardEvent)` Send a paste event to Ravelin. This is done automatically if the paste happens diff --git a/lib/track.js b/lib/track.js index 9489494..86ce85f 100644 --- a/lib/track.js +++ b/lib/track.js @@ -95,7 +95,7 @@ Track.prototype._attach = function(e) { * _detach removes event listeners that we added. */ Track.prototype._detach = function() { - while (this._listeners.length > 0) { + while (this._listeners && this._listeners.length > 0) { var e = this._listeners.pop(); var fn = e.target[e.delFn]; if (fn.call) { @@ -108,11 +108,11 @@ Track.prototype._detach = function() { /** * send an event to Ravelin. - * @param {string} name - * @param {string} type + * @param {string} type Identifies the origin of the event. + * @param {string} name A description of what occurred. * @param {object} [props] */ -Track.prototype._send = function(name, type, props) { +Track.prototype._send = function(type, name, props) { var that = this; return this.core.id().then(function(deviceId) { return that.core.send('POST', '/z', {events: [{ @@ -144,6 +144,16 @@ Track.prototype.load = function() { return this._send('track', 'PAGE_LOADED'); }; +/** + * event sends a user-driven event to Ravelin. + * @param {string} name The name of the event. + * @param {object} [props] Additional properties to describe the event. + * @returns + */ +Track.prototype.event = function(name, props) { + return this._send('track', name, props); +}; + /** * resize event handler. */ diff --git a/test/track.test.js b/test/track.test.js index 293a967..7a41cd5 100644 --- a/test/track.test.js +++ b/test/track.test.js @@ -21,9 +21,9 @@ describe('ravelin.track', function() { r.core.id().then(function(deviceId) { var loadEvent = JSON.parse(req.body).events[0]; - expect(loadEvent).to.have.property('eventType', 'PAGE_LOADED'); + expect(loadEvent).to.have.property('eventType', 'track'); expect(loadEvent).to.have.property('libVer', '1.1.2-ravelinjs'); - expect(loadEvent.eventData).to.eql({eventName: 'track'}); + expect(loadEvent.eventData).to.eql({eventName: 'PAGE_LOADED'}); expect(loadEvent.eventMeta.trackingSource).to.be('browser'); expect(loadEvent.eventMeta.ravelinDeviceId).to.be(deviceId); }).then(done, done); @@ -33,6 +33,46 @@ describe('ravelin.track', function() { }); }); + describe('#event', function() { + it('sends custom events', function(done) { + var key = this.test.fullTitle(); + xhook.before(function(req) { + if (!keysMatch(req, key)) return {status: 204}; + + r.core.id().then(function(deviceId) { + var e = JSON.parse(req.body).events[0]; + expect(e).to.have.property('eventType', 'track'); + expect(e).to.have.property('libVer', '1.1.2-ravelinjs'); + expect(e.eventData).to.eql({eventName: 'custom-event'}); + expect(e.eventMeta.trackingSource).to.be('browser'); + expect(e.eventMeta.ravelinDeviceId).to.be(deviceId); + }).then(done, done); + return {status: 204}; + }); + r = new Ravelin({key: key, api: '/', init: false}); + r.track.event('custom-event'); + }); + + it('sends custom events with properties', function(done) { + var key = this.test.fullTitle(); + xhook.before(function(req) { + if (!keysMatch(req, key)) return {status: 204}; + + r.core.id().then(function(deviceId) { + var e = JSON.parse(req.body).events[0]; + expect(e).to.have.property('eventType', 'track'); + expect(e).to.have.property('libVer', '1.1.2-ravelinjs'); + expect(e.eventData).to.eql({eventName: 'custom-event', properties: {extra: true}}); + expect(e.eventMeta.trackingSource).to.be('browser'); + expect(e.eventMeta.ravelinDeviceId).to.be(deviceId); + }).then(done, done); + return {status: 204}; + }); + r = new Ravelin({key: key, api: '/', init: false}); + r.track.event('custom-event', {extra: true}); + }); + }); + describe('#paste', function() { // IE8 doesn't support createEvent or paste handling at all. var capable = !!document.createEvent; diff --git a/test/track/track.spec.js b/test/track/track.spec.js index f5faf00..205f4f5 100644 --- a/test/track/track.spec.js +++ b/test/track/track.spec.js @@ -44,7 +44,7 @@ describe('ravelin.track', function () { query: { key: key }, "bodyJSON.events": { "$elemMatch": { - eventType: 'PAGE_LOADED', + eventData: {eventName: 'PAGE_LOADED'}, } } }) @@ -54,8 +54,8 @@ describe('ravelin.track', function () { objDiff( loadEvent.bodyJSON.events[0], { - eventType: 'PAGE_LOADED', - eventData: { eventName: "track" }, + eventType: 'track', + eventData: { eventName: 'PAGE_LOADED' }, eventMeta: { trackingSource: "browser", pageTitle: "track test",