@funnelsgrove/runtime 0.1.39 → 0.1.40

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,37 +7,31 @@ type FunnelExperimentBase = {
7
7
  status?: FunnelExperimentStatus;
8
8
  launchDate: string;
9
9
  };
10
+ type FunnelRouteExperimentVariantDefinition = {
11
+ variantKey?: string;
12
+ stepId: string;
13
+ label?: string;
14
+ trafficPercent: number;
15
+ };
16
+ type FunnelPricingExperimentVariantDefinition = {
17
+ variantKey?: string;
18
+ offerSetKey: string;
19
+ label?: string;
20
+ trafficPercent: number;
21
+ };
10
22
  export type FunnelRouteExperimentDefinition = FunnelExperimentBase & {
11
23
  type: FunnelRouteExperimentType;
12
24
  stepId?: string;
13
- control: {
14
- variantKey?: string;
15
- stepId: string;
16
- label?: string;
17
- trafficPercent: number;
18
- };
19
- variant: {
20
- variantKey?: string;
21
- stepId: string;
22
- label?: string;
23
- trafficPercent: number;
24
- };
25
+ control: FunnelRouteExperimentVariantDefinition;
26
+ variant: FunnelRouteExperimentVariantDefinition;
27
+ variants?: readonly FunnelRouteExperimentVariantDefinition[];
25
28
  };
26
29
  export type FunnelPricingExperimentDefinition = FunnelExperimentBase & {
27
30
  type: 'pricing';
28
31
  paywallStepId: string;
29
- control: {
30
- variantKey?: string;
31
- offerSetKey: string;
32
- label?: string;
33
- trafficPercent: number;
34
- };
35
- variant: {
36
- variantKey?: string;
37
- offerSetKey: string;
38
- label?: string;
39
- trafficPercent: number;
40
- };
32
+ control: FunnelPricingExperimentVariantDefinition;
33
+ variant: FunnelPricingExperimentVariantDefinition;
34
+ variants?: readonly FunnelPricingExperimentVariantDefinition[];
41
35
  };
42
36
  export type FunnelExperimentDefinition = FunnelRouteExperimentDefinition | FunnelPricingExperimentDefinition;
43
37
  export type PaywallExperimentDefinition = FunnelRouteExperimentDefinition & {
@@ -1,6 +1,33 @@
1
+ const getExperimentVariants = (experiment) => {
2
+ var _a;
3
+ return (((_a = experiment.variants) === null || _a === void 0 ? void 0 : _a.length)
4
+ ? experiment.variants
5
+ : [experiment.control, experiment.variant]);
6
+ };
7
+ const getRouteExperimentVariants = (experiment) => {
8
+ var _a;
9
+ return (((_a = experiment.variants) === null || _a === void 0 ? void 0 : _a.length)
10
+ ? experiment.variants
11
+ : [experiment.control, experiment.variant]);
12
+ };
13
+ const getPricingExperimentVariants = (experiment) => {
14
+ var _a;
15
+ return (((_a = experiment.variants) === null || _a === void 0 ? void 0 : _a.length)
16
+ ? experiment.variants
17
+ : [experiment.control, experiment.variant]);
18
+ };
19
+ const getDefaultVariantKey = (experiment, index) => {
20
+ var _a;
21
+ if (index === 0) {
22
+ return 'control';
23
+ }
24
+ return ((_a = experiment.variants) === null || _a === void 0 ? void 0 : _a.length)
25
+ ? `variant_${String.fromCharCode(96 + index)}`
26
+ : 'variant_b';
27
+ };
1
28
  export const defineFunnelExperiments = (experiments) => {
2
29
  for (const experiment of experiments) {
3
- const trafficTotal = experiment.control.trafficPercent + experiment.variant.trafficPercent;
30
+ const trafficTotal = getExperimentVariants(experiment).reduce((sum, variant) => sum + variant.trafficPercent, 0);
4
31
  if (trafficTotal !== 100) {
5
32
  throw new Error(`Experiment "${experiment.id}" traffic must sum to 100`);
6
33
  }
@@ -9,17 +36,17 @@ export const defineFunnelExperiments = (experiments) => {
9
36
  };
10
37
  export const toManifestExperiments = (experiments) => experiments
11
38
  .filter((experiment) => { var _a; return ((_a = experiment.status) !== null && _a !== void 0 ? _a : 'running') === 'running'; })
12
- .map((experiment) => ({
13
- experimentId: experiment.id,
14
- stepId: experiment.type === 'pricing'
15
- ? experiment.paywallStepId
16
- : experiment.stepId || experiment.control.stepId,
17
- variants: [
18
- Object.assign(Object.assign({ variantKey: experiment.control.variantKey || 'control' }, (experiment.control.label ? { label: experiment.control.label } : {})), { trafficPercent: experiment.control.trafficPercent, routeToStepId: experiment.type === 'pricing'
19
- ? experiment.paywallStepId
20
- : experiment.control.stepId }),
21
- Object.assign(Object.assign({ variantKey: experiment.variant.variantKey || 'variant_b' }, (experiment.variant.label ? { label: experiment.variant.label } : {})), { trafficPercent: experiment.variant.trafficPercent, routeToStepId: experiment.type === 'pricing'
22
- ? experiment.paywallStepId
23
- : experiment.variant.stepId }),
24
- ],
25
- }));
39
+ .map((experiment) => {
40
+ if (experiment.type === 'pricing') {
41
+ return {
42
+ experimentId: experiment.id,
43
+ stepId: experiment.paywallStepId,
44
+ variants: getPricingExperimentVariants(experiment).map((variant, index) => (Object.assign(Object.assign({ variantKey: variant.variantKey || getDefaultVariantKey(experiment, index) }, (variant.label ? { label: variant.label } : {})), { trafficPercent: variant.trafficPercent, routeToStepId: experiment.paywallStepId }))),
45
+ };
46
+ }
47
+ return {
48
+ experimentId: experiment.id,
49
+ stepId: experiment.stepId || experiment.control.stepId,
50
+ variants: getRouteExperimentVariants(experiment).map((variant, index) => (Object.assign(Object.assign({ variantKey: variant.variantKey || getDefaultVariantKey(experiment, index) }, (variant.label ? { label: variant.label } : {})), { trafficPercent: variant.trafficPercent, routeToStepId: variant.stepId }))),
51
+ };
52
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@funnelsgrove/runtime",
3
- "version": "0.1.39",
3
+ "version": "0.1.40",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "main": "./dist/index.js",