Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,23 @@ Add a `<noscript>` element to the page to override the opacity
</noscript>
```

### 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
Expand Down
15 changes: 15 additions & 0 deletions dist/optimize.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;

Expand All @@ -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
Expand All @@ -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();
};

Expand All @@ -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.');
}
};

Expand Down Expand Up @@ -109,6 +123,7 @@ var Optimize = function Optimize(experimentName, controlProps) {
if (controlProps) {
this.controlProps = controlProps;
}
debug('Created ' + experimentName + '.');
};

exports.default = Optimize;
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
},
"dependencies": {
"create-react-context": "^0.2.2",
"debug": "^4.1.1",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

preference is not to add extra dependancies when they are not absolutely necessary - can you add a debug helper script (which does console logs) instead of a 3rd party lib?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeh I agree, can't say I've seen this much in OSS. Maybe if it accepted debug as an optional prop that would be better. Any examples of other libraries solving this problem @danielbush?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably the size is less than 7k when bundled and minified down a bit more but I get the point.

Yeh, it's not as common in the browser. I've used it in a complex spa where I can selectively enable debugging to see what the system is doing, eg localStorage.debug='containers*,system1,foo,bar' etc. and it gives nice coloured output and might complement a similar use of debug in the consumer of this component to allow us to trace failed variant activation.

However, given the situation, maybe we just JSON.parse localStorage.debugReactExperimentify and if truthy/falsey behave accordingly; if it fails, reset it to falsey and warn the user?
Feels more straightforward to me than passing in debug.

@albertstill @jooj123

"hoist-non-react-statics": "^3.0.1",
"invariant": "^2.2.4",
"lodash": "^4.17.10",
Expand Down
12 changes: 12 additions & 0 deletions src/optimize.js
Original file line number Diff line number Diff line change
@@ -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<Function> = [];
eventData: any;
Expand All @@ -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
Expand All @@ -29,20 +35,26 @@ 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();
}

controlProps = () => undefined

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.`);
}
}

Expand Down
12 changes: 12 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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"
Expand Down