@cascayd/experiment 0.3.9 → 0.3.11

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.
package/dist/client.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { InitOptions, ExperimentConfigResponse, EventType, RecordOptions, VariantStatusResponse } from './types';
2
2
  export declare function initCascayd(opts: InitOptions): void;
3
3
  export declare function getVariantStatus(experimentId: string, variantId: string): Promise<VariantStatusResponse>;
4
- export declare function assignVariant(experimentId: string): Promise<{
4
+ export declare function assignVariant(experimentId: string, detectedVariants?: string[], route?: string, shop?: string): Promise<{
5
5
  variantId: string;
6
6
  config: ExperimentConfigResponse;
7
7
  }>;
package/dist/client.js CHANGED
@@ -41,7 +41,9 @@ function seededRandom(seed) {
41
41
  return seed / m;
42
42
  }
43
43
  function chooseByWeight(variants, experimentId) {
44
+ console.log('[cascayd-sdk] chooseByWeight called with variants:', variants);
44
45
  const total = variants.reduce((s, v) => s + v.weight, 0);
46
+ console.log('[cascayd-sdk] chooseByWeight total weight:', total);
45
47
  // Create a seed based on current time (milliseconds) and experiment ID
46
48
  // This makes it change over time while being deterministic for the same millisecond
47
49
  const now = Date.now();
@@ -55,19 +57,79 @@ function chooseByWeight(variants, experimentId) {
55
57
  }
56
58
  // Use seeded random instead of Math.random()
57
59
  const r = seededRandom(Math.abs(hash)) * total;
60
+ console.log('[cascayd-sdk] chooseByWeight seed:', seedString, 'hash:', Math.abs(hash), 'random value:', r, 'total:', total);
58
61
  let acc = 0;
59
62
  for (const v of variants) {
60
63
  acc += v.weight;
61
- if (r <= acc)
64
+ console.log('[cascayd-sdk] chooseByWeight checking variant:', v.id, 'weight:', v.weight, 'acc:', acc, 'r <= acc?', r <= acc);
65
+ if (r <= acc) {
66
+ console.log('[cascayd-sdk] chooseByWeight selected:', v.id);
62
67
  return v.id;
68
+ }
63
69
  }
64
- return variants[variants.length - 1]?.id ?? 'control';
70
+ const fallback = variants[variants.length - 1]?.id ?? 'control';
71
+ console.log('[cascayd-sdk] chooseByWeight fallback to:', fallback);
72
+ return fallback;
65
73
  }
66
- export async function assignVariant(experimentId) {
74
+ export async function assignVariant(experimentId, detectedVariants, route, shop) {
67
75
  const baseStatus = await getVariantStatus(experimentId, 'control');
68
- const weights = baseStatus.weights || {};
76
+ let weights = baseStatus.weights || {};
77
+ console.log('[cascayd-sdk] assignVariant weights received:', weights);
78
+ // If we have detected variants, ensure they exist in the database
79
+ if (detectedVariants && detectedVariants.length > 0) {
80
+ // Check if all detected variants exist in weights
81
+ const missingVariants = detectedVariants.filter(vid => !(vid in weights));
82
+ if (missingVariants.length > 0) {
83
+ console.log('[cascayd-sdk] assignVariant: Missing variants detected, ensuring they exist:', missingVariants);
84
+ try {
85
+ // Call ensure endpoint to create missing variants
86
+ const ensureBody = {
87
+ experiment_id: experimentId,
88
+ variant_ids: detectedVariants,
89
+ route: route || (typeof window !== 'undefined' ? window.location.pathname : "/"),
90
+ };
91
+ if (shop) {
92
+ ensureBody.shop = shop;
93
+ }
94
+ const ensureRes = await fetch(`${BASE_URL}/experiments/ensure`, {
95
+ method: 'POST',
96
+ headers: {
97
+ 'Content-Type': 'application/json',
98
+ Authorization: `Bearer ${API_KEY}`,
99
+ },
100
+ body: JSON.stringify(ensureBody),
101
+ });
102
+ if (ensureRes.ok) {
103
+ console.log('[cascayd-sdk] assignVariant: Successfully ensured variants exist');
104
+ // Fetch status again to get updated weights
105
+ const updatedStatus = await getVariantStatus(experimentId, 'control');
106
+ weights = updatedStatus.weights || {};
107
+ console.log('[cascayd-sdk] assignVariant: Updated weights after ensuring:', weights);
108
+ }
109
+ else {
110
+ console.warn('[cascayd-sdk] assignVariant: Failed to ensure variants, using fallback weights');
111
+ }
112
+ }
113
+ catch (error) {
114
+ console.error('[cascayd-sdk] assignVariant: Error ensuring variants:', error);
115
+ }
116
+ }
117
+ }
118
+ // If weights only has control and we have detected variants, use detected variants with equal weights (fallback)
119
+ if (Object.keys(weights).length === 1 && weights.control === 1 && detectedVariants && detectedVariants.length > 1) {
120
+ console.log('[cascayd-sdk] assignVariant: Only control in weights, using detected variants as fallback:', detectedVariants);
121
+ const equalWeight = 1 / detectedVariants.length;
122
+ weights = {};
123
+ detectedVariants.forEach(vid => {
124
+ weights[vid] = equalWeight;
125
+ });
126
+ console.log('[cascayd-sdk] assignVariant: Created equal weights from detected variants:', weights);
127
+ }
128
+ console.log('[cascayd-sdk] assignVariant weights entries:', Object.entries(weights));
69
129
  const variants = Object.entries(weights).map(([id, weight]) => ({ id, weight }));
130
+ console.log('[cascayd-sdk] assignVariant variants array:', variants);
70
131
  let candidate = chooseByWeight(variants.length > 0 ? variants : baseStatusToVariants(baseStatus), experimentId);
132
+ console.log('[cascayd-sdk] assignVariant candidate selected:', candidate);
71
133
  let finalStatus = null;
72
134
  if (candidate) {
73
135
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cascayd/experiment",
3
- "version": "0.3.9",
3
+ "version": "0.3.11",
4
4
  "description": "A lightweight A/B testing SDK for React applications with server-side analytics integration",
5
5
  "keywords": [
6
6
  "ab-testing",