Skip to content
This repository has been archived by the owner on May 8, 2023. It is now read-only.

Commit

Permalink
fix: pass variation id to qualify event, move pageview event
Browse files Browse the repository at this point in the history
  • Loading branch information
foxted committed Dec 30, 2019
1 parent 5b2cac4 commit 6e82c31
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 41 deletions.
1 change: 1 addition & 0 deletions src/__tests__/non-browser.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ it('Environment can degrade gracefully if window is undefined', () => {
expect(variate.env).toEqual(expect.objectContaining({
view: expect.objectContaining({
path: expect.any(String),
url: expect.any(String),
query: expect.any(Object),
}),
viewport: expect.objectContaining({
Expand Down
2 changes: 1 addition & 1 deletion src/components/experiment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ export default class Experiment {
public id!: string;
public siteId!: string;
public name?: string;
public manualPageview?: boolean;
public manualQualification?: boolean;
public variations: Variation[];
}
1 change: 1 addition & 0 deletions src/config/event-types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export enum EventTypes {
PAGEVIEW = 'pageview',
QUALIFY = 'qualify',
CLICK = 'click',
}
88 changes: 48 additions & 40 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,15 @@ class Variate {
// View information
const { path, query } = get(value, 'view', {
default: {
path: env.href(),
path: env.inBrowser ? env.href() : '',
query: Variate.extractQueryParams(env.search())
}
});
const view = { path, query };
const view = {
url: env.inBrowser ? env.href() : '',
path,
query
};

// Viewport information
const viewport = {
Expand Down Expand Up @@ -132,7 +136,8 @@ class Variate {
* @returns {Array<Variation>}
*/
get variations(): Array<Variation> {
return this.experiments.map((experiment) => experiment.variations).reduce((acc, val) => acc.concat(val), []);
return this.experiments.map((experiment) => experiment.variations)
.reduce((acc, val) => acc.concat(val), []);
}

/**
Expand All @@ -149,10 +154,16 @@ class Variate {
* @returns {array}
*/
extractVariationComponents(variation: Variation) {
const bucket = this.getExperimentBucket({ id: variation.experimentId });
const experiment = this.experiments.find(item => item.id === variation.experimentId);

if(!experiment) {
console.error(errors.QUALIFICATION_EXPERIMENT_NOT_FOUND);
return [];
}

const bucket = this.getExperimentBucket(experiment);

for (let component of Object.values(variation.components)) {
// components.shift();
component.bucket = bucket;
}

Expand Down Expand Up @@ -214,6 +225,12 @@ class Variate {
this.isReady = true;
this._options.debug && console.timeEnd('[BENCHMARK] Variate Initialization');

console.log('NAH', this._options.tracking.enabled, this._options.pageview);

if (this._options.tracking.enabled && this._options.pageview) {
this.track('Pageview', EventTypes.PAGEVIEW);
}

if (typeof callback == 'function') {
callback();
}
Expand All @@ -235,20 +252,6 @@ class Variate {
// 3. Reduce to 1 variation per experiment to prepare for display
experiments = experiments.map((experiment) => this.filterVariationsWithBucket(experiment));

// 4. Send pageview event if enabled
experiments.forEach((experiment) => {
const [variation] = Object.values(get(experiment, 'variations', {
default: {}
}));

if (this._options.tracking.enabled && (this._options.pageview || !experiment.manualPageview)) {
this.track('Pageview', EventTypes.PAGEVIEW, {
experimentId: experiment.id,
variationId: variation.id,
});
}
});

this.experiments = experiments;
this.isQualified = true;
}
Expand Down Expand Up @@ -283,7 +286,7 @@ class Variate {
* @returns {boolean}
*/
filterVariationsWithBucket(experiment: Experiment) {
const bucket = this.getExperimentBucket(experiment);
const bucket = this.getExperimentBucket(experiment, true);
let variations: Variation[] = Object.values(get(experiment, 'variations'));

variations = variations.filter((variation: Variation) => {
Expand Down Expand Up @@ -355,10 +358,11 @@ class Variate {
*/
qualifyView(experiment: Object) {
const path = get(this.env, 'view.path');
const url = get(this.env, 'view.url');
const excludes = get(experiment, 'targeting.views.exclude');

for (let i = 0; i < excludes.length; i++) {
if (path.match(excludes[i])) {
if (path.match(excludes[i]) || url.match(excludes[i])) {
return false;
}
}
Expand All @@ -371,7 +375,7 @@ class Variate {
}

for (let i = 0; i < includes.length; i++) {
if (path.match(includes[i])) {
if (path.match(includes[i]) || url.match(includes[i])) {
return true;
}
}
Expand Down Expand Up @@ -411,36 +415,40 @@ class Variate {
/**
* Get a traffic bucket for a given experiment
* @param experiment
* @param qualify
* @returns {number}
*/
getExperimentBucket(experiment: Pick<Experiment, 'id'>) {
if (env.inBrowser) {
getExperimentBucket(experiment: Experiment, qualify = false) {
try {
let bucket = localStorage.getItem(LOCAL_STORAGE_TRAFFIC_BUCKETS_KEY)
? JSON.parse(localStorage.getItem(LOCAL_STORAGE_TRAFFIC_BUCKETS_KEY) || '')
: {};

if (!bucket[experiment.id]) {
bucket[experiment.id] = Variate.generateTrafficBucket();
env.inBrowser && localStorage.setItem(LOCAL_STORAGE_TRAFFIC_BUCKETS_KEY, JSON.stringify(bucket));

const variationId = get(experiment, 'variations.0.id', {
default: null,
});

this.track({
name: 'Qualify',
type: 'qualify',
value: {
experimentId: experiment.id,
variationId: variationId
}
})
localStorage.setItem(LOCAL_STORAGE_TRAFFIC_BUCKETS_KEY, JSON.stringify(bucket));

if (this._options.tracking.enabled && qualify && !experiment.manualQualification) {
const [variation] = Object.values(get(experiment, 'variations', {
default: {}
}));

this.track({
name: 'Qualify',
type: EventTypes.QUALIFY,
value: {
experimentId: experiment.id,
variationId: variation.id
}
});
}
}

return bucket[experiment.id];
} catch(error) {
console.error(error);
return 0;
}

return 0;
}

/**
Expand Down
3 changes: 3 additions & 0 deletions src/lang/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,8 @@ export const IS_READY_TYPE_ERROR = `The isReady property requires a boolean.`;
export const IS_QUALIFIED_TYPE_ERROR = `The isQualified property requires a boolean.`;
export const REQUIRED_PARAMETERS = `Parameters are required for the method %s`;

// Qualification
export const QUALIFICATION_EXPERIMENT_NOT_FOUND = 'Experiment not found. Check your configuration for errors.';

// Reporting
export const TRACKING_INVALID_REPORTER = 'Reporter must be a function';

0 comments on commit 6e82c31

Please sign in to comment.