@cascayd/experiment 0.3.16 → 0.3.18

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.
@@ -57,9 +57,15 @@
57
57
  // Try to get API key from window (if SDK was initialized)
58
58
  function getAPIKey() {
59
59
  if (typeof window !== 'undefined' && window._cascaydAPIKey) {
60
+ console.log('[cascayd-shopify] ✅ Found API key from window._cascaydAPIKey');
60
61
  return window._cascaydAPIKey;
61
62
  }
62
- return API_KEY;
63
+ if (API_KEY) {
64
+ console.log('[cascayd-shopify] ✅ Found API key from local variable');
65
+ return API_KEY;
66
+ }
67
+ console.warn('[cascayd-shopify] ⚠️ No API key found! window._cascaydAPIKey =', typeof window !== 'undefined' ? window._cascaydAPIKey : 'N/A');
68
+ return '';
63
69
  }
64
70
 
65
71
  // Direct API call functions (same logic as SDK)
@@ -151,6 +157,8 @@
151
157
  const variantId = opts.variantId || fromCookie;
152
158
  if (variantId) {
153
159
  body.variant_id = variantId;
160
+ } else {
161
+ console.warn('[cascayd-shopify] ⚠️ No variant_id available for experiment:', opts.experimentId);
154
162
  }
155
163
  }
156
164
 
@@ -158,22 +166,51 @@
158
166
  body.value = opts.value;
159
167
  }
160
168
 
169
+ // Auto-capture route if not provided
170
+ if (opts.route) {
171
+ body.route = opts.route;
172
+ } else if (typeof window !== 'undefined' && window.location) {
173
+ body.route = window.location.pathname;
174
+ }
175
+
176
+ // Validate required fields
177
+ if (!body.experiment_id || !body.variant_id) {
178
+ const error = new Error('Missing required fields: experiment_id=' + body.experiment_id + ', variant_id=' + body.variant_id);
179
+ console.error('[cascayd-shopify] ❌', error.message, 'Body:', body);
180
+ throw error;
181
+ }
182
+
161
183
  const headers = {
162
184
  'Content-Type': 'application/json'
163
185
  };
164
186
  const apiKey = getAPIKey();
165
187
  if (apiKey) {
166
188
  headers.Authorization = 'Bearer ' + apiKey;
189
+ } else {
190
+ console.warn('[cascayd-shopify] ⚠️ No API key found! Check window._cascaydAPIKey');
167
191
  }
168
192
 
169
- const res = await fetch(BASE_URL + '/events', {
170
- method: 'POST',
171
- headers: headers,
172
- body: JSON.stringify(body)
173
- });
193
+ console.log('[cascayd-shopify] 📤 Sending event:', { type: type, body: body, hasApiKey: !!apiKey });
194
+
195
+ try {
196
+ const res = await fetch(BASE_URL + '/events', {
197
+ method: 'POST',
198
+ headers: headers,
199
+ body: JSON.stringify(body)
200
+ });
201
+
202
+ if (!res.ok) {
203
+ const errorText = await res.text();
204
+ console.error('[cascayd-shopify] ❌ API error response:', res.status, errorText);
205
+ throw new Error('Record failed: ' + res.status + ' - ' + errorText);
206
+ }
174
207
 
175
- if (!res.ok) {
176
- throw new Error('Record failed: ' + res.status);
208
+ const result = await res.json();
209
+ console.log('[cascayd-shopify] ✅ Event recorded successfully:', result);
210
+ return result;
211
+ } catch (error) {
212
+ console.error('[cascayd-shopify] ❌ Fetch error:', error);
213
+ throw error;
177
214
  }
178
215
  }
179
216
 
@@ -267,6 +304,77 @@
267
304
  }
268
305
  }
269
306
 
307
+ // Find variant ID from element (with DOM fallback)
308
+ function findVariantIdFromElement(el, experimentId) {
309
+ // First try cookie (most reliable)
310
+ const fromCookie = readVariantChoice(experimentId);
311
+ if (fromCookie) {
312
+ console.log('[cascayd-shopify] 📖 Found variant from cookie:', fromCookie);
313
+ return fromCookie;
314
+ }
315
+
316
+ // Fallback: traverse up DOM to find parent with data-cascayd-variant
317
+ console.log('[cascayd-shopify] 🔍 Cookie not found, traversing DOM for variant ID...');
318
+ let current = el;
319
+ while (current) {
320
+ const variantId = current.getAttribute('data-cascayd-variant');
321
+ if (variantId) {
322
+ console.log('[cascayd-shopify] ✅ Found variant ID in DOM:', variantId);
323
+ return variantId;
324
+ }
325
+
326
+ // Check if we're inside an experiment container
327
+ const experimentIdAttr = current.getAttribute('data-cascayd-experiment');
328
+ if (experimentIdAttr === experimentId) {
329
+ // We're in the right experiment container, continue up
330
+ current = current.parentElement;
331
+ } else {
332
+ // Move up to find experiment container
333
+ current = current.parentElement;
334
+ }
335
+ }
336
+
337
+ console.warn('[cascayd-shopify] ⚠️ No variant ID found for experiment:', experimentId);
338
+ return null;
339
+ }
340
+
341
+ // Setup conversion tracking for an experiment
342
+ function setupConversionTracking(experimentId) {
343
+ const selector = '[data-cascayd-experiment="' + experimentId + '"] [data-cascayd-conversion]';
344
+ const elements = document.querySelectorAll(selector);
345
+ console.log('[cascayd-shopify] 🎯 Setting up conversion tracking for experiment:', experimentId, 'found', elements.length, 'conversion elements');
346
+
347
+ elements.forEach(function(el) {
348
+ // Skip if already tracked
349
+ if (el.hasAttribute('data-cascayd-tracked')) {
350
+ console.log('[cascayd-shopify] ⏭️ Element already tracked, skipping');
351
+ return;
352
+ }
353
+
354
+ el.setAttribute('data-cascayd-tracked', 'true');
355
+ console.log('[cascayd-shopify] ✅ Marked element as tracked:', el);
356
+
357
+ el.addEventListener('click', function(e) {
358
+ console.log('[cascayd-shopify] 🎯 Conversion click detected!');
359
+ const variantId = findVariantIdFromElement(el, experimentId);
360
+ if (variantId) {
361
+ console.log('[cascayd-shopify] 📊 Recording conversion:', { experimentId, variantId });
362
+ // Use direct API call since we're in standalone mode
363
+ recordDirect('conversion', {
364
+ experimentId: experimentId,
365
+ variantId: variantId
366
+ }).then(function() {
367
+ console.log('[cascayd-shopify] ✅ Conversion recorded successfully');
368
+ }).catch(function(error) {
369
+ console.error('[cascayd-shopify] ❌ Failed to record conversion:', error);
370
+ });
371
+ } else {
372
+ console.warn('[cascayd-shopify] ⚠️ No variant found for experiment', experimentId, 'when recording conversion');
373
+ }
374
+ });
375
+ });
376
+ }
377
+
270
378
  // Process a single experiment
271
379
  async function processExperiment(experimentId, variantElements, sdk) {
272
380
  console.log('[cascayd-shopify] 🔬 Processing experiment:', { experimentId, variantElementCount: variantElements.length, hasSDK: !!sdk });
@@ -340,6 +448,9 @@
340
448
  el.classList.remove('cascayd-visible', 'cascayd-visible-inline');
341
449
  }
342
450
  });
451
+
452
+ // Setup conversion tracking after variant is shown
453
+ setupConversionTracking(experimentId);
343
454
  console.log('[cascayd-shopify] ✅ Finished processing experiment:', experimentId);
344
455
  }
345
456
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cascayd/experiment",
3
- "version": "0.3.16",
3
+ "version": "0.3.18",
4
4
  "description": "A lightweight A/B testing SDK for React applications with server-side analytics integration",
5
5
  "keywords": [
6
6
  "ab-testing",