From 2b3a41983ae7b1c4e245d41d782d68dc5927df5a Mon Sep 17 00:00:00 2001 From: Fizer Khan Date: Fri, 21 Feb 2020 17:31:35 +0530 Subject: [PATCH 1/3] Added replaybird-segment integration. --- integrations/replaybird/HISTORY.md | 4 + integrations/replaybird/README.md | 12 +++ integrations/replaybird/karma.conf-ci.js | 1 + integrations/replaybird/karma.conf.js | 1 + integrations/replaybird/lib/index.js | 118 +++++++++++++++++++++ integrations/replaybird/package.json | 49 +++++++++ integrations/replaybird/test/index.test.js | 116 ++++++++++++++++++++ 7 files changed, 301 insertions(+) create mode 100644 integrations/replaybird/HISTORY.md create mode 100644 integrations/replaybird/README.md create mode 100644 integrations/replaybird/karma.conf-ci.js create mode 100644 integrations/replaybird/karma.conf.js create mode 100644 integrations/replaybird/lib/index.js create mode 100644 integrations/replaybird/package.json create mode 100644 integrations/replaybird/test/index.test.js diff --git a/integrations/replaybird/HISTORY.md b/integrations/replaybird/HISTORY.md new file mode 100644 index 000000000..6db9f05cf --- /dev/null +++ b/integrations/replaybird/HISTORY.md @@ -0,0 +1,4 @@ +1.0.0 / 2020-02-21 +================== + + * Initial commit diff --git a/integrations/replaybird/README.md b/integrations/replaybird/README.md new file mode 100644 index 000000000..d80579e09 --- /dev/null +++ b/integrations/replaybird/README.md @@ -0,0 +1,12 @@ +# analytics.js-integration-replaybird [![Build Status][ci-badge]][ci-link] + +ReplayBird integration for [Analytics.js][]. + +## License + +Released under the [MIT license](LICENSE). + + +[Analytics.js]: https://segment.com/docs/libraries/analytics.js/ +[ci-link]: https://circleci.com/gh/segment-integrations/analytics.js-integration-replaybird +[ci-badge]: https://circleci.com/gh/segment-integrations/analytics.js-integration-replaybird.svg?style=svg diff --git a/integrations/replaybird/karma.conf-ci.js b/integrations/replaybird/karma.conf-ci.js new file mode 100644 index 000000000..2ba15b707 --- /dev/null +++ b/integrations/replaybird/karma.conf-ci.js @@ -0,0 +1 @@ +module.exports = require('../../karma.conf-ci.js'); diff --git a/integrations/replaybird/karma.conf.js b/integrations/replaybird/karma.conf.js new file mode 100644 index 000000000..8605180af --- /dev/null +++ b/integrations/replaybird/karma.conf.js @@ -0,0 +1 @@ +module.exports = require('../../karma.conf'); diff --git a/integrations/replaybird/lib/index.js b/integrations/replaybird/lib/index.js new file mode 100644 index 000000000..b55326985 --- /dev/null +++ b/integrations/replaybird/lib/index.js @@ -0,0 +1,118 @@ +'use strict'; + +/** + * Module dependencies. + */ + +var camel = require('camelcase'); +var foldl = require('@ndhoule/foldl'); +var integration = require('@segment/analytics.js-integration'); + +/** + * Expose `ReplayBird` integration. + * + * https://www.replaybird.com + */ + +var ReplayBird = (module.exports = integration('ReplayBird') + .option('siteKey', '') + .option('debug', false)); + +/** + * Initialize. + */ +ReplayBird.prototype.initialize = function() { + + /* eslint-disable no-param-reassign */ + !function(a,b,c,d,e,f,g,h){a.ReplayBirdObject=e,a[e]=a[e]||function(){ + (a[e].o=a[e].o||[]).push(arguments)},g=b.createElement(c),h=b.getElementsByTagName(c)[0], + g.async=1,g.src=d,a.__replaybirdNoConflict=!!f,h.parentNode.insertBefore(g,h); + }(window,document,"script","https://cdn.replaybird.com/replaybird.min.js","_rb"); + /* eslint-enable no-param-reassign */ + + _rb("apikey", this.options.siteKey); + _rb("debugMode", this.options.debug); + this.ready(); +}; + +/** + * Loaded? + * + * @return {Boolean} + */ +ReplayBird.prototype.loaded = function() { + return !!window.ReplayBird; +}; + +/** + * Identify + * + * @param {Identify} identify + */ +ReplayBird.prototype.identify = function(identify) { + if (!identify.userId()) { + return this.debug('user id is required'); + } + + var traits = identify.traits({ name: 'name' }); + + var newTraits = foldl( + function(results, value, key) { + var rs = results; + if (key !== 'id') { + rs[ + key === 'name' || key === 'email' ? key : camelCaseField(key) + ] = value; + } + return rs; + }, + {}, + traits + ); + + if (identify.userId()) { + window.ReplayBird.identify(String(identify.userId()), newTraits); + } +}; + +/** + * Track. Passes the events directly to ReplayBird + * + * @param {Track} track + */ +ReplayBird.prototype.track = function(track) { + window.ReplayBird.event(track.event(), track.properties()); +}; + +/** + * Camel cases `.`, `-`, `_`, and white space within fieldNames. Leaves type suffix alone. + * + * NOTE: Does not fix otherwise malformed fieldNames. + * ReplayBird will scrub characters from keys that do not conform to /^[a-zA-Z][a-zA-Z0-9_]*$/. + * + * @param {string} fieldName + */ +function camelCaseField(fieldName) { + // Do not camel case across type suffixes. + var parts = fieldName.split('_'); + if (parts.length > 1) { + var typeSuffix = parts.pop(); + switch (typeSuffix) { + case 'str': + case 'int': + case 'date': + case 'real': + case 'bool': + case 'strs': + case 'ints': + case 'dates': + case 'reals': + case 'bools': + return camel(parts.join('_')) + '_' + typeSuffix; + default: // passthrough + } + } + + // No type suffix found. Camel case the whole field name. + return camel(fieldName); +} diff --git a/integrations/replaybird/package.json b/integrations/replaybird/package.json new file mode 100644 index 000000000..877fedd5d --- /dev/null +++ b/integrations/replaybird/package.json @@ -0,0 +1,49 @@ +{ + "name": "@segment/analytics.js-integration-replaybird", + "description": "The ReplayBird analytics.js integration.", + "version": "1.0.0", + "keywords": [ + "analytics.js", + "analytics.js-integration", + "segment", + "replaybird" + ], + "main": "lib/index.js", + "scripts": { + "test": "karma start", + "test:ci": "karma start karma.conf-ci.js" + }, + "author": "Segment ", + "license": "SEE LICENSE IN LICENSE", + "homepage": "https://github.com/segmentio/analytics.js-integrations/blob/master/integrations/replaybird#readme", + "bugs": { + "url": "https://github.com/segmentio/analytics.js-integrations/issues" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/segmentio/analytics.js-integrations.git" + }, + "dependencies": { + "@ndhoule/foldl": "^2.0.1", + "@segment/analytics.js-integration": "^2.1.0", + "camelcase": "^3.0.0", + "is": "^3.1.0" + }, + "devDependencies": { + "@segment/analytics.js-core": "^3.8.2", + "@segment/analytics.js-integration-tester": "^3.1.1", + "@segment/clear-env": "^2.1.1", + "browserify": "^16.2.3", + "eslint": "^5.16.0", + "karma": "^4.1.0", + "karma-browserify": "^6.0.0", + "karma-chrome-launcher": "^2.2.0", + "karma-mocha": "^1.3.0", + "karma-mocha-reporter": "^2.2.5", + "karma-sauce-launcher": "^2.0.2", + "karma-spec-reporter": "^0.0.32", + "karma-summary-reporter": "^1.6.0", + "mocha": "^6.1.4", + "watchify": "^3.11.1" + } +} diff --git a/integrations/replaybird/test/index.test.js b/integrations/replaybird/test/index.test.js new file mode 100644 index 000000000..cf7a0d53c --- /dev/null +++ b/integrations/replaybird/test/index.test.js @@ -0,0 +1,116 @@ +'use strict'; + +var Analytics = require('@segment/analytics.js-core').constructor; +var integration = require('@segment/analytics.js-integration'); +var sandbox = require('@segment/clear-env'); +var tester = require('@segment/analytics.js-integration-tester'); +var ReplayBird = require('../lib/'); + +describe('ReplayBird', function() { + var analytics; + var replaybird; + var options = { + siteKey: '7vrdFkeywUwS94YQXUTdBf0pPQHXNlcWihmo1gsKLBO', + debug: false + }; + + beforeEach(function() { + analytics = new Analytics(); + replaybird = new ReplayBird(options); + analytics.use(ReplayBird); + analytics.use(tester); + analytics.add(replaybird); + }); + + afterEach(function() { + analytics.restore(); + analytics.reset(); + replaybird.reset(); + sandbox(); + }); + + it('should have the right settings', function() { + analytics.compare( + ReplayBird, + integration('ReplayBird') + .option('siteKey', '') + .option('debug', false) + ); + }); + + describe('before loading', function() { + beforeEach(function() { + analytics.stub(replaybird, 'load'); + }); + + describe('#initialize', function() { + it('should call #load', function() { + analytics.initialize(); + analytics.called(replaybird.load); + }); + }); + }); + + describe('after loading', function() { + beforeEach(function(done) { + analytics.once('ready', done); + analytics.initialize(); + analytics.page(); + }); + + describe('#identify', function() { + beforeEach(function() { + analytics.stub(window.ReplayBird, 'identify'); + }); + + it('should send an id', function() { + analytics.identify('id'); + analytics.called(window.ReplayBird.identify, 'id', {}); + }); + + it('should camel case custom props', function() { + analytics.identify('id', { + name: 'User123', + email: 'example@acme.com', + 'First name': 'Eric', + lastName: 'Brown' + }); + analytics.called( + window.ReplayBird.identify, + 'id', + { + name: 'User123', + email: 'example@acme.com', + firstName: 'Eric', + lastName: 'Brown' + } + ); + }); + + it('should map name and email', function() { + analytics.identify('id', { name: 'Test', email: 'test@test.com' }); + analytics.called( + window.ReplayBird.identify, + 'id', + { name: 'Test', email: 'test@test.com' } + ); + }); + }); + + describe('#track', function() { + beforeEach(function() { + analytics.stub(window.ReplayBird, 'event'); + }); + + it('should send track event name and properties', function() { + analytics.track('my_event', { some_field: 'field_value' }); + analytics.called( + window.ReplayBird.event, + 'my_event', + { some_field: 'field_value' } + ); + }); + }); + + }); +}); From ee2b48327c11c1ba530448cbd646a90a64ba1d09 Mon Sep 17 00:00:00 2001 From: Fizer Khan Date: Wed, 26 Feb 2020 15:07:43 +0530 Subject: [PATCH 2/3] Fixed ReplayBird object issue due to async loading. --- integrations/replaybird/HISTORY.md | 2 +- integrations/replaybird/lib/index.js | 17 ++++++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/integrations/replaybird/HISTORY.md b/integrations/replaybird/HISTORY.md index 6db9f05cf..5c85c20c9 100644 --- a/integrations/replaybird/HISTORY.md +++ b/integrations/replaybird/HISTORY.md @@ -1,4 +1,4 @@ -1.0.0 / 2020-02-21 +1.0.0 / 2020-02-26 ================== * Initial commit diff --git a/integrations/replaybird/lib/index.js b/integrations/replaybird/lib/index.js index b55326985..ccfe87ebd 100644 --- a/integrations/replaybird/lib/index.js +++ b/integrations/replaybird/lib/index.js @@ -51,17 +51,17 @@ ReplayBird.prototype.loaded = function() { */ ReplayBird.prototype.identify = function(identify) { if (!identify.userId()) { - return this.debug('user id is required'); + return this.debug('User id is required!'); } - var traits = identify.traits({ name: 'name' }); + var traits = identify.traits({ name: 'displayName' }); var newTraits = foldl( function(results, value, key) { var rs = results; if (key !== 'id') { rs[ - key === 'name' || key === 'email' ? key : camelCaseField(key) + key === 'displayName' || key === 'email' ? key : camelCaseField(key) ] = value; } return rs; @@ -70,9 +70,8 @@ ReplayBird.prototype.identify = function(identify) { traits ); - if (identify.userId()) { - window.ReplayBird.identify(String(identify.userId()), newTraits); - } + newTraits.id = String(identify.userId()); + window._rb('identify', newTraits); }; /** @@ -81,7 +80,11 @@ ReplayBird.prototype.identify = function(identify) { * @param {Track} track */ ReplayBird.prototype.track = function(track) { - window.ReplayBird.event(track.event(), track.properties()); + if (window.ReplayBird) { + window.ReplayBird.event(track.event(), track.properties()); + } else { + window._rb('event', { name: track.event(), properties: track.properties() }); + } }; /** From cb58ab77b2ed43d0ad04f17b63d0a4c091a915ad Mon Sep 17 00:00:00 2001 From: Fizer Khan Date: Thu, 25 Aug 2022 13:31:19 +0530 Subject: [PATCH 3/3] Updated replaybird new script with session recording support. --- integrations/replaybird/lib/index.js | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/integrations/replaybird/lib/index.js b/integrations/replaybird/lib/index.js index ccfe87ebd..7483bc137 100644 --- a/integrations/replaybird/lib/index.js +++ b/integrations/replaybird/lib/index.js @@ -24,14 +24,13 @@ var ReplayBird = (module.exports = integration('ReplayBird') ReplayBird.prototype.initialize = function() { /* eslint-disable no-param-reassign */ - !function(a,b,c,d,e,f,g,h){a.ReplayBirdObject=e,a[e]=a[e]||function(){ - (a[e].o=a[e].o||[]).push(arguments)},g=b.createElement(c),h=b.getElementsByTagName(c)[0], - g.async=1,g.src=d,a.__replaybirdNoConflict=!!f,h.parentNode.insertBefore(g,h); - }(window,document,"script","https://cdn.replaybird.com/replaybird.min.js","_rb"); + !function(t,e){var o,n,p,r;e.__SV||(window.replaybird=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.async=!0,p.src="https://cdn.replaybird.com/agent/latest/replaybird.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r);var u=e;for(void 0!==a?u=e[a]=[]:a="replaybird",u.people=u.people||[],u.toString=function(t){var e="replaybird";return"replaybird"!==a&&(e+="."+a),t||(e+=" (stub)"),e},u.people.toString=function(){return u.toString(1)+".people (stub)"},o="identify capture alias people.set people.set_once set_config register register_once unregister opt_out_capturing has_opted_out_capturing opt_in_capturing reset".split(" "),n=0;n