diff --git a/CHANGELOG.md b/CHANGELOG.md
index 952bf6a..6805492 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased][]
+### Added
+- `debug` module. In browser console: `localStorage.DEBUG='react-experimentify'`.
+ This should help to trace the execution of experiments in a complex page to aid in
+ debugging experiment activation with Google Optimize.
## [1.0.7][] - 2018-11-21
### Fixed
diff --git a/README.md b/README.md
index 453baca..e886102 100644
--- a/README.md
+++ b/README.md
@@ -147,6 +147,23 @@ Add a `
```
+### Debugging
+
+You can enable debugging for experiments using the `debug` npm module.
+In your browser console:
+
+```javascript
+localStorage.debug='react-experimentify'
+```
+
+Then reload the page.
+
+You should see events for
+
+- experiment creation
+- experiment activation and listening (waiting for a variant to fire)
+- `.render` event but only if a variant fires, there is no event for staying with the control
+
### Optimizely
```javascript
diff --git a/dist/optimize.js b/dist/optimize.js
index 183d7bf..e0e3ba8 100644
--- a/dist/optimize.js
+++ b/dist/optimize.js
@@ -8,6 +8,10 @@ var _once = require('lodash/once');
var _once2 = _interopRequireDefault(_once);
+var _debug = require('debug');
+
+var _debug2 = _interopRequireDefault(_debug);
+
var _pushToDataLayer = require('./helpers/push-to-data-layer');
var _pushToDataLayer2 = _interopRequireDefault(_pushToDataLayer);
@@ -18,6 +22,8 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+var debug = (0, _debug2.default)('react-experimentify');
+
var Optimize = function Optimize(experimentName, controlProps) {
var _this = this;
@@ -26,6 +32,8 @@ var Optimize = function Optimize(experimentName, controlProps) {
this.listeners = [];
this.activate = function (onActivation) {
+ debug('Activating ' + _this.experimentName + '.');
+ debug(_this.experimentName + ' isActive=' + _this.isActive() + ' (should be false unless a variant fires in near future)');
_this.addEventListener();
// Trigger an experiment execute is a async operation hence we need
@@ -40,12 +48,15 @@ var Optimize = function Optimize(experimentName, controlProps) {
this.addEventListener = (0, _once2.default)(function () {
if (window) {
+ debug('Listening for "' + _this.experimentName + '.render".');
window.addEventListener(_this.experimentName + '.render', _this.triggerRenderingOfExperiment);
}
});
this.triggerRenderingOfExperiment = function (event) {
+ debug('Received .render event for variant from Optimize for ' + _this.experimentName + '.', event);
_this.eventData = event.detail;
+ debug(_this.experimentName + ' isActive=' + _this.isActive() + ' (must be true for Treatment to render)');
_this.dispatch();
};
@@ -55,9 +66,12 @@ var Optimize = function Optimize(experimentName, controlProps) {
this.dispatch = function () {
if (_this.isActive()) {
+ debug('Dispatching subscribers for ' + _this.experimentName + '.');
_this.listeners.forEach(function (listener) {
return listener({});
});
+ } else {
+ debug('NOT Dispatching subscribers for ' + _this.experimentName + ' because experiment is not active.');
}
};
@@ -109,6 +123,7 @@ var Optimize = function Optimize(experimentName, controlProps) {
if (controlProps) {
this.controlProps = controlProps;
}
+ debug('Created ' + experimentName + '.');
};
exports.default = Optimize;
\ No newline at end of file
diff --git a/package.json b/package.json
index b30c6ce..0b103c1 100644
--- a/package.json
+++ b/package.json
@@ -87,6 +87,7 @@
},
"dependencies": {
"create-react-context": "^0.2.2",
+ "debug": "^4.1.1",
"hoist-non-react-statics": "^3.0.1",
"invariant": "^2.2.4",
"lodash": "^4.17.10",
diff --git a/src/optimize.js b/src/optimize.js
index 14d8504..39a2213 100644
--- a/src/optimize.js
+++ b/src/optimize.js
@@ -1,7 +1,10 @@
import once from 'lodash/once';
+import Debug from 'debug';
import pushToDataLayer from './helpers/push-to-data-layer';
import { Experiment } from './models/experiment';
+const debug = Debug('react-experimentify');
+
class Optimize implements Experiment {
listeners: Array = [];
eventData: any;
@@ -12,9 +15,12 @@ class Optimize implements Experiment {
if (controlProps) {
this.controlProps = controlProps;
}
+ debug(`Created ${experimentName}.`);
}
activate = (onActivation) => {
+ debug(`Activating ${this.experimentName}.`);
+ debug(`${this.experimentName} isActive=${this.isActive()} (should be false unless a variant fires in near future)`);
this.addEventListener();
// Trigger an experiment execute is a async operation hence we need
@@ -29,12 +35,15 @@ class Optimize implements Experiment {
addEventListener = once(() => {
if (window) {
+ debug(`Listening for "${this.experimentName}.render".`);
window.addEventListener(`${this.experimentName}.render`, this.triggerRenderingOfExperiment);
}
});
triggerRenderingOfExperiment = (event) => {
+ debug(`Received .render event for variant from Optimize for ${this.experimentName}.`, event);
this.eventData = event.detail;
+ debug(`${this.experimentName} isActive=${this.isActive()} (must be true for Treatment to render)`);
this.dispatch();
}
@@ -42,7 +51,10 @@ class Optimize implements Experiment {
dispatch = () => {
if (this.isActive()) {
+ debug(`Dispatching subscribers for ${this.experimentName}.`);
this.listeners.forEach(listener => listener({}));
+ } else {
+ debug(`NOT Dispatching subscribers for ${this.experimentName} because experiment is not active.`);
}
}
diff --git a/yarn.lock b/yarn.lock
index 063abae..9dd9a7f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2105,6 +2105,13 @@ debug@3.1.0, debug@^3.1.0:
dependencies:
ms "2.0.0"
+debug@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
+ integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==
+ dependencies:
+ ms "^2.1.1"
+
decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2:
version "1.2.0"
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
@@ -4738,6 +4745,11 @@ ms@2.0.0:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
+ms@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
+ integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
+
mute-stream@0.0.7:
version "0.0.7"
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"