@keak/sdk 1.0.1

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.
Files changed (89) hide show
  1. package/README.md +131 -0
  2. package/dist/Conversion.d.ts +13 -0
  3. package/dist/Conversion.d.ts.map +1 -0
  4. package/dist/KeakToolbarShadow.d.ts +21 -0
  5. package/dist/KeakToolbarShadow.d.ts.map +1 -0
  6. package/dist/components/ui/card.d.ts +9 -0
  7. package/dist/components/ui/card.d.ts.map +1 -0
  8. package/dist/components/ui/html-preview.d.ts +9 -0
  9. package/dist/components/ui/html-preview.d.ts.map +1 -0
  10. package/dist/components/ui/simple-tabs.d.ts +26 -0
  11. package/dist/components/ui/simple-tabs.d.ts.map +1 -0
  12. package/dist/components/ui/spinner.d.ts +6 -0
  13. package/dist/components/ui/spinner.d.ts.map +1 -0
  14. package/dist/components/ui/tabs.d.ts +13 -0
  15. package/dist/components/ui/tabs.d.ts.map +1 -0
  16. package/dist/components/ui/textarea.d.ts +6 -0
  17. package/dist/components/ui/textarea.d.ts.map +1 -0
  18. package/dist/index.cjs.js +17407 -0
  19. package/dist/index.cjs.js.map +1 -0
  20. package/dist/index.d.ts +101 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +17395 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/runtime/sourceInjector.d.ts +2 -0
  25. package/dist/runtime/sourceInjector.d.ts.map +1 -0
  26. package/dist/scripts/sourcePathInjection.d.ts +11 -0
  27. package/dist/scripts/sourcePathInjection.d.ts.map +1 -0
  28. package/dist/services/index.d.ts +7 -0
  29. package/dist/services/index.d.ts.map +1 -0
  30. package/dist/services/telemetry/index.d.ts +20 -0
  31. package/dist/services/telemetry/index.d.ts.map +1 -0
  32. package/dist/services/telemetry/telemetryService.d.ts +66 -0
  33. package/dist/services/telemetry/telemetryService.d.ts.map +1 -0
  34. package/dist/services/telemetry/types.d.ts +64 -0
  35. package/dist/services/telemetry/types.d.ts.map +1 -0
  36. package/dist/toolbar/AIPromptPanel.d.ts +9 -0
  37. package/dist/toolbar/AIPromptPanel.d.ts.map +1 -0
  38. package/dist/toolbar/ElementSelector.d.ts +8 -0
  39. package/dist/toolbar/ElementSelector.d.ts.map +1 -0
  40. package/dist/toolbar/ExperimentPanel.d.ts +9 -0
  41. package/dist/toolbar/ExperimentPanel.d.ts.map +1 -0
  42. package/dist/toolbar/KeakToolbar.d.ts +10 -0
  43. package/dist/toolbar/KeakToolbar.d.ts.map +1 -0
  44. package/dist/toolbar/MetricsPanel.d.ts +7 -0
  45. package/dist/toolbar/MetricsPanel.d.ts.map +1 -0
  46. package/dist/toolbar/PageScanPanel.d.ts +15 -0
  47. package/dist/toolbar/PageScanPanel.d.ts.map +1 -0
  48. package/dist/toolbar/components/PrimaryButton.d.ts +12 -0
  49. package/dist/toolbar/components/PrimaryButton.d.ts.map +1 -0
  50. package/dist/toolbar/components/WarningButton.d.ts +12 -0
  51. package/dist/toolbar/components/WarningButton.d.ts.map +1 -0
  52. package/dist/toolbar/components/icons/index.d.ts +13 -0
  53. package/dist/toolbar/components/icons/index.d.ts.map +1 -0
  54. package/dist/toolbar/components/ui/Badge.d.ts +10 -0
  55. package/dist/toolbar/components/ui/Badge.d.ts.map +1 -0
  56. package/dist/toolbar/components/ui/Button.d.ts +12 -0
  57. package/dist/toolbar/components/ui/Button.d.ts.map +1 -0
  58. package/dist/toolbar/components/ui/Progress.d.ts +5 -0
  59. package/dist/toolbar/components/ui/Progress.d.ts.map +1 -0
  60. package/dist/toolbar/components/ui/Tabs.d.ts +44 -0
  61. package/dist/toolbar/components/ui/Tabs.d.ts.map +1 -0
  62. package/dist/toolbar/components/ui/dropdown-menu.d.ts +28 -0
  63. package/dist/toolbar/components/ui/dropdown-menu.d.ts.map +1 -0
  64. package/dist/toolbar/lib/utils.d.ts +3 -0
  65. package/dist/toolbar/lib/utils.d.ts.map +1 -0
  66. package/dist/toolbar/utils/fiberSource.d.ts +64 -0
  67. package/dist/toolbar/utils/fiberSource.d.ts.map +1 -0
  68. package/dist/toolbar/utils/keakCodeClient.d.ts +104 -0
  69. package/dist/toolbar/utils/keakCodeClient.d.ts.map +1 -0
  70. package/dist/toolbar.css +1 -0
  71. package/dist/toolbar.js +1257 -0
  72. package/dist/toolbar.js.map +1 -0
  73. package/dist/utils/generateElementId.d.ts +44 -0
  74. package/dist/utils/generateElementId.d.ts.map +1 -0
  75. package/dist/utils/injectDataId.d.ts +33 -0
  76. package/dist/utils/injectDataId.d.ts.map +1 -0
  77. package/package.json +152 -0
  78. package/src/cli/ai-helper.js +206 -0
  79. package/src/cli/code-transformer.js +354 -0
  80. package/src/cli/conversion-detector.js +716 -0
  81. package/src/cli/framework-config.js +477 -0
  82. package/src/cli/install.js +618 -0
  83. package/src/cli/keak-setup.js +43 -0
  84. package/src/cli/revert-conversions.js +264 -0
  85. package/src/cli/safe-transformer.js +456 -0
  86. package/src/cli/simple-transformer.js +339 -0
  87. package/src/plugins/README.md +131 -0
  88. package/src/plugins/babel-source-inject.cjs +170 -0
  89. package/src/plugins/next.cjs +145 -0
@@ -0,0 +1,716 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from 'fs';
4
+ import path from 'path';
5
+ import SafeTransformer from './safe-transformer.js';
6
+
7
+ class ConversionDetector {
8
+ constructor() {
9
+ this.codeTransformer = new SafeTransformer();
10
+ this.conversionSelectors = [
11
+ // Button elements
12
+ 'button',
13
+ 'input[type="button"]',
14
+ 'input[type="submit"]',
15
+ '[role="button"]',
16
+
17
+ // Link elements
18
+ 'a[href]',
19
+
20
+ // Common CTA patterns
21
+ '[class*="cta"]',
22
+ '[class*="button"]',
23
+ '[class*="btn"]',
24
+ '[id*="cta"]',
25
+ '[id*="button"]',
26
+ '[id*="btn"]',
27
+
28
+ // Form submit elements
29
+ 'form button',
30
+ 'form input[type="submit"]',
31
+
32
+ // Common conversion text patterns
33
+ '[class*="buy"]',
34
+ '[class*="purchase"]',
35
+ '[class*="checkout"]',
36
+ '[class*="sign-up"]',
37
+ '[class*="signup"]',
38
+ '[class*="subscribe"]',
39
+ '[class*="download"]',
40
+ '[class*="get-started"]',
41
+ '[class*="learn-more"]',
42
+ '[class*="contact"]',
43
+ '[class*="demo"]',
44
+ '[class*="trial"]',
45
+
46
+ // E-commerce specific
47
+ '[class*="add-to-cart"]',
48
+ '[class*="add-cart"]',
49
+ '[class*="cart"]',
50
+ '[class*="wishlist"]',
51
+
52
+ // Navigation that might lead to conversions
53
+ 'nav a',
54
+ 'header a',
55
+ '.navigation a',
56
+ '.menu a'
57
+ ];
58
+
59
+ this.conversionTextPatterns = [
60
+ /buy\s+now/i,
61
+ /get\s+started/i,
62
+ /sign\s+up/i,
63
+ /subscribe/i,
64
+ /download/i,
65
+ /try\s+free/i,
66
+ /free\s+trial/i,
67
+ /learn\s+more/i,
68
+ /contact\s+us/i,
69
+ /request\s+demo/i,
70
+ /book\s+demo/i,
71
+ /add\s+to\s+cart/i,
72
+ /checkout/i,
73
+ /purchase/i,
74
+ /order\s+now/i,
75
+ /join\s+now/i,
76
+ /register/i,
77
+ /apply\s+now/i,
78
+ /get\s+quote/i,
79
+ /call\s+now/i,
80
+ /schedule/i,
81
+ /book\s+now/i
82
+ ];
83
+ }
84
+
85
+ generateConversionScript() {
86
+ return `
87
+ // Keak Conversion Tracking - Auto-generated
88
+ (function() {
89
+ 'use strict';
90
+
91
+ // Configuration
92
+ const CONVERSION_SELECTORS = ${JSON.stringify(this.conversionSelectors, null, 2)};
93
+ const CONVERSION_TEXT_PATTERNS = [
94
+ ${this.conversionTextPatterns.map(pattern =`/${pattern.source}/${pattern.flags}`).join(',\n ')}
95
+ ];
96
+
97
+ // Conversion tracking state
98
+ let trackedElements = new Set();
99
+ let conversionGoals = new Map();
100
+
101
+ // Initialize conversion tracking
102
+ function initConversionTracking() {
103
+ console.log('šŸŽÆ Keak Conversion Tracking initialized');
104
+
105
+ // Tag existing elements
106
+ tagConversionElements();
107
+
108
+ // Set up mutation observer for dynamic content
109
+ observeNewElements();
110
+
111
+ // Set up periodic re-scanning
112
+ setInterval(tagConversionElements, 5000);
113
+
114
+ console.log(\`šŸ“Š Tagged \${trackedElements.size} conversion elements\`);
115
+ }
116
+
117
+ // Main function to detect and tag conversion elements
118
+ function tagConversionElements() {
119
+ const newElements = new Set();
120
+
121
+ // Find elements by selectors
122
+ CONVERSION_SELECTORS.forEach(selector ={
123
+ try {
124
+ const elements = document.querySelectorAll(selector);
125
+ elements.forEach(element ={
126
+ if (!trackedElements.has(element) && isConversionElement(element)) {
127
+ tagElement(element);
128
+ newElements.add(element);
129
+ trackedElements.add(element);
130
+ }
131
+ });
132
+ } catch (e) {
133
+ console.warn('Invalid selector:', selector, e);
134
+ }
135
+ });
136
+
137
+ // Find elements by text content
138
+ const allClickableElements = document.querySelectorAll('a, button, [onclick], [role="button"], input[type="button"], input[type="submit"]');
139
+ allClickableElements.forEach(element ={
140
+ if (!trackedElements.has(element) && hasConversionText(element)) {
141
+ tagElement(element);
142
+ newElements.add(element);
143
+ trackedElements.add(element);
144
+ }
145
+ });
146
+
147
+ if (newElements.size 0) {
148
+ console.log(\`šŸ” Found \${newElements.size} new conversion elements\`);
149
+
150
+ // Show visual indicators
151
+ showConversionIndicators();
152
+ }
153
+ }
154
+
155
+ // Check if element is likely a conversion element
156
+ function isConversionElement(element) {
157
+ // Skip if already tracked
158
+ if (trackedElements.has(element)) return false;
159
+
160
+ // Skip hidden elements
161
+ if (!isElementVisible(element)) return false;
162
+
163
+ // Check if it's clickable
164
+ if (!isClickable(element)) return false;
165
+
166
+ // Check text content
167
+ if (hasConversionText(element)) return true;
168
+
169
+ // Check classes and IDs
170
+ const className = element.className || '';
171
+ const id = element.id || '';
172
+ const combined = (className + ' ' + id).toLowerCase();
173
+
174
+ const conversionKeywords = [
175
+ 'cta', 'button', 'btn', 'buy', 'purchase', 'checkout',
176
+ 'signup', 'sign-up', 'subscribe', 'download', 'trial',
177
+ 'demo', 'contact', 'get-started', 'learn-more', 'cart'
178
+ ];
179
+
180
+ return conversionKeywords.some(keyword =combined.includes(keyword));
181
+ }
182
+
183
+ // Check if element has conversion-related text
184
+ function hasConversionText(element) {
185
+ const text = (element.textContent || element.value || element.alt || element.title || '').toLowerCase();
186
+ return CONVERSION_TEXT_PATTERNS.some(pattern =pattern.test(text));
187
+ }
188
+
189
+ // Check if element is visible
190
+ function isElementVisible(element) {
191
+ const style = window.getComputedStyle(element);
192
+ return style.display !== 'none' &&
193
+ style.visibility !== 'hidden' &&
194
+ style.opacity !== '0' &&
195
+ element.offsetWidth 0 &&
196
+ element.offsetHeight 0;
197
+ }
198
+
199
+ // Check if element is clickable
200
+ function isClickable(element) {
201
+ const clickableTypes = ['a', 'button', 'input'];
202
+ const hasClickableRole = element.getAttribute('role') === 'button';
203
+ const hasClickHandler = element.onclick || element.getAttribute('onclick');
204
+ const isClickableInput = element.type === 'button' || element.type === 'submit';
205
+
206
+ return clickableTypes.includes(element.tagName.toLowerCase()) ||
207
+ hasClickableRole ||
208
+ hasClickHandler ||
209
+ isClickableInput;
210
+ }
211
+
212
+ // Tag an element for conversion tracking
213
+ function tagElement(element) {
214
+ // Add data attributes
215
+ element.setAttribute('data-keak-conversion', 'true');
216
+ element.setAttribute('data-keak-conversion-id', generateConversionId());
217
+ element.setAttribute('data-keak-conversion-type', getConversionType(element));
218
+
219
+ // Add event listener for tracking
220
+ element.addEventListener('click', handleConversionClick, { passive: true });
221
+
222
+ // Add visual indicator class
223
+ element.classList.add('keak-conversion-element');
224
+ }
225
+
226
+ // Generate unique conversion ID
227
+ function generateConversionId() {
228
+ return 'conv_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
229
+ }
230
+
231
+ // Determine conversion type based on element
232
+ function getConversionType(element) {
233
+ const text = (element.textContent || element.value || '').toLowerCase();
234
+ const className = (element.className || '').toLowerCase();
235
+ const id = (element.id || '').toLowerCase();
236
+ const combined = text + ' ' + className + ' ' + id;
237
+
238
+ if (/buy|purchase|checkout|order/.test(combined)) return 'purchase';
239
+ if (/sign.?up|register|join/.test(combined)) return 'signup';
240
+ if (/subscribe/.test(combined)) return 'subscription';
241
+ if (/download/.test(combined)) return 'download';
242
+ if (/demo|trial/.test(combined)) return 'demo';
243
+ if (/contact|call|phone/.test(combined)) return 'contact';
244
+ if (/cart/.test(combined)) return 'add-to-cart';
245
+ if (/learn.?more|read.?more/.test(combined)) return 'engagement';
246
+
247
+ return 'click';
248
+ }
249
+
250
+ // Handle conversion click events
251
+ function handleConversionClick(event) {
252
+ const element = event.currentTarget;
253
+ const conversionId = element.getAttribute('data-keak-conversion-id');
254
+ const conversionType = element.getAttribute('data-keak-conversion-type');
255
+
256
+ // Track the conversion event
257
+ if (window.keak && window.keak.trackEvent) {
258
+ window.keak.trackEvent('conversion', {
259
+ conversionId,
260
+ conversionType,
261
+ elementTag: element.tagName.toLowerCase(),
262
+ elementText: (element.textContent || element.value || '').substring(0, 100),
263
+ elementClass: element.className,
264
+ elementId: element.id,
265
+ href: element.href,
266
+ timestamp: new Date().toISOString(),
267
+ url: window.location.href,
268
+ referrer: document.referrer
269
+ });
270
+
271
+ console.log(\`šŸŽÆ Conversion tracked: \${conversionType}\`, {
272
+ id: conversionId,
273
+ element: element.tagName.toLowerCase(),
274
+ text: element.textContent?.substring(0, 50)
275
+ });
276
+ }
277
+
278
+ // Visual feedback
279
+ showConversionFeedback(element);
280
+ }
281
+
282
+ // Show visual feedback for conversion
283
+ function showConversionFeedback(element) {
284
+ const feedback = document.createElement('div');
285
+ feedback.innerHTML = 'šŸŽÆ';
286
+ feedback.style.cssText = \`
287
+ position: fixed;
288
+ z-index: 999999;
289
+ pointer-events: none;
290
+ font-size: 24px;
291
+ animation: keakConversionPing 0.8s ease-out;
292
+ \`;
293
+
294
+ const rect = element.getBoundingClientRect();
295
+ feedback.style.left = (rect.left + rect.width / 2) + 'px';
296
+ feedback.style.top = (rect.top + rect.height / 2) + 'px';
297
+
298
+ document.body.appendChild(feedback);
299
+
300
+ setTimeout(() => {
301
+ feedback.remove();
302
+ }, 800);
303
+ }
304
+
305
+ // Show visual indicators for all conversion elements
306
+ function showConversionIndicators() {
307
+ // Add CSS for conversion indicators
308
+ if (!document.getElementById('keak-conversion-styles')) {
309
+ const style = document.createElement('style');
310
+ style.id = 'keak-conversion-styles';
311
+ style.textContent = \`
312
+ .keak-conversion-element {
313
+ position: relative !important;
314
+ }
315
+
316
+ .keak-conversion-element::after {
317
+ content: 'šŸŽÆ';
318
+ position: absolute !important;
319
+ top: -8px !important;
320
+ right: -8px !important;
321
+ width: 20px !important;
322
+ height: 20px !important;
323
+ background: #ff6b35 !important;
324
+ border-radius: 50% !important;
325
+ display: flex !important;
326
+ align-items: center !important;
327
+ justify-content: center !important;
328
+ font-size: 10px !important;
329
+ z-index: 999998 !important;
330
+ animation: keakConversionBadge 2s infinite !important;
331
+ pointer-events: none !important;
332
+ border: 2px solid white !important;
333
+ box-shadow: 0 2px 4px rgba(0,0,0,0.2) !important;
334
+ }
335
+
336
+ .keak-conversion-element:hover::after {
337
+ animation: keakConversionHover 0.3s ease !important;
338
+ }
339
+
340
+ @keyframes keakConversionBadge {
341
+ 0% { transform: scale(1); opacity: 1; }
342
+ 50% { transform: scale(1.1); opacity: 0.8; }
343
+ 100% { transform: scale(1); opacity: 1; }
344
+ }
345
+
346
+ @keyframes keakConversionHover {
347
+ 0% { transform: scale(1); }
348
+ 50% { transform: scale(1.3); }
349
+ 100% { transform: scale(1.1); }
350
+ }
351
+
352
+ @keyframes keakConversionPing {
353
+ 0% {
354
+ transform: scale(1) translate(-50%, -50%);
355
+ opacity: 1;
356
+ }
357
+ 100% {
358
+ transform: scale(2) translate(-50%, -50%);
359
+ opacity: 0;
360
+ }
361
+ }
362
+
363
+ .keak-conversion-summary {
364
+ position: fixed !important;
365
+ top: 20px !important;
366
+ right: 20px !important;
367
+ background: #2d3748 !important;
368
+ color: white !important;
369
+ padding: 12px 16px !important;
370
+ border-radius: 8px !important;
371
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
372
+ font-size: 14px !important;
373
+ z-index: 999999 !important;
374
+ box-shadow: 0 4px 12px rgba(0,0,0,0.3) !important;
375
+ border: 1px solid #4a5568 !important;
376
+ }
377
+
378
+ .keak-conversion-summary h4 {
379
+ margin: 0 0 8px 0 !important;
380
+ font-size: 16px !important;
381
+ font-weight: 600 !important;
382
+ }
383
+
384
+ .keak-conversion-summary ul {
385
+ margin: 0 !important;
386
+ padding: 0 !important;
387
+ list-style: none !important;
388
+ }
389
+
390
+ .keak-conversion-summary li {
391
+ margin: 4px 0 !important;
392
+ font-size: 12px !important;
393
+ opacity: 0.9 !important;
394
+ }
395
+ \`;
396
+ document.head.appendChild(style);
397
+ }
398
+
399
+ // Show summary
400
+ showConversionSummary();
401
+ }
402
+
403
+ // Show conversion tracking summary
404
+ function showConversionSummary() {
405
+ const existingSummary = document.getElementById('keak-conversion-summary');
406
+ if (existingSummary) {
407
+ existingSummary.remove();
408
+ }
409
+
410
+ const typeCount = {};
411
+ trackedElements.forEach(element ={
412
+ const type = element.getAttribute('data-keak-conversion-type');
413
+ typeCount[type] = (typeCount[type] || 0) + 1;
414
+ });
415
+
416
+ const summary = document.createElement('div');
417
+ summary.id = 'keak-conversion-summary';
418
+ summary.className = 'keak-conversion-summary';
419
+ summary.innerHTML = \`
420
+ <h4šŸŽÆ Conversion Tracking Active</h4<div\${trackedElements.size} elements tagged</div<ul\${Object.entries(typeCount).map(([type, count]) =\`<li\${type}: \${count}</li\`
421
+ ).join('')}
422
+ </ul\`;
423
+
424
+ document.body.appendChild(summary);
425
+
426
+ // Auto-hide after 10 seconds
427
+ setTimeout(() => {
428
+ if (summary.parentNode) {
429
+ summary.style.transition = 'opacity 0.5s';
430
+ summary.style.opacity = '0';
431
+ setTimeout(() =summary.remove(), 500);
432
+ }
433
+ }, 10000);
434
+ }
435
+
436
+ // Observe for new elements (dynamic content)
437
+ function observeNewElements() {
438
+ const observer = new MutationObserver((mutations) => {
439
+ let hasNewElements = false;
440
+
441
+ mutations.forEach((mutation) => {
442
+ if (mutation.type === 'childList') {
443
+ mutation.addedNodes.forEach((node) => {
444
+ if (node.nodeType === Node.ELEMENT_NODE) {
445
+ hasNewElements = true;
446
+ }
447
+ });
448
+ }
449
+ });
450
+
451
+ if (hasNewElements) {
452
+ // Debounce the tagging
453
+ clearTimeout(window.keakTaggingTimeout);
454
+ window.keakTaggingTimeout = setTimeout(tagConversionElements, 1000);
455
+ }
456
+ });
457
+
458
+ observer.observe(document.body, {
459
+ childList: true,
460
+ subtree: true
461
+ });
462
+ }
463
+
464
+ // Public API for manual control
465
+ window.keakConversions = {
466
+ scan: tagConversionElements,
467
+ show: showConversionIndicators,
468
+ hide: () => {
469
+ document.querySelectorAll('.keak-conversion-element').forEach(el ={
470
+ el.classList.remove('keak-conversion-element');
471
+ });
472
+ const summary = document.getElementById('keak-conversion-summary');
473
+ if (summary) summary.remove();
474
+ },
475
+ getTracked: () =Array.from(trackedElements),
476
+ getStats: () => {
477
+ const typeCount = {};
478
+ trackedElements.forEach(element ={
479
+ const type = element.getAttribute('data-keak-conversion-type');
480
+ typeCount[type] = (typeCount[type] || 0) + 1;
481
+ });
482
+ return { total: trackedElements.size, byType: typeCount };
483
+ }
484
+ };
485
+
486
+ // Initialize when DOM is ready
487
+ if (document.readyState === 'loading') {
488
+ document.addEventListener('DOMContentLoaded', initConversionTracking);
489
+ } else {
490
+ initConversionTracking();
491
+ }
492
+
493
+ // Also initialize after a short delay to catch any late-loading content
494
+ setTimeout(initConversionTracking, 2000);
495
+
496
+ })();
497
+ `;
498
+ }
499
+
500
+ generateResultsHTML(report, results) {
501
+ const modifiedFiles = results.filter(r => r.success && r.modified);
502
+ const errors = results.filter(r => !r.success);
503
+
504
+ return `<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Keak Conversion Tracking Setup Complete</title><style>body {
505
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
506
+ max-width: 800px;
507
+ margin: 0 auto;
508
+ padding: 20px;
509
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
510
+ color: #333;
511
+ min-height: 100vh;
512
+ }
513
+
514
+ .container {
515
+ background: white;
516
+ border-radius: 12px;
517
+ padding: 40px;
518
+ box-shadow: 0 20px 40px rgba(0,0,0,0.1);
519
+ }
520
+
521
+ .header {
522
+ text-align: center;
523
+ margin-bottom: 40px;
524
+ }
525
+
526
+ .logo {
527
+ font-size: 48px;
528
+ margin-bottom: 16px;
529
+ }
530
+
531
+ h1 {
532
+ color: #2d3748;
533
+ margin-bottom: 8px;
534
+ font-size: 28px;
535
+ }
536
+
537
+ .subtitle {
538
+ color: #718096;
539
+ font-size: 18px;
540
+ }
541
+
542
+ .feature-grid {
543
+ display: grid;
544
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
545
+ gap: 20px;
546
+ margin: 40px 0;
547
+ }
548
+
549
+ .feature {
550
+ padding: 20px;
551
+ border: 1px solid #e2e8f0;
552
+ border-radius: 8px;
553
+ background: #f7fafc;
554
+ }
555
+
556
+ .feature h3 {
557
+ color: #2d3748;
558
+ margin-bottom: 8px;
559
+ display: flex;
560
+ align-items: center;
561
+ gap: 8px;
562
+ }
563
+
564
+ .instructions {
565
+ background: #edf2f7;
566
+ padding: 24px;
567
+ border-radius: 8px;
568
+ margin: 20px 0;
569
+ }
570
+
571
+ .code {
572
+ background: #2d3748;
573
+ color: #e2e8f0;
574
+ padding: 16px;
575
+ border-radius: 8px;
576
+ font-family: 'SF Mono', Monaco, monospace;
577
+ margin: 16px 0;
578
+ overflow-x: auto;
579
+ }
580
+
581
+ .success {
582
+ background: #f0fff4;
583
+ border: 1px solid #9ae6b4;
584
+ color: #22543d;
585
+ padding: 16px;
586
+ border-radius: 8px;
587
+ margin: 20px 0;
588
+ }
589
+
590
+ .button {
591
+ background: #4299e1;
592
+ color: white;
593
+ border: none;
594
+ padding: 12px 24px;
595
+ border-radius: 8px;
596
+ font-size: 16px;
597
+ cursor: pointer;
598
+ transition: background 0.2s;
599
+ }
600
+
601
+ .button:hover {
602
+ background: #3182ce;
603
+ }
604
+
605
+ .status {
606
+ font-weight: 600;
607
+ color: #38a169;
608
+ }
609
+
610
+ .stats, .modified-files, .errors {
611
+ background: #f7fafc;
612
+ padding: 20px;
613
+ border-radius: 8px;
614
+ margin: 20px 0;
615
+ border-left: 4px solid #4299e1;
616
+ }
617
+
618
+ .errors {
619
+ border-left-color: #f56565;
620
+ background: #fed7d7;
621
+ }
622
+
623
+ .stats ul, .modified-files ul, .errors ul {
624
+ margin: 8px 0;
625
+ padding-left: 20px;
626
+ }
627
+
628
+ .stats li, .modified-files li, .errors li {
629
+ margin: 4px 0;
630
+ }
631
+
632
+ .backup {
633
+ color: #718096;
634
+ font-size: 12px;
635
+ }
636
+ </style></head><body><div class="container"><div class="header"><div class="logo">šŸŽÆ</div><h1>Conversion Tracking Setup Complete</h1><p class="subtitle">Your React components have been automatically wrapped with conversion tracking</p></div><div class="success"><strong>āœ… Success!</strong>Conversion tracking has been integrated into your codebase.
637
+ All clickable elements are now wrapped with &lt;Conversion&gt; components for automatic telemetry.
638
+ </div><div class="stats"><h3>šŸ“Š Transformation Results</h3><ul><li><strong>Files processed:</strong> ${report.stats.filesProcessed}</li><li><strong>Files modified:</strong> ${report.stats.filesModified}</li><li><strong>Elements wrapped:</strong> ${report.stats.elementsWrapped}</li></ul></div>${modifiedFiles.length > 0 ? `
639
+ <div class="modified-files"><h3>šŸ“ Modified Files</h3><ul>${modifiedFiles.map(file => `
640
+ <li><code>${path.basename(file.filePath)}</code>${file.backup ? ` <span class="backup">(backup: ${path.basename(file.backup)})</span>` : ''}
641
+ </li>`).join('')}
642
+ </ul></div>` : ''}
643
+
644
+ ${errors.length > 0 ? `
645
+ <div class="errors"><h3>āš ļø Issues Found</h3><ul>${errors.map(error => `
646
+ <li><code>${path.basename(error.filePath)}</code>: ${error.error}</li>`).join('')}
647
+ </ul></div>` : ''}
648
+
649
+ <div class="feature-grid"><div class="feature"><h3>šŸ” Auto-Detection</h3><p>Automatically finds buttons, CTAs, forms, and links that could be conversion points</p></div><div class="feature"><h3>šŸŽÆ Smart Tagging</h3><p>Uses AI-powered patterns to identify conversion-worthy elements based on text and context</p></div><div class="feature"><h3>šŸ“Š Real-time Tracking</h3><p>Tracks conversion events in real-time and sends data to your Keak dashboard</p></div><div class="feature"><h3>šŸ‘ļø Visual Indicators</h3><p>Shows small badges on tracked elements so you can see what's being monitored</p></div></div><div class="instructions"><h3>How to use:</h3><ol><li><strong>Automatic:</strong> The tracking script is already running and detecting elements</li><li><strong>Manual control:</strong> Use the browser console commands for manual control</li><li><strong>View tracked elements:</strong> Look for šŸŽÆ badges on your conversion elements</li><li><strong>Analytics:</strong> Check your Keak dashboard for conversion data</li></ol></div><div class="instructions"><h3>Browser Console Commands:</h3><div class="code">// View tracking statistics
650
+ keakConversions.getStats()
651
+
652
+ // Manually scan for new elements
653
+ keakConversions.scan()
654
+
655
+ // Show/hide visual indicators
656
+ keakConversions.show()
657
+ keakConversions.hide()
658
+
659
+ // Get all tracked elements
660
+ keakConversions.getTracked()
661
+ </div></div><div style="text-align: center; margin-top: 40px;"><p class="status">Conversion tracking is now active! šŸš€</p><p>Visit your website to see the conversion elements highlighted with šŸŽÆ badges.</p></div></div></body></html>`;
662
+ }
663
+
664
+ createConversionFiles(targetDir) {
665
+ try {
666
+ console.log(`šŸ” Scanning for React files in ${targetDir}...`);
667
+
668
+ // Use code transformer to automatically wrap elements
669
+ const results = this.codeTransformer.processDirectory(targetDir);
670
+ const report = this.codeTransformer.generateReport();
671
+
672
+ // Create a success page with results
673
+ const htmlPath = path.join(targetDir, 'conversion-setup-complete.html');
674
+ fs.writeFileSync(htmlPath, this.generateResultsHTML(report, results));
675
+
676
+ // Show any errors
677
+ const errors = results.filter(r => !r.success);
678
+
679
+ return {
680
+ htmlPath,
681
+ success: true,
682
+ results,
683
+ report,
684
+ errors
685
+ };
686
+ } catch (error) {
687
+ console.error('Error setting up conversion tracking:', error);
688
+ return { success: false, error: error.message };
689
+ }
690
+ }
691
+ }
692
+
693
+ export default ConversionDetector;
694
+
695
+ // CLI execution
696
+ if (import.meta.url === `file://${process.argv[1]}`) {
697
+ const detector = new ConversionDetector();
698
+ const targetDir = process.argv[2] || process.cwd();
699
+
700
+ console.log('šŸŽÆ Setting up conversion tracking...');
701
+
702
+ const result = detector.createConversionFiles(targetDir);
703
+
704
+ if (result.success) {
705
+ console.log('āœ… Conversion tracking files created successfully!');
706
+ console.log('šŸ“„ Script:', result.scriptPath);
707
+ console.log('🌐 Setup page:', result.htmlPath);
708
+ console.log('\nšŸ”§ Next steps:');
709
+ console.log('1. Add the script to your website');
710
+ console.log('2. The system will automatically detect conversion elements');
711
+ console.log('3. Check the setup page for more details');
712
+ } else {
713
+ console.error('āŒ Failed to create conversion files:', result.error);
714
+ process.exit(1);
715
+ }
716
+ }