Skip to content

Commit

Permalink
Merge pull request #8 from driveback/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
ConstantineYurevich committed Feb 1, 2016
2 parents 43712cb + 01a98e1 commit df7b191
Show file tree
Hide file tree
Showing 24 changed files with 4,351 additions and 189 deletions.
1,760 changes: 1,657 additions & 103 deletions dist/dd-manager.js

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions dist/dd-manager.min.js

Large diffs are not rendered by default.

9 changes: 6 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "digital-data-manager",
"description": "The hassle-free way to integrate Digital Data Layer on your website.",
"author": "Driveback LLC <[email protected]>",
"version": "1.0.0-beta6",
"version": "1.0.0",
"license": "MIT",
"main": "dist/dd-manager.js",
"directories": {
Expand Down Expand Up @@ -51,6 +51,7 @@
"eslint-plugin-react": "^3.10.0",
"exorcist": "^0.4.0",
"faucet": "0.0.1",
"js-cookie": "^2.1.0",
"karma": "^0.13.15",
"karma-babel-preprocessor": "^6.0.1",
"karma-browserify": "^4.4.0",
Expand All @@ -60,7 +61,7 @@
"karma-safari-launcher": "^0.1.1",
"karma-sauce-launcher": "^0.3.0",
"karma-tap": "^1.0.3",
"mocha": "2.3.4",
"mocha": "^2.4.4",
"polyify": "0.0.4",
"sinon": "^1.17.2",
"tape": "^4.2.2",
Expand All @@ -70,6 +71,8 @@
"dependencies": {
"async": "^1.5.0",
"component-clone": "^0.2.2",
"debug": "^2.2.0"
"debug": "^2.2.0",
"store": "^1.3.20",
"uuid": "^2.0.1"
}
}
21 changes: 0 additions & 21 deletions src/AutoEvents.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ class AutoEvents
this.fireViewedPage();
this.fireViewedProductCategory();
this.fireViewedProductDetail();
this.fireViewedCheckoutStep();
this.fireCompletedTransaction();

if (this.ddListener) {
Expand All @@ -28,8 +27,6 @@ class AutoEvents
this.ddListener.push(['on', 'change:transaction.orderId', (newOrderId, oldOrderId) => {
this.onTransactionChange(newOrderId, oldOrderId);
}]);

// TODO: checkout step change
}
}
}
Expand Down Expand Up @@ -59,7 +56,6 @@ class AutoEvents
fireViewedPage(page) {
page = page || this.digitalData.page;
this.digitalData.events.push({
updateDigitalData: false,
enrichEventData: false,
name: 'Viewed Page',
category: 'Content',
Expand All @@ -73,7 +69,6 @@ class AutoEvents
return;
}
this.digitalData.events.push({
updateDigitalData: false,
enrichEventData: false,
name: 'Viewed Product Category',
category: 'Ecommerce',
Expand All @@ -87,35 +82,19 @@ class AutoEvents
return;
}
this.digitalData.events.push({
updateDigitalData: false,
enrichEventData: false,
name: 'Viewed Product Detail',
category: 'Ecommerce',
product: product,
});
}

fireViewedCheckoutStep(page) {
page = page || this.digitalData.page || {};
if (page.type !== 'cart' && page.type !== 'checkout') {
return;
}
this.digitalData.events.push({
updateDigitalData: false,
enrichEventData: false,
name: 'Viewed Checkout Step',
category: 'Ecommerce',
page: page,
});
}

fireCompletedTransaction(transaction) {
transaction = transaction || this.digitalData.transaction;
if (!transaction || transaction.isReturning === true) {
return;
}
this.digitalData.events.push({
updateDigitalData: false,
enrichEventData: false,
name: 'Completed Transaction',
category: 'Ecommerce',
Expand Down
33 changes: 9 additions & 24 deletions src/DDHelper.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,11 @@
import getProperty from './functions/getProperty.js';
import clone from 'component-clone';

function _keyToArray(key) {
key = key.trim();
if (key === '') {
return [];
}
key = key.replace(/\[(\w+)\]/g, '.$1');
key = key.replace(/^\./, '');
return key.split('.');
}

class DDHelper {

static get(key, digitalData) {
const keyParts = _keyToArray(key);
let nestedVar = clone(digitalData);
while (keyParts.length > 0) {
const childKey = keyParts.shift();
if (nestedVar.hasOwnProperty(childKey)) {
nestedVar = nestedVar[childKey];
} else {
return undefined;
}
}
return nestedVar;
const value = getProperty(digitalData, key);
return clone(value);
}

static getProduct(id, digitalData) {
Expand All @@ -39,9 +21,12 @@ class DDHelper {
}
for (const listing of listings) {
if (listing.items && listing.items.length) {
for (const product of listing.items) {
if (product.id && String(product.id) === String(id)) {
return clone(product);
for (let i = 0, length = listing.items.length; i < length; i++) {
if (listing.items[i].id && String(listing.items[i].id) === String(id)) {
const product = clone(listing.items[i]);
product.position = product.position || (i + 1);
if (listing.listName) product.listName = product.listName || listing.listName;
return product;
}
}
}
Expand Down
75 changes: 75 additions & 0 deletions src/DigitalDataEnricher.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import htmlGlobals from './functions/htmlGlobals.js';
import uuid from 'uuid';

class DigitalDataEnricher
{
constructor(digitalData, storage, options) {
this.digitalData = digitalData;
this.storage = storage;
this.options = Object.assign({
sessionLength: 3600,
}, options);
}

setDigitalData(digitalData) {
this.digitalData = digitalData;
}

setStorage(storage) {
this.storage = storage;
}

getStorage() {
return this.storage;
}

enrichDigitalData() {
this.enrichPageData();
this.enrichUserData();
this.enrichContextData();
}

enrichPageData() {
const page = this.digitalData.page;

page.path = page.path || this.getHtmlGlobals().getLocation().pathname;
page.referrer = page.referrer || this.getHtmlGlobals().getDocument().referrer;
page.queryString = page.queryString || this.getHtmlGlobals().getLocation().search;
page.title = page.title || this.getHtmlGlobals().getDocument().title;
page.url = page.url || this.getHtmlGlobals().getLocation().href;
page.hash = page.hash || this.getHtmlGlobals().getLocation().hash;
}

enrichUserData() {
const user = this.digitalData.user;
user.anonymousId = this.getUserAnonymousId();
}

enrichContextData() {
const context = this.digitalData.context;
context.userAgent = this.getHtmlGlobals().getNavigator().userAgent;
}

/**
* Can be overriden for test purposes
* @returns {{getDocument, getLocation, getNavigator}}
*/
getHtmlGlobals() {
return htmlGlobals;
}

getUserAnonymousId() {
let anonymousId = this.storage.get('user.anonymousId');
if (!anonymousId) {
anonymousId = uuid();
this.storage.set('user.anonymousId', anonymousId);
}
return anonymousId;
}

getOption(name) {
return this.options[name];
}
}

export default DigitalDataEnricher;
90 changes: 90 additions & 0 deletions src/Storage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import store from 'store';
import cookie from 'js-cookie';
import debug from 'debug';
import topDomain from './functions/topDomain.js';

class Storage
{
constructor(options) {
this.options = Object.assign({
cookieDomain: topDomain(location.href),
cookieMaxAge: 31536000000, // default to a year
prefix: 'ddl:',
}, options);

// http://curl.haxx.se/rfc/cookie_spec.html
// https://publicsuffix.org/list/effective_tld_names.dat
//
// try setting a dummy cookie with the options
// if the cookie isn't set, it probably means
// that the domain is on the public suffix list
// like myapp.herokuapp.com or localhost / ip.
if (this.getOption('cookieDomain')) {
cookie.set('__tld__', true, {
domain: this.getOption('cookieDomain'),
});
if (!this.get('__tld__')) {
debug('fallback to domain=null');
this.setOption('cookieDomain', null);
}
cookie.remove('__tld__');
}
}

set(key, val, exp) {
key = this.prefix + key;
if (store.enabled) {
store.set(key, {
val: val,
exp: exp,
time: new Date().getTime(),
});
} else {
exp = exp || this.getOption('cookieMaxAge');
const expDays = exp / 86400;
cookie.set(key, val, {
expires: expDays,
domain: this.getOption('cookieDomain'),
});
}
}

get(key) {
key = this.prefix + key;
if (store.enabled) {
const info = store.get(key);
if (!info) {
return null;
}
if (new Date().getTime() - info.time > info.exp) {
return null;
}
return info.val;
}
return cookie.get(key);
}

remove(key) {
key = this.prefix + key;
if (store.enabled) {
return store.remove(key);
}
cookie.remove(key);
}

clear() {
if (store.enabled) {
return store.clear();
}
}

isEnabled() {
return store.enabled;
}

getOption(name) {
return this.options[name];
}
}

export default Storage;
2 changes: 2 additions & 0 deletions src/availableIntegrations.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import GoogleAnalytics from './integrations/GoogleAnalytics.js';
import GoogleTagManager from './integrations/GoogleTagManager.js';
import Driveback from './integrations/Driveback.js';
import RetailRocket from './integrations/RetailRocket.js';
import FacebookPixel from './integrations/FacebookPixel.js';

const integrations = {
[GoogleAnalytics.getName()]: GoogleAnalytics,
[GoogleTagManager.getName()]: GoogleTagManager,
[FacebookPixel.getName()]: FacebookPixel,
[Driveback.getName()]: Driveback,
Expand Down
24 changes: 24 additions & 0 deletions src/ddManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import Integration from './Integration.js';
import EventManager from './EventManager.js';
import AutoEvents from './AutoEvents.js';
import DDHelper from './DDHelper.js';
import DigitalDataEnricher from './DigitalDataEnricher.js';
import Storage from './Storage.js';

/**
* @type {string}
Expand Down Expand Up @@ -39,6 +41,12 @@ let _digitalData = {};
*/
let _ddListener = [];

/**
* @type {Storage}
* @private
*/
let _storage;

/**
* @type {Object}
* @private
Expand Down Expand Up @@ -79,6 +87,7 @@ function _prepareGlobals() {

_digitalData.page = _digitalData.page || {};
_digitalData.user = _digitalData.user || {};
_digitalData.context = _digitalData.context || {};
if (!_digitalData.page.type || _digitalData.page.type !== 'confirmation') {
_digitalData.cart = _digitalData.cart || {};
}
Expand Down Expand Up @@ -126,6 +135,7 @@ const ddManager = {
*
* {
* autoEvents: true,
* sessionLength: 3600,
* integrations: {
* 'Google Tag Manager': {
* containerId: 'XXX'
Expand All @@ -138,7 +148,9 @@ const ddManager = {
*/
initialize: (settings) => {
settings = Object.assign({
domain: null,
autoEvents: true,
sessionLength: 3600,
}, settings);

if (_isInitialized) {
Expand All @@ -147,6 +159,18 @@ const ddManager = {

_prepareGlobals();

// initialize storage
_storage = new Storage({
cookieDomain: settings.domain,
});

// initialize digital data enricher
const digitalDataEnricher = new DigitalDataEnricher(_digitalData, _storage, {
sessionLength: settings.sessionLength,
});
digitalDataEnricher.enrichDigitalData();

// initialize event manager
_eventManager = new EventManager(_digitalData, _ddListener);
if (settings.autoEvents) {
_eventManager.setAutoEvents(new AutoEvents());
Expand Down
Loading

0 comments on commit df7b191

Please sign in to comment.